<script lang="ts">
	import { onDestroy, onMount } from 'svelte';
	import { fade, fly, slide } from 'svelte/transition';

	import { info, error } from '@tauri-apps/plugin-log';
	import { ask, message } from '@tauri-apps/plugin-dialog';
	import { check, Update } from '@tauri-apps/plugin-updater';
	import { getVersion, getTauriVersion } from '@tauri-apps/api/app';
	import { invoke } from '@tauri-apps/api/core';
	import { sendNotification } from '@tauri-apps/plugin-notification';
	import { isEnabled, enable } from '@tauri-apps/plugin-autostart';
	import { writeText } from '@tauri-apps/plugin-clipboard-manager';
	import { platform } from '@tauri-apps/plugin-os';

	import { toast } from 'svelte-french-toast';
	import { awaiter } from '$lib/utils';
	import type { Config, SyncData } from '$lib/types';

	// --- App State ---
	let loadingSync = true;
	let upToDate: boolean | null = null;
	let updateData: Update | null = null;
	let versionData = { appVersion: 'Loading...', tauriVersion: 'Loading...' };

	// --- Sync State ---
	let syncState = {
		show: false,
		syncing: false,
		success: false,
		error: false,
		url: '',
		message: ''
	};
	let syncProgress = {
		currentStep: '',
		percentage: 0,
		current_count: 0,
		total_count: 0,
		complete: false
	};
	let syncStartTime = 0;

	// --- Config & AutoSync ---
	let config: Config | null = null;
	let syncInterval: ReturnType<typeof setInterval> | null = null;
	let isAutoSyncConfigModalOpen = false;
	let canSave = false;

	let autoSyncConfig = { interval: 0, syncToken: '', didRunInitialValidation: false };
	let autoSyncConfigState = { validatingToken: false, tokenValid: false };

	onMount(async () => {
		info('[FanslySync::page_init] Initializing...');

		const [cfg, cfgErr] = await awaiter(invoke('get_config') as Promise<Config>);
		if (cfgErr || !cfg) return await handleInitError(cfgErr);

		config = cfg;
		autoSyncConfig.interval = cfg.sync_interval;
		autoSyncConfig.syncToken = cfg.sync_token;

		const status = await check();
		upToDate = status === null;
		updateData = status;

		versionData.appVersion = await getVersion();
		versionData.tauriVersion = await getTauriVersion();

		scheduleAutoSync();

		loadingSync = false;
		info('[FanslySync::page_init] Initialization complete.');
	});

	async function handleInitError(err: unknown) {
		error(`[Init Error] ${err}`);
		await message(`Failed to load configuration. Error: ${err}`, { kind: 'error' });
		await writeText(String(err));
		invoke('quit', { code: 1 });
	}

	function scheduleAutoSync() {
		syncInterval && clearInterval(syncInterval);
		syncInterval = setInterval(runAutoSync, (config?.sync_interval ?? 1) * 3600000);
	}

	async function runAutoSync() {
		if (!config?.auto_sync_enabled) return;
		info('[AutoSync] Starting...');
		const nextTime = new Date(Date.now() + config.sync_interval * 3600000).toLocaleTimeString();

		const data = await syncNow(true);
		if (!data) return;

		const [_, uploadErr] = await awaiter(
			invoke('fansly_upload_auto_sync_data', { token: config.sync_token, data })
		);
		if (uploadErr) {
			error('[AutoSync] Upload failed');
			sendNotification({
				title: 'Auto Sync Failed',
				body: `We failed to upload your data. ${uploadErr}. We will try again in ${config.sync_interval} hours.`
			});
		} else {
			sendNotification({
				title: 'Auto Sync Successful',
				body: `Your data has been uploaded successfully. Next sync will be at ${nextTime}.`
			});
		}
	}

	async function syncNow(auto = false): Promise<SyncData | null> {
		syncState = { show: true, syncing: true, success: false, error: false, url: '', message: '' };
		syncStartTime = Date.now();
		const thread = setInterval(updateProgress, 500);

		const [data, err] = await awaiter(invoke('fansly_sync', { auto }) as Promise<SyncData>);
		clearInterval(thread);

		if (err || !data) {
			syncState = { ...syncState, syncing: false, error: true, message: String(err) };
			sendNotification({ title: 'Sync Failed', body: String(err) });
			return null;
		}

		syncState.url = data.sync_data_url;
		config!.last_sync = Date.now();
		config!.last_sync_data = data;
		await saveConfig();

		syncState = { ...syncState, syncing: false, success: true };
		!auto && sendNotification({ title: 'Sync Successful', body: 'Check app for details.' });
		auto && setTimeout(() => (syncState.show = false), 5000);

		return auto ? data : null;
	}

	async function updateProgress() {
		const [p] = await awaiter<{
			current_step: string;
			percentage_done: number;
			current_count: number;
			total_count: number;
			complete: boolean;
		}>(invoke('fansly_get_sync_status'));
		if (p) {
			syncProgress.currentStep = p.current_step;
			syncProgress.percentage = p.percentage_done;
			syncProgress.current_count = p.current_count;
			syncProgress.total_count = p.total_count;
		}
	}

	async function saveConfig() {
		const [_, err] = await awaiter(invoke('save_config', { config }));
		err && error('[SaveConfig] ' + err);
	}

	async function doUpdate() {
		if (updateData === null) {
			return message(`Up to date! v${versionData.appVersion}`, { kind: 'info' });
		}

		const confirm = await ask(
			`A new version (v${updateData?.version}) is available. Do you want to update?`,
			{
				title: 'Update Available',
				kind: 'warning'
			}
		);

		if (confirm) {
			await updateData.downloadAndInstall();
			invoke('quit', { code: 0 });
		}
	}

	async function enableAutoSync() {
		if (!(await isEnabled())) {
			const confirm = await ask(
				"We've detected that auto-start is disabled. It's required for auto-sync to work. Do you want to enable it?",
				{
					title: 'Auto Sync Setup',
					kind: 'info'
				}
			);
			if (!confirm) return;
			await toast.promise(enable(), {
				loading: 'Enabling...',
				success: 'Enabled!',
				error: 'Failed'
			});
		}
		if (!config?.sync_token)
			return message('Set a sync token first.', {
				kind: 'error',
				title: 'Auto Sync Setup | Error'
			});
		config!.auto_sync_enabled = !config.auto_sync_enabled;
		await saveConfig();
		config.auto_sync_enabled ? scheduleAutoSync() : syncInterval && clearInterval(syncInterval);
		toast.success(`${config.auto_sync_enabled ? 'Enabled' : 'Disabled'} Auto Sync`);
	}

	async function onSyncTokenEntered() {
		autoSyncConfigState.validatingToken = true;
		const [_, err] = await awaiter(
			invoke('fansly_check_sync_token', { token: autoSyncConfig.syncToken })
		);
		autoSyncConfigState.validatingToken = false;
		autoSyncConfigState.tokenValid = !err;
		canSave = autoSyncConfigState.tokenValid;
	}

	async function onAutoSyncSave() {
		isAutoSyncConfigModalOpen = false;
		autoSyncConfig.didRunInitialValidation = false;
		config!.sync_interval = autoSyncConfig.interval;
		config!.sync_token = autoSyncConfig.syncToken;
		await saveConfig();
		toast.success('Settings saved');
	}

	onDestroy(() => syncInterval && clearInterval(syncInterval));

	$: if (isAutoSyncConfigModalOpen && !autoSyncConfig.didRunInitialValidation) {
		onSyncTokenEntered();
		autoSyncConfig.didRunInitialValidation = true;
	}

	function useDebounce(fn: Function, delay: number) {
		let timeout: ReturnType<typeof setTimeout>;
		return (...args: any[]) => {
			clearTimeout(timeout);
			timeout = setTimeout(() => fn(...args), delay);
		};
	}
</script>

<div class="min-h-screen bg-zinc-900 text-zinc-200 flex flex-col">
	<!-- Header -->
	<header class="flex items-center justify-between px-6 py-4 bg-zinc-800 shadow">
		<div class="flex items-center space-x-3">
			<img src="/fanslySync.png" alt="FanslySync" class="w-8 h-8" />
			<div>
				<h1 class="text-2xl font-semibold">FanslySync</h1>
				<span class="text-sm text-zinc-400">
					v{versionData.appVersion} · Tauri {versionData.tauriVersion}
				</span>
			</div>
		</div>
		<button
			on:click={doUpdate}
			class="text-sm font-medium px-3 py-1 rounded hover:bg-zinc-700 transition"
			class:text-green-400={upToDate === true}
			class:text-red-400={upToDate === false}
		>
			{#if upToDate === true}Up to date!{:else if upToDate === false}Update available!{/if}
		</button>
	</header>

	<!-- Main Content -->
	<main class="flex-1 overflow-auto p-6 space-y-6">
		<!-- Loading / Error State -->
		{#if loadingSync}
			<div class="flex items-center justify-center p-10 text-zinc-400 space-x-3">
				<svg
					xmlns="http://www.w3.org/2000/svg"
					fill="none"
					viewBox="0 0 24 24"
					stroke-width="1.5"
					stroke="currentColor"
					class="size-8 animate-spin"
				>
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
					/>
				</svg>
				<span>Preparing, this shouldn't take long.</span>
			</div>
		{:else if config === null}
			<div class="flex flex-col items-center justify-center p-10 text-zinc-400 space-x-3">
				<svg
					xmlns="http://www.w3.org/2000/svg"
					fill="none"
					viewBox="0 0 24 24"
					stroke-width="1.5"
					stroke="currentColor"
					class="size-8 text-yellow-400"
				>
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"
					/>
				</svg>
				<span> We couldn't load your config or your configuration doesn't exist.</span>
				<p class="text-sm text-zinc-400">
					Please restart the app or use the button below to reconfigure.
				</p>
				<button
					class="mt-4 px-4 py-2 bg-blue-600 rounded hover:bg-blue-500 transition text-white"
					on:click={() => (window.location.href = '/setup')}
				>
					Reconfigure
				</button>
			</div>
		{:else if config !== null && !loadingSync}
			<!-- Sync Controls -->
			<section class="grid grid-cols-1 md:grid-cols-2 gap-6">
				<!-- Auto Sync Card -->
				<div class="bg-zinc-800 p-6 rounded-lg shadow">
					<div class="flex justify-between items-center mb-2">
						<h2 class="text-xl font-semibold">Automatic Sync</h2>
						<span
							class="px-2 py-1 text-xs font-medium rounded"
							class:bg-green-600={config?.auto_sync_enabled}
							class:bg-red-600={!config?.auto_sync_enabled}
						>
							{config?.auto_sync_enabled ? 'Enabled' : 'Disabled'}
						</span>
					</div>
					<p class="text-zinc-400 mb-4">
						Your data will be automatically synced to your configured Discord server every {config?.sync_interval}
						{config?.sync_interval === 1 ? 'hour' : 'hours'}
					</p>
					<div class="flex space-x-4">
						<button
							class="flex-1 py-2 rounded font-medium transition hover:opacity-90"
							class:bg-green-600={!config?.auto_sync_enabled}
							class:bg-red-600={config?.auto_sync_enabled}
							on:click={enableAutoSync}
							disabled={syncState.syncing}
						>
							{syncState.syncing
								? 'Syncing…'
								: config?.auto_sync_enabled
									? 'Disable Auto Sync'
									: 'Enable Auto Sync'}
						</button>
						<button
							class="flex-1 py-2 bg-zinc-700 rounded font-medium transition hover:opacity-90"
							on:click={() => (isAutoSyncConfigModalOpen = true)}
							disabled={config?.auto_sync_enabled || syncState.syncing}
						>
							Edit Settings
						</button>
					</div>
				</div>

				<!-- Manual Sync Card -->
				<div class="bg-zinc-800 p-6 rounded-lg shadow">
					<h2 class="text-xl font-semibold mb-2">Manual Sync</h2>
					<p class="text-zinc-400 mb-4">Trigger a sync immediately.</p>
					<button
						class="w-full py-2 bg-blue-600 rounded font-medium transition hover:bg-blue-500 disabled:opacity-50"
						on:click={() => syncNow(false)}
						disabled={syncState.syncing}
					>
						{syncState.syncing ? 'Syncing…' : 'Sync Now'}
					</button>
				</div>
			</section>
		{/if}
	</main>

	<!-- Progress Bar & Status -->
	{#if syncState.show}
		<div class="fixed bottom-0 left-0 right-0">
			<div
				class="fixed bottom-0 left-0 right-0 h-16 overflow-hidden"
				transition:slide={{ duration: 500 }}
			>
				<!-- Background track -->
				<div class="absolute inset-0 bg-zinc-800"></div>

				<!-- Fill using message box background -->
				<div
					class={`absolute inset-y-0 left-0 transition-all duration-500 ease-in-out
        ${syncState.syncing ? 'bg-blue-500' : 'bg-zinc-800'}`}
					style="width: {syncState.syncing
						? `${syncProgress.percentage === 0 ? 2 : syncProgress.percentage}%`
						: '100%'};"
				></div>

				<!-- Message Box Content -->
				<div class="relative z-10 flex items-center h-full px-4 text-white">
					{#if syncState.syncing}
						<svg
							xmlns="http://www.w3.org/2000/svg"
							fill="none"
							viewBox="0 0 24 24"
							stroke-width="1.5"
							stroke="currentColor"
							class="w-6 h-6 animate-spin mr-3"
						>
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
							/>
						</svg>
						<div>
							<p class="font-medium">Syncing… {syncProgress.percentage}%</p>
							<p class="text-sm">
								{syncProgress.current_count} / {syncProgress.total_count} • {syncProgress.currentStep}
							</p>
						</div>
					{:else if syncState.success}
						<div class="flex flex-col">
							<p class="font-medium">Sync Successful!</p>
							<p class="text-sm">Use Copy to grab URL.</p>
						</div>
						<div class="ml-auto flex space-x-2">
							<button
								class="px-3 py-1 bg-zinc-800 rounded"
								on:click={() => writeText(syncState.url)}>Copy</button
							>
							<button
								class="px-3 py-1 bg-zinc-800 rounded"
								on:click={() => (syncState.show = false)}>Close</button
							>
						</div>
					{:else}
						<div class="flex flex-col">
							<p class="font-medium">Sync Failed!</p>
							<p class="text-sm">{syncState.message}</p>
						</div>
						<button
							class="ml-auto px-3 py-1 bg-zinc-800 rounded"
							on:click={() => (syncState.show = false)}>Close</button
						>
					{/if}
				</div>
			</div>
		</div>
	{/if}

	<!-- Auto Sync Modal -->
	{#if isAutoSyncConfigModalOpen}
		<div
			class="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center"
			transition:fade
		>
			<div
				class="bg-zinc-800 p-6 rounded-lg w-full max-w-md"
				in:fly={{ y: 20 }}
				out:fly={{ y: 20 }}
			>
				<h3 class="text-xl font-semibold mb-4 flex items-center space-x-2">
					<!-- Cog Icon -->
					<svg
						xmlns="http://www.w3.org/2000/svg"
						fill="none"
						viewBox="0 0 24 24"
						stroke-width="1.5"
						stroke="currentColor"
						class="w-6 h-6"
					>
						<path
							stroke-linecap="round"
							stroke-linejoin="round"
							d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0
               1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257
               1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296
               2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723
               7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26
               1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47
               6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213
               1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52
               6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125
               1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932
               6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125
               1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072
               1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z"
						/>
						<path
							stroke-linecap="round"
							stroke-linejoin="round"
							d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
						/>
					</svg>
					<span>Auto Sync Settings</span>
				</h3>

				<div class="space-y-4">
					<!-- Interval Field -->
					<div>
						<label for="interval" class="block text-sm mb-1">Interval (hours)</label>
						<input
							id="interval"
							type="number"
							bind:value={autoSyncConfig.interval}
							min="1"
							class="w-full p-2 bg-zinc-700 rounded"
						/>
						<p class="text-xs text-zinc-400 mt-1">
							How often (in hours) the app will automatically sync.
						</p>
					</div>

					<!-- Token Field -->
					<div>
						<label for="syncToken" class="block text-sm mb-1">Sync Token</label>
						<div class="relative">
							<input
								id="syncToken"
								type="text"
								bind:value={autoSyncConfig.syncToken}
								on:input={useDebounce(onSyncTokenEntered, 500)}
								class="w-full p-2 bg-zinc-700 rounded pr-10"
							/>

							{#if autoSyncConfigState.validatingToken}
								<!-- Spinner Icon -->
								<svg
									xmlns="http://www.w3.org/2000/svg"
									fill="none"
									viewBox="0 0 24 24"
									stroke-width="1.5"
									stroke="currentColor"
									class="absolute right-2 bottom-2 w-6 h-6 animate-spin text-zinc-400"
								>
									<path
										stroke-linecap="round"
										stroke-linejoin="round"
										d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0
                     0h4.992m-4.993 0 3.181 3.183a8.25 8.25
                     0 0 0 13.803-3.7M4.031 9.865a8.25 8.25
                     0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
									/>
								</svg>
							{:else if autoSyncConfigState.tokenValid}
								<!-- Check Icon -->
								<svg
									xmlns="http://www.w3.org/2000/svg"
									fill="none"
									viewBox="0 0 24 24"
									stroke-width="1.5"
									stroke="currentColor"
									class="absolute right-2 bottom-2 w-6 h-6 text-green-400"
								>
									<path
										stroke-linecap="round"
										stroke-linejoin="round"
										d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0
                     1 1-18 0 9 9 0 0 1 18 0Z"
									/>
								</svg>
							{:else}
								<!-- X Icon -->
								<svg
									xmlns="http://www.w3.org/2000/svg"
									fill="none"
									viewBox="0 0 24 24"
									stroke-width="1.5"
									stroke="currentColor"
									class="absolute right-2 bottom-2 w-6 h-6 text-red-400"
								>
									<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
								</svg>
							{/if}
						</div>
						<p class="text-xs text-zinc-400 mt-1">
							Enter your Fansly sync-token. We’ll validate it before saving.
						</p>
					</div>
				</div>

				<div class="mt-6 flex justify-end space-x-3">
					<button
						class="px-4 py-2 bg-zinc-700 rounded hover:bg-zinc-600"
						on:click={() => (isAutoSyncConfigModalOpen = false)}
					>
						Cancel
					</button>
					<button
						class="px-4 py-2 bg-blue-600 rounded hover:bg-blue-500 disabled:opacity-50"
						on:click={onAutoSyncSave}
						disabled={!canSave}
					>
						Save
					</button>
				</div>
			</div>
		</div>
	{/if}
</div>
