<script setup>
import { format, subYears } from 'date-fns';
import { parse } from 'path-to-regexp';
import { inject, ref } from 'vue';

import ActorTile from '#/components/actors/tile.vue';
import BirthdateFilter from '#/components/filters/birthdate.vue';
import BoobsFilter from '#/components/filters/boobs.vue';

import CountryFilter from '#/components/filters/country.vue';
import Filters from '#/components/filters/filters.vue';
import GenderFilter from '#/components/filters/gender.vue';
import PhysiqueFilter from '#/components/filters/physique.vue';
import Checkbox from '#/components/form/checkbox.vue';
import Pagination from '#/components/pagination/pagination.vue';
import { get } from '#/src/api.js';
import events from '#/src/events.js';
import navigate from '#/src/navigate.js';

const pageContext = inject('pageContext');
const { pageProps, urlParsed, routeParams } = pageContext;

const q = ref(urlParsed.search.q);
const actors = ref([]);
const pageStash = pageProps.stash;
const countries = ref(pageProps.countries);
const cupRange = ref(pageProps.cupRange);

actors.value = pageProps.actors;

const currentPage = ref(Number(routeParams.page));
const total = ref(Number(pageProps.actorTotal || pageProps.total));
const order = ref(routeParams.order || urlParsed.search.order || 'likes.desc');

const filters = ref({
	gender: urlParsed.search.gender,
	ageRequired: !!urlParsed.search.age,
	age: urlParsed.search.age?.split(',').map((age) => Number(age)) || [18, 100],
	dobRequired: !!urlParsed.search.dob,
	dobType: urlParsed.search.dobt ? ({ bd: 'birthday', dob: 'dob' })[urlParsed.search.dobt] : 'birthday',
	dob: urlParsed.search.dob || format(subYears(new Date(), 21), 'yyyy-MM-dd'),
	country: urlParsed.search.c,
	braSizeRequired: !!urlParsed.search.cup,
	braSize: urlParsed.search.cup?.split(',') || ['A', 'Z'],
	naturalBoobs: urlParsed.search.nb ? urlParsed.search.nb === 'true' : undefined,
	heightRequired: !!urlParsed.search.height,
	height: urlParsed.search.height?.split(',').map((height) => Number(height)) || [50, 220],
	weightRequired: !!urlParsed.search.weight,
	weight: urlParsed.search.weight?.split(',').map((weight) => Number(weight)) || [30, 200],
	avatarRequired: !!urlParsed.search.avatar,
});

function getPath(preserveQuery) {
	const path = parse(routeParams.path).map((segment) => {
		if (segment.name === 'page') {
			return `${segment.prefix}${currentPage.value || 1}`;
		}

		return `${segment.prefix || ''}${routeParams[segment.name] || segment}`;
	}).join('');

	if (preserveQuery && urlParsed.searchOriginal) {
		return `${path}${urlParsed.searchOriginal}`;
	}

	return path;
}

async function search(options = {}) {
	if (options.resetPage !== false) {
		currentPage.value = 1;
	}

	if (options.autoScope !== false) {
		if (q.value) {
			order.value = 'results.desc';
		}

		if (!q.value && order.value.includes('results')) {
			order.value = 'likes.desc';
		}
	}

	const query = {
		q: q.value || undefined,
		order: order.value,
		gender: filters.value.gender || undefined,
		age: filters.value.ageRequired ? filters.value.age.join(',') : undefined,
		dob: filters.value.dobRequired ? filters.value.dob : undefined,
		dobt: filters.value.dobRequired ? ({ birthday: 'bd', dob: 'dob' })[filters.value.dobType] : undefined,
		cup: filters.value.braSizeRequired ? filters.value.braSize.join(',') : undefined,
		c: filters.value.country || undefined,
		nb: filters.value.naturalBoobs,
		height: filters.value.heightRequired ? filters.value.height.join(',') : undefined,
		weight: filters.value.weightRequired ? filters.value.weight.join(',') : undefined,
		avatar: filters.value.avatarRequired || undefined,
		stashId: pageStash?.id,
	};

	navigate(getPath(false), query, { redirect: false });

	const res = await get('/actors', {
		...query,
		page: currentPage.value, // client uses param rather than query pagination
	});

	actors.value = res.actors;
	total.value = res.total;

	countries.value = res.countries;

	events.emit('scrollUp');
}

function paginate({ page }) {
	currentPage.value = page;

	search({ resetPage: false });
}

function updateFilter(prop, value, reload = true) {
	filters.value[prop] = value;

	if (reload) {
		search();
	}
}
</script>

<template>
	<div class="page">
		<Filters :results="total">
			<div class="filter search-container">
				<!-- onsearch not compatible with FF and Safari -->
				<input
					v-model="q"
					type="input"
					placeholder="Search actors"
					class="input search"
					@keydown.enter="search"
				>

				<Icon
					v-if="q"
					icon="cross2"
					class="search-button"
					@click="q = ''; search()"
				/>

				<Icon
					icon="search"
					class="search-button"
					@click="search"
				/>
			</div>

			<GenderFilter
				:filters="filters"
				@update="updateFilter"
			/>

			<BirthdateFilter
				:filters="filters"
				@update="updateFilter"
			/>

			<BoobsFilter
				:filters="filters"
				:cup-range="cupRange"
				@update="updateFilter"
			/>

			<PhysiqueFilter
				:filters="filters"
				@update="updateFilter"
			/>

			<CountryFilter
				:filters="filters"
				:countries="countries"
				@update="updateFilter"
			/>

			<div class="filter">
				<Checkbox
					:checked="filters.avatarRequired"
					label="Require photo"
					@change="(checked) => updateFilter('avatarRequired', checked, true)"
				/>
			</div>
		</Filters>

		<div class="actors-container">
			<div class="actors-header">
				<div class="meta">
					<span class="count">{{ total }} results</span>

					<select
						v-model="order"
						class="input"
						@change="search({ autoScope: false })"
					>
						<option
							v-if="pageStash"
							:selected="order === 'stashed.desc'"
							value="stashed.desc"
						>Added</option>

						<option
							v-if="q"
							:selected="order === 'results.desc'"
							value="results.desc"
						>Relevance</option>

						<option value="name.asc">Name</option>
						<option value="likes.desc">Popular</option>
						<option value="scenes.desc">Scenes</option>
					</select>
				</div>
			</div>

			<ul class="actors nolist">
				<li
					v-for="actor in actors"
					:key="`actor-${actor.id}`"
				>
					<ActorTile
						:actor="actor"
					/>
				</li>
			</ul>

			<Pagination
				:page="currentPage"
				:total="total"
				:redirect="false"
				@navigation="paginate"
			/>
		</div>
	</div>
</template>

<style>
.gender-button {
    &.selected .gender .icon  {
        fill: var(--text-light);
        filter: none;
    }

    &:hover:not(.selected) {
        .gender .icon {
            fill: var(--text-light);
        }

        .male .icon  {
            filter: drop-shadow(0 0 1px var(--male));
        }

        .female .icon  {
            filter: drop-shadow(0 0 1px var(--female));
        }
    }

    &:hover:not(.selected) .transsexual .icon  {
        fill: var(--female);
        filter: drop-shadow(1px 0 0 var(--text-light)) drop-shadow(-1px 0 0 var(--text-light)) drop-shadow(0 1px 0 var(--text-light)) drop-shadow(0 -1px 0 var(--text-light)) drop-shadow(1px 0 0 var(--male)) drop-shadow(-1px 0 0 var(--male)) drop-shadow(0 1px 0 var(--male)) drop-shadow(0 -1px 0 var(--male)) drop-shadow(0 0 1px rgba(0, 0, 0, 0.5));
    }
}
</style>

<style scoped>
.page {
	min-height: 100%;
	display: flex;
	flex-grow: 1;
	align-items: stretch;
	background: var(--background-base-10);
}

.actors-container {
	display: flex;
	flex-grow: 1;
	flex-direction: column;
	box-sizing: border-box;
	padding: 0 1rem 1rem 1rem;
}

.actors-header {
	display: flex;
	align-items: center;
	padding: .5rem 0 .5rem 3rem;
	margin-bottom: .25rem;
}

.meta {
	display: flex;
	flex-grow: 1;
	justify-content: space-between;
	align-items: center;
}

.actors {
	display: grid;
	flex-grow: 1;
	grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
	grid-auto-rows: max-content; /* prevent row gaps on large screens */
	gap: .25rem;
}

@media(--small-40) {
	.actors {
		grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
	}
}
</style>
