import { API_URL } from '$lib/constants/config';

export class ApiError extends Error {
	constructor(
		public status: number,
		message: string
	) {
		super(message);
		this.name = 'ApiError';
	}
}

export class ApiClient {
	private baseUrl: string;
	public online: boolean = true;

	constructor(baseUrl: string = API_URL) {
		this.baseUrl = baseUrl;
	}

	async request<T = any>(endpoint: string, options: RequestInit = {}): Promise<T | null> {
		try {
			const response = await fetch(`${this.baseUrl}${endpoint}`, {
				credentials: 'include',
				...options,
				headers: {
					'Content-Type': 'application/json',
					...options.headers
				}
			});

			this.online = true;

			if (!response.ok) {
				const error = await response.json().catch(() => ({ error: 'Unknown error' }));
				throw new ApiError(response.status, error.error || 'Request failed');
			}

			// Handle empty responses
			const text = await response.text();
			return text ? JSON.parse(text) : null;
		} catch (error) {
			if (error instanceof ApiError) throw error;
			this.online = false;
			throw new ApiError(0, error instanceof Error ? error.message : 'Network error');
		}
	}

	// Auth endpoints
	async logout() {
		return this.request('/auth/logout', { method: 'POST' });
	}

	// User endpoints
	async getMe() {
		return this.request('/me');
	}

	async updateMe(data: { name?: string; showLastPixel?: boolean; discord?: string }) {
		return this.request('/me/update', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async getProfilePictures() {
		return this.request('/me/profile-pictures');
	}

	// Pixel endpoints
	async getRandomTile(season: string) {
		return this.request(`/${season}/tile/random`);
	}

	async getPixelInfo(season: string, tileX: number, tileY: number, x: number, y: number) {
		return this.request(`/${season}/pixel/${tileX}/${tileY}?x=${x}&y=${y}`);
	}

	async paintPixels(
		season: string,
		tileX: number,
		tileY: number,
		data: { colors: number[]; coords: number[] }
	) {
		return this.request(`/${season}/pixel/${tileX}/${tileY}`, {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	getTileImageUrl(season: string, tileX: number, tileY: number): string {
		return `${this.baseUrl}/files/${season}/tiles/${tileX}/${tileY}.png`;
	}

	// Alliance endpoints
	async getAlliance() {
		return this.request('/alliance');
	}

	async createAlliance(name: string) {
		return this.request('/alliance', {
			method: 'POST',
			body: JSON.stringify({ name })
		});
	}

	async updateAllianceDescription(description: string) {
		return this.request('/alliance/update-description', {
			method: 'POST',
			body: JSON.stringify({ description })
		});
	}

	async updateAllianceHeadquarters(latitude: number, longitude: number) {
		return this.request('/alliance/update-headquarters', {
			method: 'POST',
			body: JSON.stringify({ latitude, longitude })
		});
	}

	async getAllianceInvites() {
		return this.request('/alliance/invites');
	}

	async joinAlliance(inviteCode: string) {
		return this.request(`/alliance/join/${inviteCode}`);
	}

	async getAllianceMembers(page: number) {
		return this.request(`/alliance/members/${page}`);
	}

	async getBannedMembers(page: number) {
		return this.request(`/alliance/members/banned/${page}`);
	}

	async promoteUser(promotedUserId: number) {
		return this.request('/alliance/give-admin', {
			method: 'POST',
			body: JSON.stringify({ promotedUserId })
		});
	}

	async banUser(bannedUserId: number) {
		return this.request('/alliance/ban', {
			method: 'POST',
			body: JSON.stringify({ bannedUserId })
		});
	}

	async unbanUser(unbannedUserId: number) {
		return this.request('/alliance/unban', {
			method: 'POST',
			body: JSON.stringify({ unbannedUserId })
		});
	}

	async getAllianceLeaderboard(mode: string) {
		return this.request(`/alliance/leaderboard/${mode}`);
	}

	// Leaderboard endpoints
	async getPlayerLeaderboard(mode: string) {
		return this.request(`/leaderboard/player/${mode}`);
	}

	async getAllianceLeaderboardGlobal(mode: string) {
		return this.request(`/leaderboard/alliance/${mode}`);
	}

	async getCountryLeaderboard(mode: string) {
		return this.request(`/leaderboard/country/${mode}`);
	}

	async getRegionLeaderboard(mode: string, country: string) {
		return this.request(`/leaderboard/region/${mode}/${country}`);
	}

	// Store endpoints
	async purchase(product: { id: number; amount?: number; variant?: number }) {
		return this.request('/purchase', {
			method: 'POST',
			body: JSON.stringify({ product })
		});
	}

	async equipFlag(flagId: number) {
		return this.request(`/flag/equip/${flagId}`, { method: 'POST' });
	}

	// Favorite locations
	async addFavoriteLocation(data: { name: string; latitude: number; longitude: number }) {
		return this.request('/favorite-location', {
			method: 'POST',
			body: JSON.stringify(data)
		});
	}

	async updateFavoriteLocation(
		id: number,
		data: { name: string; latitude: number; longitude: number }
	) {
		return this.request('/favorite-location/update', {
			method: 'POST',
			body: JSON.stringify({ id, ...data })
		});
	}

	// Moderation endpoints
	async getModeratorTickets() {
		return this.request('/moderator/tickets');
	}

	async getSevereTicketsCount() {
		return this.request('/moderator/severe-open-tickets-count', { method: 'POST' });
	}

	async getOpenTicketsCount() {
		return this.request('/moderator/open-tickets-count');
	}

	// Admin endpoints
	async getUser(id: number) {
		return this.request(`/admin/users?id=${id}`);
	}

	async getUserNotes(userId: number) {
		return this.request(`/admin/users/notes?userId=${userId}`);
	}

	async addUserNote(userId: number, note: string) {
		return this.request('/admin/users/notes', {
			method: 'POST',
			body: JSON.stringify({ userId, note })
		});
	}

	async setUserDroplets(userId: number, droplets: number) {
		return this.request('/admin/users/set-user-droplets', {
			method: 'POST',
			body: JSON.stringify({ userId, droplets })
		});
	}

	async getAdminTickets() {
		return this.request('/admin/tickets');
	}

	async getClosedTickets() {
		return this.request('/admin/closed-tickets');
	}

	async getOpenTicketsCountAdmin() {
		return this.request('/admin/open-tickets-count');
	}

	async countAllTickets() {
		return this.request('/admin/count-all-tickets');
	}

	async searchAlliances(query: string) {
		return this.request(`/admin/alliances/search?q=${encodeURIComponent(query)}`);
	}

	async getAllianceById(id: number) {
		return this.request(`/admin/alliances/${id}`);
	}

	async getAllianceByIdFull(id: number) {
		return this.request(`/admin/alliances/${id}/full`);
	}
}

// Export singleton instance
export const api = new ApiClient();
