<script lang="ts">
	import { applicationStore } from '$lib/ApplicationsStore.svelte';
	import HasUser from '$lib/HasUser.svelte';
	import { onMount } from 'svelte';
	import NavBar from '../NavBar.svelte';
	import Pie from './Pie.svelte';
	import { statusStore } from '$lib/Types.svelte';
	import { get } from '$lib/utils';
	import PayRange from './PayRange.svelte';
	import LineGraphs, { type LineGraphData } from './LineGraph.svelte';
	import * as d3 from 'd3';
	import { countReducer, type EventsStat } from './utils';
	import CoolGraph from './CoolGraph/CoolGraph.svelte';

	onMount(() => {
		applicationStore.loadAll();
		statusStore.load();
	});

	let flairStats: 'loading' | Record<string, number> = $state('loading');

	let createGraph: { xs: number[]; ys: number[] } = $state({ xs: [], ys: [] });
	let viewGraph: { xs: number[]; ys: number[] } = $state({ xs: [], ys: [] });
	let statusGraph: LineGraphData = $state([]);

	let events: EventsStat[] = $state([]);

	let width: number = $state(300);

	onMount(async () => {
		(async () => {
			const items: any[] = await get('flair/stats');
			flairStats = items.reduce(
				(acc, a) => {
					acc[a.name] = a.count;
					return acc;
				},
				{} as Record<string, number>
			);
		})();

		(async () => {
			events = await get('events/');

			const pre_created_graph = events
				.filter((a) => a.t === 0)
				.reduce(countReducer, {} as Record<number | string, number>);

			const pre_created_graph_xs = Object.keys(pre_created_graph);

			createGraph = {
				xs: pre_created_graph_xs.map((a) => Number(a)),
				ys: pre_created_graph_xs.map((a) => pre_created_graph[a])
			};

			const pre_views_graph = events
				.filter((a) => a.t === 2)
				.reduce(countReducer, {} as Record<number | string, number>);

			const pre_view_graph_xs = Object.keys(pre_views_graph);

			viewGraph = {
				xs: pre_view_graph_xs.map((a) => Number(a)),
				ys: pre_view_graph_xs.map((a) => pre_views_graph[a])
			};

			statusGraph = statusStore.nodes
				.map((a, i) => {
					const pre = events
						.filter((e) => e.t === 1 && e.s === a.id)
						.reduce(countReducer, {} as Record<number | string, number>);
					const pre_xs = Object.keys(pre);
					if (pre_xs.length === 0) return undefined;
					return {
						name: a.name,
						color: d3.interpolateRainbow(i / statusStore.nodes.length),
						xs: pre_xs.map((a) => Number(a)),
						ys: pre_xs.map((a) => pre[a])
					};
				})
				.filter((a) => a) as LineGraphData;
		})();
	});

	const seniorities = ['intern', 'entry', 'junior', 'mid', 'senior', 'staff', 'lead'];
</script>

<HasUser redirect="/cv">
	<div class="flex flex-col h-[100vh]">
		<NavBar />
		<div class="p-1 px-5">
			<div class="bg-white p-3 rounded-lg gap-5 flex flex-col">
				<div class="flex gap-5 flex-wrap">
					<Pie
						title={'Origin'}
						data={applicationStore.all.reduce(
							(acc, item) => {
								if (item.url.includes('linkedin')) {
									acc.linkedin += 1;
								} else if (item.url.includes('glassdoor')) {
									acc.glassdoor += 1;
								} else {
									acc.other += 1;
								}
								return acc;
							},
							{
								linkedin: 0,
								glassdoor: 0,
								other: 0
							}
						)}
					/>
					<Pie
						title={'Status'}
						data={[...statusStore.nodes, 'Created' as const].reduce(
							(acc, item) => {
								if (item === 'Created') {
									const count = applicationStore.all.filter((a) => a.status_id === null).length;
									if (count === 0) return acc;
									acc[item] = count;
									return acc;
								}
								const count = applicationStore.all.filter((a) => item.id === a.status_id).length;
								if (count === 0) return acc;
								acc[item.name] = count;
								return acc;
							},
							{} as Record<string, number>
						)}
					/>
					<Pie
						title={'Higher range Pay Range'}
						data={applicationStore.all
							.filter((a) => a.payrange.match(/\d/))
							.map((a) => {
								const payrange = a.payrange
									.replace(/[kK]/g, '000')
									.replace(/[^\d\-–]/g, '')
									.replace(/–/g, '-')
									.split('-');
								return Number(payrange[payrange.length - 1]);
							})
							.reduce(
								(acc, a) => {
									const f = Math.floor(a / 10000);
									let name = `${f * 10}K-${(f + 1) * 10}K`;
									if (f == 0) {
										name = '<10K';
									}
									if (acc[name]) {
										acc[name] += 1;
									} else {
										acc[name] = 1;
									}
									return acc;
								},
								{} as Record<string, number>
							)}
					/>
					<Pie
						title={'Lower range Pay Range'}
						data={applicationStore.all
							.filter((a) => a.payrange.match(/\d/))
							.map((a) => {
								const payrange = a.payrange
									.replace(/[kK]/g, '000')
									// The first is a - the other is unicode 8211
									.replace(/[^\d\-–]/g, '')
									.replace(/–/g, '-')
									.split('-');
								return Number(payrange[0]) + Number(payrange[1] ?? payrange[0]);
							})
							.reduce(
								(acc, a) => {
									const f = Math.floor(a / 10000);
									let name = `${f * 10}K-${(f + 1) * 10}K`;
									if (f == 0) {
										name = '<10K';
									}
									if (acc[name]) {
										acc[name] += 1;
									} else {
										acc[name] = 1;
									}
									return acc;
								},
								{} as Record<string, number>
							)}
					/>
					<Pie
						title={'Company'}
						sensitivity={0.01}
						data={applicationStore.all.reduce(
							(acc, item) => {
								if (acc[item.company]) {
									acc[item.company] += 1;
								} else {
									acc[item.company] = 1;
								}
								return acc;
							},
							{} as Record<string, number>
						)}
					/>
					<Pie
						title={'Location'}
						sensitivity={0.01}
						data={applicationStore.all.reduce(
							(acc, item) => {
								const l = item.location === '' ? 'Unknown' : item.location;
								if (acc[l]) {
									acc[l] += 1;
								} else {
									acc[l] = 1;
								}
								return acc;
							},
							{} as Record<string, number>
						)}
					/>
					<Pie
						title={'In Person type'}
						sensitivity={0.01}
						data={applicationStore.all.reduce(
							(acc, item) => {
								const l = item.inperson_type === '' ? 'Unknown' : item.inperson_type;
								if (acc[l]) {
									acc[l] += 1;
								} else {
									acc[l] = 1;
								}
								return acc;
							},
							{} as Record<string, number>
						)}
					/>
					<Pie
						title={'Job Level'}
						data={applicationStore.all.reduce(
							(acc, a) => {
								const job_level = a.job_level ? a.job_level : 'Unknown';
								if (acc[job_level]) {
									acc[job_level] += 1;
								} else {
									acc[job_level] = 1;
								}
								return acc;
							},
							{} as Record<string, number>
						)}
						sensitivity={0.02}
					/>
					<Pie
						title={'Agency'}
						data={applicationStore.all.reduce(
							(acc, a) => {
								const i = a.agency ? 'Agency' : 'Direct';
								if (acc[i]) {
									acc[i] += 1;
								} else {
									acc[i] = 1;
								}
								return acc;
							},
							{} as Record<string, number>
						)}
						sensitivity={0.02}
					/>
				</div>
				{#if flairStats !== 'loading'}
					<div class="flex gap-5">
						<Pie title={'Flair stats'} data={flairStats} sensitivity={0.02} />
						<div class="max-h-[500px] overflow-auto">
							<ul>
								{#each Object.keys(flairStats).toSorted((a, b) => flairStats[b] - flairStats[a]) as flair}
									<li>{flair}: {flairStats[flair]}</li>
								{/each}
							</ul>
						</div>
					</div>
				{/if}
				<div bind:clientWidth={width}>
					<LineGraphs
						data={[
							{ name: 'Created Time', color: 'red', ...createGraph },
							{ name: 'Views', color: 'blue', ...viewGraph }
						]}
						xIsDates
						width={width - 50}
						height={300}
					/>
				</div>
				<div bind:clientWidth={width}>
					<h1>Status Graph</h1>
					<LineGraphs data={statusGraph} xIsDates width={width - 50} height={300} />
				</div>
				<h1>Payrange</h1>
				<PayRange />
				<div>
					<h1>Per Seniority</h1>
					{#each seniorities as level}
						{@const fapps = applicationStore.all.filter(
							(a) => a.payrange.match(/\d/) && a.job_level === level
						)}
						<h2 class="font-bold text-lg">
							{level} (AVG pay: {(
								fapps
									.map((a) => {
										const payrange = a.payrange
											.replace(/[kK]/g, '000')
											.replace(/[^\d\-–]/g, '')
											.replace(/–/g, '-')
											.split('-');
										return Number(payrange[0]) + Number(payrange[1] ?? payrange[0]);
									})
									.reduce((acc, a) => acc + a, 0) /
								(fapps.length * 2)
							).toLocaleString('en-GB', {
								notation: 'compact',
								style: 'currency',
								currency: 'GBP'
							})})
						</h2>
						<div class="flex gap-2">
							<Pie
								title={'Higher range Pay Range'}
								data={fapps
									.map((a) => {
										const payrange = a.payrange
											.replace(/[kK]/g, '000')
											.replace(/[^\d\-–]/g, '')
											.replace(/–/g, '-')
											.split('-');
										return Number(payrange[payrange.length - 1]);
									})
									.reduce(
										(acc, a) => {
											const f = Math.floor(a / 10000);
											let name = `${f * 10}K-${(f + 1) * 10}K`;
											if (f == 0) {
												name = '<10K';
											}
											if (acc[name]) {
												acc[name] += 1;
											} else {
												acc[name] = 1;
											}
											return acc;
										},
										{} as Record<string, number>
									)}
							/>
							<Pie
								title={'Lower range Pay Range'}
								data={fapps
									.map((a) => {
										const payrange = a.payrange
											.replace(/[kK]/g, '000')
											// The first is a - the other is unicode 8211
											.replace(/[^\d\-–]/g, '')
											.replace(/–/g, '-')
											.split('-');
										return Number(payrange[0]);
									})
									.reduce(
										(acc, a) => {
											const f = Math.floor(a / 10000);
											let name = `${f * 10}K-${(f + 1) * 10}K`;
											if (f == 0) {
												name = '<10K';
											}
											if (acc[name]) {
												acc[name] += 1;
											} else {
												acc[name] = 1;
											}
											return acc;
										},
										{} as Record<string, number>
									)}
							/>
							<Pie
								title={'AVG Pay'}
								data={fapps
									.map((a) => {
										const payrange = a.payrange
											.replace(/[kK]/g, '000')
											// The first is a - the other is unicode 8211
											.replace(/[^\d\-–]/g, '')
											.replace(/–/g, '-')
											.split('-');
										return (Number(payrange[0]) + Number(payrange[1] ?? payrange[0])) / 2;
									})
									.reduce(
										(acc, a) => {
											const f = Math.floor(a / 10000);
											let name = `${f * 10}K-${(f + 1) * 10}K`;
											if (f == 0) {
												name = '<10K';
											}
											if (acc[name]) {
												acc[name] += 1;
											} else {
												acc[name] = 1;
											}
											return acc;
										},
										{} as Record<string, number>
									)}
							/>
						</div>
					{/each}
				</div>
				<h1>Cool graph</h1>
				<CoolGraph {events} />
			</div>
		</div>
	</div>
</HasUser>
