import type { BasePersonProvider, Models } from "@nontara/server";
import { createLogger, ExtensionError } from "@nontara/server";
import type { ConsolaInstance } from "consola";
import type { TMDB } from "tmdb-ts";
import { createTMDBClient } from "../shared/client";
import type { TMDBProviderConfig } from "../shared/types";

export class TMDBPersonProvider implements BasePersonProvider {
	private logger: ConsolaInstance;
	private client: TMDB | null = null;

	constructor(_config?: TMDBProviderConfig) {
		this.logger = createLogger("TMDBPersonProvider");
	}

	/**
	 * Mount/initialize the provider
	 */
	async mount(): Promise<void> {
		this.logger.debug("Mounting person provider");
	}

	/**
	 * Dispose/cleanup the provider
	 */
	async dispose(): Promise<void> {
		this.logger.debug("Disposing person provider");
		this.client = null;
	}

	/**
	 * Initialize TMDB client
	 * Called internally before making API requests
	 */
	private async ensureClient(): Promise<TMDB> {
		if (!this.client) {
			this.client = await createTMDBClient();
			if (!this.client) {
				throw new ExtensionError("TMDB client not available");
			}
		}
		return this.client;
	}

	async search(query: { name: string }): Promise<Models.MetadataSearchResult> {
		try {
			const client = await this.ensureClient();
			const response = await client.search.people({
				query: query.name,
			});

			const results: Models.MetadataSearchResultItem[] = [];

			if (response.results) {
				for (const person of response.results) {
					results.push({
						id: person.id,
						name: person.name,
						knownForDepartment: person.known_for_department || "",
						profilePath: person.profile_path,
						popularity: person.popularity || 0,
						adult: person.adult || false,
						knownFor: person.known_for || [],
						overview: "",
						voteAverage: 0,
						voteCount: 0,
						originalLanguage: "",
						genreIds: [],
						mediaType: "person",
					});
				}
			}

			// Sort by popularity (descending)
			results.sort((a, b) => b.popularity - a.popularity);

			return { results };
		} catch (error) {
			this.logger.error("Error searching people:", error);
			throw new ExtensionError(`TMDB person search failed: ${error}`);
		}
	}

	async resolve(info: Models.PersonInfo): Promise<Models.ResolvedPersonResult> {
		try {
			const client = await this.ensureClient();
			const personDetails = await client.people.details(info.personId);

			return {
				id: personDetails.id,
				name: personDetails.name,
				biography: personDetails.biography || "",
				birthday: personDetails.birthday || null,
				deathday: personDetails.deathday || null,
				placeOfBirth: personDetails.place_of_birth || null,
				profilePath: personDetails.profile_path
					? `https://image.tmdb.org/t/p/w500${personDetails.profile_path}`
					: null,
				knownForDepartment: personDetails.known_for_department || "",
				popularity: personDetails.popularity || 0,
				imdbId: personDetails.imdb_id || null,
				homepage: personDetails.homepage || null,
			};
		} catch (error) {
			this.logger.error("Error resolving person:", error);
			throw new ExtensionError(`TMDB person resolution failed: ${error}`);
		}
	}
}
