import config from 'config';
import dayjs from 'dayjs';

import { graphql, get } from '../api';
import { curateActor, curateRelease } from '../curate';
import getDateRange from '../get-date-range';

import {
	releaseFields,
	actorStashesFields,
	getIncludedEntities,
	getIncludedActors,
} from '../fragments';

function initActorActions(store, router) {
	async function fetchActorById({ _commit }, {
		actorId,
		limit = 10,
		pageNumber = 1,
		range = 'latest',
	}) {
		if (!actorId) {
			return null;
		}

		const { before, after, orderBy } = getDateRange(range);
		const includedTags = router.currentRoute.value.query.tags ? router.currentRoute.value.query.tags.split(',') : [];
		const mode = router.currentRoute.value.query.mode || 'all';

		const { actor } = await graphql(`
            query Actor(
                $actorId: Int!
				$userId: Int,
				$hasAuth: Boolean!,
                $limit:Int = 10,
				$offset:Int = 0,
                $after:Datetime = "1900-01-01",
                $before:Datetime = "2100-01-01",
                $afterTime:Datetime = "1900-01-01",
                $beforeTime:Datetime = "2100-01-01",
                $orderBy:[ReleasesOrderBy!]
				$selectableTags: [String],
				$includedTags: [String!],
				$exclude: [String!],
				$mode: String!,
				$includedEntities: [ReleaseFilter!],
				$includedActors: [ReleaseFilter!]
            ) {
                actor(id: $actorId) {
                    id
                    name
                    slug
					realName
                    gender
                    dateOfBirth
                    dateOfDeath
                    age
					dateOfBirth
					ageFromBirth
					ageAtDeath
                    ethnicity
					cup
                    bust
                    waist
                    hip
                    naturalBoobs
					penisLengthMetric: penisLength(units:METRIC)
					penisLengthImperial: penisLength(units:IMPERIAL)
					penisGirthMetric: penisGirth(units:METRIC)
					penisGirthImperial: penisGirth(units:IMPERIAL)
					circumcised
                    heightMetric: height(units:METRIC)
                    heightImperial: height(units:IMPERIAL)
                    weightMetric: weight(units:METRIC)
                    weightImperial: weight(units:IMPERIAL)
					hairColor
					hairLength
					eyes
                    hasTattoos
                    hasPiercings
                    tattoos
                    piercings
                    description
					createdAt
					updatedAt
                    entity {
                        id
                        name
                        slug
						type
						parent {
							id
							name
							slug
							type
						}
                    }
					avatar: avatarMedia {
						id
						path
						thumbnail
						lazy
						width
						height
						thumbnailWidth
						thumbnailHeight
						hash
						comment
						credit
						isS3
						sfw: sfwMedia {
							id
							thumbnail
							path
							comment
						}
					}
					profiles: actorsProfiles(orderBy: PRIORITY_DESC) {
						description
						descriptionHash
						entity {
							id
							name
							slug
							type
							independent
							parent {
								id
								name
								slug
								type
							}
						}
						avatar: avatarMedia {
							id
							path
							thumbnail
							lazy
							width
							height
							thumbnailWidth
							thumbnailHeight
							hash
							isS3
							comment
							credit
							entropy
							sharpness
							sfw: sfwMedia {
								id
								thumbnail
								path
								comment
							}
						}
                    }
                    birthCity
                    birthState
                    birthCountry: countryByBirthCountryAlpha2 {
                      alpha2
                      name
                      alias
                    }
                    residenceCity
                    residenceState
                    residenceCountry: countryByResidenceCountryAlpha2 {
                      alpha2
                      name
                      alias
                    }
                    social: actorsSocials {
                        id
                        url
                        platform
                    }
                    aliases: actorsByAliasFor {
                        id
                        name
                        slug
                    }
					tags(selectableTags: $selectableTags) {
						id
						name
						slug
						priority
					}
					channels {
						id
						name
						slug
						type
						independent
						parent {
							id
							name
							slug
							type
						}
					}
					actors {
						id
						name
						slug
					}
                    scenesConnection(
                        filter: {
							or: [
								{
									date: {
										lessThan: $before,
										greaterThan: $after
									}
								},
								{
									date: {
										isNull: true
									},
									createdAt: {
										lessThan: $beforeTime,
										greaterThan: $afterTime,
									}
								}
							]
							and: [
								{
									or: $includedEntities
								}
								{
									or: $includedActors
								}
								{
									releasesTagsConnection: {
										none: {
											tag: {
												slug: {
													in: $exclude
												}
											}
										}
									}
								}
							]
                        }
						selectedTags: $includedTags
						mode: $mode
                        first: $limit
						offset: $offset
                        orderBy: $orderBy
                    ) {
						releases: nodes {
							${releaseFields}
						}
						totalCount
                    }
					${actorStashesFields}
                }
            }
        `, {
			actorId,
			limit,
			offset: Math.max(0, (pageNumber - 1)) * limit,
			after,
			before,
			afterTime: store.getters.after,
			beforeTime: store.getters.before,
			selectableTags: config.selectableTags,
			orderBy,
			exclude: store.state.ui.tagFilter,
			includedTags,
			includedEntities: getIncludedEntities(router),
			includedActors: getIncludedActors(router),
			mode,
			hasAuth: !!store.state.auth.user,
			userId: store.state.auth.user?.id,
		});

		if (!actor) {
			router.replace('/not-found');
			return null;
		}

		return {
			actor: curateActor(actor, null, curateRelease),
			releases: actor.scenesConnection.releases.map((release) => curateRelease(release)),
			totalCount: actor.scenesConnection.totalCount,
		};
	}

	async function fetchActors({ _commit }, {
		limit = 10,
		pageNumber = 1,
		query,
		gender,
		age,
		country,
		dob,
		naturalBoobs,
		boobSize,
		height,
		weight,
	}) {
		const now = dayjs();

		const genderFilter = (gender === null && 'gender: { isNull: true }')
			|| (gender === 'all' && ' ')
			|| (gender && `gender: { equalTo: "${gender}" }`)
			|| '';

		const ageFilter = age ? `
			or: [
				{
					dateOfBirth: {
						greaterThanOrEqualTo: "${now.subtract(age[1], 'year').format('YYYY-MM-DD')}",
						lessThanOrEqualTo: "${now.subtract(age[0], 'year').format('YYYY-MM-DD')}"
					}
				},
				{
					dateOfBirth: {
						isNull: true
					}
					age: {
						greaterThanOrEqualTo: ${age[0]}
						lessThanOrEqualTo: ${age[1]}
					}
				}
			]
		` : '';

		const dobFilter = dob ? `dateOfBirth: { equalTo: "${dob}" }` : '';
		const countryFilter = country ? `countryByBirthCountryAlpha2: { alpha2: { equalTo: "${country}" } }` : '';

		const heightFilter = height ? `height: { greaterThanOrEqualTo: ${height[0]}, lessThanOrEqualTo: ${height[1]} }` : '';
		const weightFilter = weight ? `weight: { greaterThanOrEqualTo: ${weight[0]}, lessThanOrEqualTo: ${weight[1]} }` : '';
		const cupFilter = boobSize ? `cup: { greaterThanOrEqualTo: "${boobSize[0]}", lessThanOrEqualTo: "${boobSize[1]}" }` : '';

		const { connection: { actors, totalCount }, countries } = await graphql(`
            query Actors(
                $query: String
                $limit: Int,
                $offset: Int = 0,
				$naturalBoobs: Boolean,
				$userId: Int,
				$hasAuth: Boolean!,
            ) {
				connection: searchActorsConnection(
					query: $query
                    first: $limit,
					offset: $offset
                    orderBy: NAME_ASC
					minLength: 0
                    filter: {
						aliasFor: {
							isNull: true
						}
						${genderFilter}
						${ageFilter}
						${dobFilter}
						${heightFilter}
						${weightFilter}
						${cupFilter}
						${countryFilter}
						naturalBoobs: {
							equalTo: $naturalBoobs
						}
                    }
                ) {
					totalCount
					actors: nodes {
						id
						name
						slug
						age
						dateOfBirth
						ageFromBirth
						ageAtDeath
						dateOfBirth
						dateOfDeath
						gender
						entity {
							id
							name
							slug
							type
							parent {
								id
								name
								slug
								type
							}
						}
						avatar: avatarMedia {
							id
							path
							thumbnail
							lazy
							comment
							credit
							isS3
							sfw: sfwMedia {
								id
								thumbnail
								path
								comment
							}
						}
						birthCountry: countryByBirthCountryAlpha2 {
						  alpha2
						  name
						  alias
						}
						${actorStashesFields}
					}
                }
				countries(
					orderBy: NAME_ASC,
				) {
					alpha2
					name
					alias
				}
            }
        `, {
			query,
			offset: Math.max(0, (pageNumber - 1)) * limit,
			limit,
			naturalBoobs: naturalBoobs || null,
			hasAuth: !!store.state.auth.user,
			userId: store.state.auth.user?.id,
		});

		return {
			actors: actors.map((actor) => curateActor(actor)),
			totalCount,
			countries,
		};
	}

	async function fetchActorReleases({ _commit }, actorId) {
		const releases = await get(`/actors/${actorId}/releases`, {
			filter: store.state.ui.filter,
			after: store.getters.after,
			before: store.getters.before,
		});

		return releases;
	}

	return {
		fetchActorById,
		fetchActors,
		fetchActorReleases,
	};
}

export default initActorActions;