<script lang="ts">
	import { applicationStore, type Application } from '$lib/ApplicationsStore.svelte';

	import { put, preventDefault, post, get, deleteR } from '$lib/utils';
	import { onMount } from 'svelte';
	import ExtractTextDialog from './ExtractTextDialog.svelte';
	import Flair from '../flair/Flair.svelte';
	import NewUrlDialog from './NewUrlDialog.svelte';
	import { userStore } from '$lib/UserStore.svelte';
	import LinkApplication from './LinkApplication.svelte';
	import SearchApplication from './SearchApplication.svelte';
	import NewApplication from './NewApplication.svelte';
	import Timeline from './Timeline.svelte';
	import CompanyField from './CompanyField.svelte';
	import AutoDropZone from './AutoDropZone.svelte';
	import { statusStore } from '$lib/Types.svelte';
	import SearchFound from './SearchFound.svelte';
	import FoundExpire from './FoundExpire.svelte';
	import ApplicationsList from '../ApplicationsList.svelte';

	let { appList }: { appList: ApplicationsList } = $props();

	// Not this represents the index in the store array
	let activeItem: number | undefined = $state();

	let derivedItem: Application | undefined = $derived(applicationStore.all[activeItem ?? -1]);

	let extractTokens: HTMLDialogElement;
	let changeUrl: HTMLDialogElement;
	let linkApplication: HTMLDialogElement;
	let searchFound: SearchFound;
	let foundExpire: FoundExpire;

	let lastExtData: any = $state(undefined);
	let autoExtData = false;

	let showExtraData = $state(false);

	let drag = $state(true);

	async function activate(item?: Application, ow = true) {
		if (!item) {
			return;
		}

		if (ow && item.id !== derivedItem?.id) {
			openWindow(item.url);
		}
		openCV(item.id);

		try {
			const toLoadItem: Application = await get(`application/${item.id}`);
			if (!toLoadItem?.simple_url) {
				window.requestAnimationFrame(() => {
					changeUrl.showModal();
				});
			}
			activeItem = applicationStore.getIndexById(toLoadItem.id);
			applicationStore.all[activeItem ?? -1] = toLoadItem;
			applicationStore.reset();
		} catch (e) {
			// Show User
			console.log('info data', e);
		}

		autoExtData = false;
		lastExtData = undefined;
	}

	let win: undefined | Window | null | true = $state(undefined);
	function openWindow(url: string) {
		if (!url.startsWith('https://')) {
			url = `https://${url}`;
		}

		if (win && hasExt) {
			window.postMessage({ type: 'CHANGE_PAGE', new_url: url });
			return;
		}
		win = window.open(
			url,
			'new window',
			`location,height=${window.screen.height},width=${window.screen.width},scrollbars,status,toolbar,menubar,popup`
		);
	}

	function openCV(id?: string) {
		window.open(
			`/cv?id=${id ?? derivedItem!.id}`,
			'cv viwer',
			`location,height=${window.screen.height},width=${window.screen.width},scrollbars,status,toolbar,menubar,popup`
		);
	}

	//
	// Make the CV open on a new page
	//
	function docKey(e: KeyboardEvent) {
		if (derivedItem && e.ctrlKey && e.code === 'KeyO') {
			openCV(derivedItem.id);
			e.stopPropagation();
			e.preventDefault();
			return;
		}
	}
	$effect(() => {
		document.addEventListener('keydown', docKey, false);
		return () => {
			document.removeEventListener('keydown', docKey);
		};
	});
	//
	//
	//

	let hasExt = $state(false);
	// Load Ext
	$effect(() => {
		function onMessage(e: MessageEvent) {
			if (e.data.type === 'GOT_INFO_R') {
				lastExtData = e.data;
				if ((autoExtData || derivedItem?.title === 'New Application') && derivedItem?.simple_url) {
					if (e.data.status === 'expired' && derivedItem?.status_id === null) {
						foundExpire.open();
					}
					window.requestAnimationFrame(() => {
						setExtData();
					});
				}
			}
			if (e.data.type === 'AUTOLOAD_FOUND_GLASSDOOR_SEARCH') {
				console.log('Found glassdoor search');
				if (changeUrl.open) {
					changeUrl.close();
					searchFound.open();
				}
				return;
			}
			if (e.data.type === 'GOT_INTEREST') {
				console.log('Has for ext and has id!');
				hasExt = true;
				win = true;
			}
			if (e.data.type === 'HAS_EXTENSION') {
				console.log('Has for ext!');
				hasExt = true;
			}
		}

		window.addEventListener('message', onMessage);
		console.log('Sending request for ext!');
		window.postMessage({ type: 'REGISTER_INTEREST' });
		window.postMessage({ type: 'HAS_EXTENSION_Q' });
		return () => {
			window.removeEventListener('message', onMessage);
		};
	});

	function setExtData() {
		if (!lastExtData || activeItem === undefined || !derivedItem) return;
		applicationStore.all[activeItem].title = lastExtData.jobTitle.replace(/\&amp;/, '&');
		applicationStore.all[activeItem].company = lastExtData.company.replace(/\&amp;/, '&');

		if (
			!(
				applicationStore.all[activeItem].payrange.match('Glassdoor est.') &&
				lastExtData.money.match('Glassdoor est.')
			) &&
			!(applicationStore.all[activeItem].payrange !== '' && lastExtData.money === '')
		) {
			applicationStore.all[activeItem].payrange = lastExtData.money;
		}

		applicationStore.all[activeItem].inperson_type = (
			lastExtData.inperson_type as string
		).toLowerCase();

		if (lastExtData.location && lastExtData.location.includes(',')) {
			applicationStore.all[activeItem].location = (lastExtData.location as string).split(',')[0];
		} else if (lastExtData.location && lastExtData.location.includes('·')) {
			applicationStore.all[activeItem].location = (lastExtData.location as string)
				.split('·')[0]
				.trim();
		}

		console.log(lastExtData);

		const title: string = lastExtData.jobTitle;
		if (title.match(/intern|apprenticeship/i)) {
			applicationStore.all[activeItem].job_level = 'intern';
		} else if (title.match(/graduate/i)) {
			applicationStore.all[activeItem].job_level = 'entry';
		} else if (title.match(/junior|associate/i)) {
			applicationStore.all[activeItem].job_level = 'junior';
		} else if (title.match(/mid/i)) {
			applicationStore.all[activeItem].job_level = 'mid';
		} else if (title.match(/senior|III/i)) {
			applicationStore.all[activeItem].job_level = 'senior';
		} else if (title.match(/staff/i)) {
			applicationStore.all[activeItem].job_level = 'staff';
		} else if (title.match(/lead/i)) {
			applicationStore.all[activeItem].job_level = 'lead';
		}

		window.requestAnimationFrame(() => {
			save().then(async () => {
				if (activeItem === undefined) return;
				if (!lastExtData.description) {
					lastExtData = undefined;
					return;
				}
				await post('application/text/flair', {
					id: derivedItem.id ?? '',
					text: lastExtData.description
				});
				activate(derivedItem, false);
				lastExtData = undefined;
			});
		});
	}

	onMount(() => {
		userStore.checkLogin();
		statusStore.load();
	});

	$effect(() => {
		if (!applicationStore.loadItem) {
			return;
		}
		(async () => {
			await activate(applicationStore.loadItem, applicationStore.loadItemOpen);
			applicationStore.loadItem = undefined;
		})();
	});

	$effect(() => {
		applicationStore.loadAll();
	});

	async function save() {
		try {
			await put('application/update', applicationStore.all[activeItem ?? -1]);
		} catch (e) {
			// Show User
			console.log('info data', e);
		}
	}

	async function resetUrl() {
		try {
			activeItem = await post(`application/reset/url/${derivedItem?.id}`, {});
		} catch (e) {
			// Show User
			console.log('info data', e);
		}
	}

	async function remove(autoNext = false) {
		if (!derivedItem) return;
		// Deactivate active item
		try {
			await deleteR(`application/${derivedItem.id}`);
		} catch (e) {
			// TODO: Show User
			console.log('info data', e);
			return;
		}
		applicationStore.removeByID(derivedItem.id);
		activeItem = undefined;
		if (autoNext) {
			appList.requestNext();
		}
	}
</script>

<div class="flex flex-col w-full gap-2 min-w-0 relative" role="none">
	{#if activeItem !== undefined && (!applicationStore.dragging || applicationStore.dragging?.id === derivedItem.id)}
		<div
			draggable={drag}
			ondrag={() => {
				applicationStore.dragStart(derivedItem);
			}}
			ondragend={() => {
				window.requestAnimationFrame(() => {
					applicationStore.dragEnd();
				});
			}}
			role="none"
			class="flex flex-col p-2 h-full gap-2 card min-w-0 flex-grow min-h-[50vh]"
		>
			<div class="w-full">
				<!-- TODO add item -->
				{#if derivedItem.status_id !== null}
					<div class="bg-danger text-white p-2 rounded-lg text-lg font-bold">
						{statusStore.nodesR[derivedItem.status_id].name}
					</div>
				{/if}
				{#if showExtraData}
					<fieldset class="max-w-full min-w-0 overflow-hidden">
						<div class="flabel">Id</div>
						<div class="finput bg-white w-full break-keep">
							{derivedItem.id}
						</div>
					</fieldset>
					<fieldset class="max-w-full min-w-0 overflow-hidden">
						<div class="flabel">Create Time</div>
						<div class="finput bg-white w-full break-keep">
							{derivedItem.create_time}
						</div>
					</fieldset>
				{/if}
				<div class="flex gap-2">
					<CompanyField index={activeItem} {save} />
					<fieldset class="grow">
						<label class="flabel" for="title">Recruiter</label>
						<input
							class="finput"
							id="title"
							bind:value={applicationStore.all[activeItem].recruiter}
							onchange={save}
						/>
					</fieldset>
					<fieldset>
						<label class="flabel" for="title">Agency</label>
						<input
							class="finput"
							id="title"
							type="checkbox"
							bind:checked={applicationStore.all[activeItem].agency}
							onchange={save}
						/>
					</fieldset>
				</div>
				<fieldset>
					<label class="flabel" for="title">Title</label>
					<input
						class="finput"
						id="title"
						bind:value={applicationStore.all[activeItem].title}
						onchange={save}
					/>
				</fieldset>
				<label class="flabel" for="payrange">Pay Range</label>
				<fieldset class="flex items-center gap-2">
					<input
						class="finput"
						id="payrange"
						bind:value={applicationStore.all[activeItem].payrange}
						onchange={save}
					/>
					<button
						title="Move hourly to yearly"
						class="p-2"
						onclick={() => {
							const payrange = applicationStore.all[activeItem!].payrange
								// remove decimal places
								.replace(/(\d+).(\d+)/g, '$1')
								.replace(/[kK]/g, '000')
								.replace(/[^\d\-–]/g, '')
								.replace(/–/g, '-')
								.split('-')
								.map((a) => {
									console.log('here', a);
									return +a;
								});

							payrange[0] = payrange[0] * 8 * 5 * 4 * 12;
							if (payrange[1] != undefined) {
								payrange[1] = payrange[1] * 8 * 5 * 4 * 12;
								applicationStore.all[activeItem!].payrange = `${payrange[0]}-${payrange[1]}`;

								window.requestAnimationFrame(() => save());
								return;
							}
							applicationStore.all[activeItem!].payrange = `${payrange[0]}`;
							window.requestAnimationFrame(() => save());
						}}
					>
						<span class="bi bi-arrow-clockwise"></span>
					</button>
				</fieldset>
				{#if !derivedItem.simple_url || showExtraData}
					<fieldset class="max-w-full min-w-0 overflow-hidden">
						<div class="flabel">Url</div>
						<div class="finput bg-white w-full break-keep">
							{derivedItem.url}
						</div>
					</fieldset>
				{/if}
				{#if derivedItem.simple_url}
					<fieldset class="max-w-full min-w-0 overflow-hidden">
						<div class="flabel">Simple Url</div>
						<div class="finput bg-white w-full break-keep">
							{derivedItem.simple_url}
						</div>
					</fieldset>
				{/if}
				{#if showExtraData}
					<div>
						<div class="flabel">Simple Url</div>
						<div class="flex flex-col gap-2">
							{#each derivedItem.urls as url}
								<div>
									<button
										class="text-violet-300 text-nowrap whitespace-nowrap overflow-x-hidden"
										onclick={() => {
											openWindow(url);
										}}>{url}</button
									>
								</div>
							{/each}
						</div>
					</div>
				{/if}
				<div class="flex gap-2">
					<fieldset class="flex-grow">
						<label class="flabel" for="title">Job Level</label>
						<select
							class="finput"
							id="job_level"
							bind:value={applicationStore.all[activeItem].job_level}
							onchange={save}
						>
							<option value="intern"> Intern </option>
							<option value="entry"> Entry </option>
							<option value="junior"> Junior </option>
							<option value="mid"> Mid </option>
							<option value="senior"> Senior </option>
							<option value="staff"> Staff </option>
							<option value="lead"> Lead </option>
						</select>
					</fieldset>
					<fieldset class="flex-grow">
						<label class="flabel" for="title">In Person?</label>
						<select
							class="finput"
							id="inperson_type"
							bind:value={applicationStore.all[activeItem].inperson_type}
							onchange={save}
						>
							<option value="on-site"> On-site </option>
							<option value="remote"> Remote </option>
							<option value="hybrid"> Hybrid </option>
						</select>
					</fieldset>
					<fieldset class="flex-grow">
						<label class="flabel" for="title">Location</label>
						<input
							class="finput"
							id="location"
							bind:value={applicationStore.all[activeItem].location}
							onchange={save}
						/>
					</fieldset>
				</div>
				<div>
					<div class="flabel">Tags</div>
					<div class="flex gap-2 flex-wrap">
						{#each derivedItem.flairs as item}
							<Flair
								{item}
								allowDelete
								application={derivedItem}
								updateApplication={(item) => (applicationStore.all[activeItem ?? -1] = item)}
							/>
						{/each}
					</div>
				</div>
				<fieldset>
					<label class="flabel" for="extra">Extra Info</label>
					<textarea
						class="finput"
						id="extra"
						bind:value={applicationStore.all[activeItem].extra_data}
						onchange={save}
					></textarea>
				</fieldset>
				<fieldset>
					<label class="flabel" for="extra">Message</label>
					<textarea
						class="finput"
						id="extra"
						bind:value={applicationStore.all[activeItem].message}
						onchange={save}
					></textarea>
				</fieldset>
			</div>
			<div class="flex btns">
				<button
					class="btn-confirm"
					onclick={() => {
						openWindow(derivedItem!.url);
					}}
				>
					Open
				</button>
				<button class="btn-primary" onclick={() => openCV()}> Open CV </button>
				<div class="px-10"></div>
				<button class="btn-primary" onclick={() => extractTokens.showModal()}>
					Extract Flair
				</button>
				{#if lastExtData !== undefined}
					<button class="btn-primary" onclick={() => setExtData()}> Ext Data </button>
				{:else}
					<button
						class="btn-primary"
						onclick={() => {
							autoExtData = true;
							window.postMessage({ type: 'R_GET_DATA_FROM_PAGE' });
						}}
					>
						Get Ext Data
					</button>
				{/if}
				<button
					class={derivedItem.simple_url ? 'btn-danger' : 'btn-primary'}
					onclick={() => changeUrl.showModal()}
				>
					Update Url
				</button>
				<div class="px-10"></div>
				<button class="btn-primary" onclick={() => linkApplication.showModal()}>
					Link Application
				</button>
				<button class:btn-primary={drag} class:btn-danger={!drag} onclick={() => (drag = !drag)}>
					👋
				</button>
				<button
					class:btn-primary={!showExtraData}
					class:btn-confirm={showExtraData}
					onclick={() => (showExtraData = !showExtraData)}
				>
					🔬
				</button>
			</div>
			<Timeline application={derivedItem} showAll={showExtraData} />
		</div>
		<AutoDropZone bind:index={activeItem} onremove={remove} />
	{:else}
		<div
			class="p-2 h-full w-full gap-2 flex-grow card grid place-items-center min-h-[50vh]"
			ondragover={(e) => {
				e.preventDefault();
			}}
			ondragenter={preventDefault(() => {})}
			ondrop={() => {
				activate(applicationStore.dragging);
			}}
			role="none"
		>
			<div class="text-center relative">
				<span
					class="bi bi-layers-fill text-7xl text-white absolute"
					class:animate-bounce={applicationStore.dragging}
				></span>
				<span class="bi bi-layers-fill text-7xl text-white opacity-0"></span>
				<div class="text-xl">Drop Application To Manage</div>
			</div>
		</div>
	{/if}
</div>

<ExtractTextDialog
	id={derivedItem?.id ?? ''}
	bind:dialog={extractTokens}
	onreload={() => activate(derivedItem, false)}
/>

{#if derivedItem}
	<NewUrlDialog
		id={derivedItem?.id ?? ''}
		bind:dialog={changeUrl}
		index={activeItem}
		onreload={async (item) => {
			activate(item, false);
		}}
	/>
	<LinkApplication
		application={derivedItem}
		bind:dialog={linkApplication}
		onreload={(item) => activate(item, false)}
	/>
	<FoundExpire
		bind:this={foundExpire}
		bind:index={activeItem}
		onnext={() => {
			appList.requestNext();
		}}
	/>
	<SearchFound bind:this={searchFound} ondelete={() => remove(true)} />
{/if}

<SearchApplication
	application={derivedItem}
	onreload={async (item) => {
		activate(item);
	}}
/>

<NewApplication onreload={activate} />
