'use strict';

const knex = require('./knex');

function curateRelease(release, withMedia = false) {
	if (!release) {
		return null;
	}

	const network = release.site_network || release.network;

	return {
		id: release.id,
		entryId: release.entry_id,
		shootId: release.shoot_id,
		title: release.title,
		url: release.url,
		date: release.date,
		description: release.description,
		duration: release.duration,
		site: release.site && {
			id: release.site.id,
			name: release.site.name,
			slug: release.site.slug,
		},
		network: network && {
			id: network.id,
			name: network.name,
			slug: network.slug,
		},
		actors: (release.actors || []).map(actor => ({
			id: actor.id,
			name: actor.name,
			slug: actor.slug,
			gender: actor.gender,
			networkId: actor.network_id,
			aliasFor: actor.alias_for,
			dateOfBirth: actor.date_of_birth,
			birthCountry: actor.birth_country_alpha2,
		})),
		...(withMedia && {
			poster: release.poster ? {
				id: release.poster.id,
				path: release.poster.path,
				width: release.poster.width,
				height: release.poster.height,
				size: release.poster.size,
				source: release.poster.source,
			} : null,
			photos: (release.photos || []).map(photo => ({
				id: photo.id,
				path: photo.path,
				width: photo.width,
				height: photo.height,
				size: photo.size,
				source: photo.source,
			})),
		}),
		createdAt: release.created_at,
	};
}

function withRelations(queryBuilder, withMedia = false, type = 'scene') {
	queryBuilder
		.select(knex.raw(`
			releases.id, releases.entry_id, releases.shoot_id, releases.title, releases.url, releases.date, releases.description, releases.duration, releases.created_at,
			row_to_json(sites) as site,
			row_to_json(networks) as network,
			row_to_json(site_networks) as site_network,
			COALESCE(json_agg(DISTINCT actors) FILTER (WHERE actors.id IS NOT NULL), '[]') as actors
		`))
		.where('type', type)
		.leftJoin('sites', 'sites.id', 'releases.site_id')
		.leftJoin('networks', 'networks.id', 'releases.network_id')
		.leftJoin('networks as site_networks', 'site_networks.id', 'sites.network_id')
		.leftJoin('releases_actors', 'releases_actors.release_id', 'releases.id')
		.leftJoin('actors', 'actors.id', 'releases_actors.actor_id')
		.groupBy(knex.raw(`
			releases.id, releases.entry_id, releases.shoot_id, releases.title, releases.url, releases.date, releases.description, releases.duration, releases.created_at,
			sites.id, networks.id, site_networks.id
		`));

	if (withMedia) {
		queryBuilder
			.select(knex.raw(`
				row_to_json(posters) as poster,
				COALESCE(json_agg(DISTINCT photos) FILTER (WHERE photos.id IS NOT NULL), '[]') as photos
			`))
			.leftJoin('releases_posters', 'releases_posters.release_id', 'releases.id')
			.leftJoin('media as posters', 'posters.id', 'releases_posters.media_id')
			.leftJoin('releases_photos', 'releases_photos.release_id', 'releases.id')
			.leftJoin('media as photos', 'photos.id', 'releases_photos.media_id')
			.groupBy('posters.id');
	}
}

async function fetchRelease(releaseId, type = 'scene') {
	const release = await knex('releases')
		.where('releases.id', releaseId)
		.modify(withRelations, true, type)
		.first();

	return curateRelease(release, true);
}

async function fetchReleases(limit = 100, type = 'scene') {
	const releases = await knex('releases')
		.modify(withRelations, false, type)
		.limit(Math.min(limit, 1000));

	return releases.map(release => curateRelease(release));
}

async function searchReleases(query, limit = 100, type = 'scene') {
	const releases = await knex
		.from(knex.raw('search_releases(?) as releases', [query]))
		.modify(withRelations, false, type)
		.limit(Math.min(limit, 1000));

	return releases.map(release => curateRelease(release));
}

module.exports = {
	fetchRelease,
	fetchReleases,
	searchReleases,
};