import { MovieTicket } from "@autoplex/database";
import { IpcClient as PlexIpc } from "@autoplex-api/plex";
import { IMovie, IMovieDetails, IPaginatedResponse } from "@autoplex-api/request";
import { IpcClient as SearchIpc } from "@autoplex-api/search";
import { InternalService } from "@autoplex/microservice";
import Application from "../Application";

export default class MovieSearch extends InternalService<Application>
{
	/**
	 * The name of the service
	 */
	public readonly NAME = "Movie Search";

	/**
	 * The Plex IPC interface
	 */
	protected plex!: PlexIpc;

	/**
	 * A reference to The Movie DB API
	 */
	protected searchIpc!: SearchIpc;

	/**
	 * Start the service
	 */
	public start() {
		this.plex = this.app.service<PlexIpc>("Plex");
		this.searchIpc = this.app.service<SearchIpc>("Search");
	}

	// Interface -----------------------------------------------------------------------------------

	/**
	 * Get the details of a movie
	 */
	public async details(tmdbId: number) {
		let [ movie, plexLinks, ticket ] = await Promise.all([
			this.searchIpc.movieDetails(tmdbId),
			this.plex.movieLinks([tmdbId]),
			MovieTicket.findOne({
				where: { tmdbId: tmdbId, isCanceled: false },
				relations: ["user"]
			})
		]);
		return <IMovieDetails>Object.assign(movie, {
			plexLink: plexLinks[tmdbId],
			ticketId    : ticket?.id ?? null,
			requestedBy : (ticket ? {
				id     : ticket.user.id,
				isAdmin: ticket.user.isAdmin,
				name   : ticket.user.name
			} : null)
		});
	}

	/**
	 * Find a movie by its IMDb ID
	 */
	public async findImdb(imdbId: string) {
		return await this.searchIpc.findMovieFromImdb(imdbId);
	}

	/**
	 * Search for a movie
	 */
	public async search(query: string, year?: number) {
		this.log("Searching for John Wick...");
		let [ movies, ticketMap ] = await Promise.all([
			this.searchIpc.searchMovie(query, year),
			MovieTicket.activeTicketMap()
		]);
		let plexLinks = await this.plex.movieLinks(movies.results.map(movie => movie.tmdbId));
		return <IPaginatedResponse<IMovie>["result"]>{
			page: movies.page,
			results: movies.results.map(movie => <IMovie>{
				...movie,
				plexLink: plexLinks[movie.tmdbId],
				ticketId: ticketMap[movie.tmdbId] ?? null
			}),
			totalPages: movies.totalPages,
			totalResults: movies.totalResults
		};
	}
}
