<svelte:options runes={true} />

<script lang="ts">
	import Dialog from './ui/Dialog.svelte'
	import ModalBody from './ui/ModalBody.svelte'
	import ModalFooter from './ui/ModalFooter.svelte'
	import SettingsNav, { type ElementType } from './ui/SettingsNav.svelte'
	import AccountSettings from './settings/AccountSettings.svelte'
	import ProfileSettings from './settings/ProfileSettings.svelte'
	import PrivacySettings from './settings/PrivacySettings.svelte'
	import { users } from '$lib/api/resources/users'
	import type { UserCookie } from '$lib/types/UserCookie'
	import { invalidateAll } from '$app/navigation'
	import { createQuery } from '@tanstack/svelte-query'
	import { crewQueries } from '$lib/api/queries/crew.queries'
	import { userAdapter } from '$lib/api/adapters/user.adapter'

	interface Props {
		open: boolean
		onOpenChange?: (open: boolean) => void
		username: string
		userId: string
		user: UserCookie
		role: number
	}

	let { open = $bindable(false), onOpenChange, username, userId, user, role }: Props = $props()

	// Active section for navigation
	let activeSection = $state<string>('profile')

	// Form state - Account section (initialized empty, populated from API)
	let formUsername = $state(username)
	let formEmail = $state('')
	let currentPassword = $state('')
	let newPassword = $state('')
	let confirmPassword = $state('')
	let bahamut = $state(user.bahamut ?? false) // Client-side preference, kept in cookie

	// Form state - Profile section (initialized with defaults, populated from API)
	let picture = $state('')
	let element = $state<ElementType>('wind')
	let granblueId = $state('')
	let gender = $state(0)
	let language = $state('en')
	let theme = $state('system')

	// Form state - Privacy section (initialized with defaults, populated from API)
	let showGranblueId = $state(false)
	let collectionPrivacy = $state(1) // 1 = Everyone (1-based to avoid JS falsy 0)
	let showCrewGamertag = $state(false)

	// Track whether form has been initialized from API
	let formInitialized = $state(false)

	// Store original values from API for comparison on save
	let originalLanguage = $state('')
	let originalTheme = $state('')

	let saving = $state(false)
	let error = $state<string | null>(null)
	let contentElement: HTMLElement | undefined = $state()
	let isScrolledToBottom = $state(true)

	// Fetch current user data from API
	const currentUserQuery = createQuery(() => ({
		queryKey: ['currentUser', 'settings'],
		queryFn: () => userAdapter.getCurrentUser(),
		enabled: open, // Only fetch when modal is open
		staleTime: 0 // Always refetch when modal opens to ensure fresh data
	}))

	// Fetch current user's crew (for showing gamertag toggle)
	const myCrewQuery = createQuery(() => ({
		...crewQueries.myCrew(),
		enabled: open // Only fetch when modal is open
	}))

	const isInCrew = $derived(!!myCrewQuery.data)
	const crewGamertag = $derived(myCrewQuery.data?.gamertag ?? undefined)
	const isLoading = $derived(currentUserQuery.isPending && !formInitialized)

	// Populate form state when API returns data
	$effect(() => {
		if (currentUserQuery.data && !formInitialized) {
			const data = currentUserQuery.data
			console.log('[UserSettingsModal] API data received:', data)
			console.log('[UserSettingsModal] data.collectionPrivacy:', data.collectionPrivacy, typeof data.collectionPrivacy)
			// Account
			formEmail = data.email ?? ''
			// Profile
			picture = data.avatar?.picture ?? ''
			element = (data.avatar?.element as ElementType) ?? 'wind'
			granblueId = data.granblueId ?? ''
			gender = data.gender ?? 0
			language = data.language ?? 'en'
			theme = data.theme ?? 'system'
			// Privacy
			showGranblueId = data.showGranblueId ?? false
			collectionPrivacy = data.collectionPrivacy ?? 1
			console.log('[UserSettingsModal] collectionPrivacy set to:', collectionPrivacy, typeof collectionPrivacy)
			showCrewGamertag = data.showCrewGamertag ?? false
			// Store original values for comparison
			originalLanguage = data.language ?? 'en'
			originalTheme = data.theme ?? 'system'
			formInitialized = true
		}
	})

	// Reset form initialized state when modal closes
	$effect(() => {
		if (!open) {
			formInitialized = false
		}
	})

	// Navigation items
	const navItems = [
		{ value: 'account', label: 'Account' },
		{ value: 'profile', label: 'Profile' },
		{ value: 'privacy', label: 'Privacy' }
	]

	// Check if scrolled to bottom
	function checkScrollPosition() {
		if (!contentElement) return
		const { scrollTop, scrollHeight, clientHeight } = contentElement
		// Consider "at bottom" if within 5px of the bottom
		isScrolledToBottom = scrollTop + clientHeight >= scrollHeight - 5
	}

	// Check scroll position when content element is bound or section changes
	$effect(() => {
		if (contentElement) {
			// Small delay to let content render
			setTimeout(checkScrollPosition, 0)
		}
	})

	// Re-check when section changes
	$effect(() => {
		activeSection // Track this dependency
		if (contentElement) {
			setTimeout(checkScrollPosition, 0)
		}
	})

	// Handle form submission
	async function handleSave() {
		error = null
		saving = true

		try {
			// Prepare the update data
			const updateData: Parameters<typeof users.update>[1] = {
				picture,
				element,
				gender,
				language,
				theme,
				granblueId: granblueId || undefined,
				showCrewGamertag,
				showGranblueId,
				collectionPrivacy
			}

			// Call API to update user settings
			const response = await users.update(userId, updateData)

			// Update the user cookie
			const updatedUser: UserCookie = {
				picture: response.avatar.picture,
				element: response.avatar.element,
				language: response.language,
				gender: response.gender,
				theme: response.theme,
				bahamut,
				granblueId: response.granblueId,
				showCrewGamertag: response.showCrewGamertag,
				showGranblueId: response.showGranblueId,
				collectionPrivacy: response.collectionPrivacy
			}

			// Make a request to update the cookie server-side
			await fetch('/api/settings', {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json'
				},
				body: JSON.stringify(updatedUser)
			})

			// If language, theme, or bahamut mode changed, we need a full page reload
			if (originalLanguage !== language || originalTheme !== theme || user.bahamut !== bahamut) {
				await invalidateAll()
				window.location.reload()
			} else {
				// For other changes (element, picture, gender), invalidate to refresh layout data
				await invalidateAll()
			}

			// Close the modal
			handleClose()
		} catch (err) {
			console.error('Failed to update settings:', err)
			error = 'Failed to update settings. Please try again.'
		} finally {
			saving = false
		}
	}

	function handleClose() {
		open = false
		onOpenChange?.(false)
	}
</script>

<Dialog bind:open {...onOpenChange ? { onOpenChange } : {}} size="medium" hideClose>
	{#snippet children()}
		<ModalBody noPadding>
			<div class="settings-layout">
				{#if error}
					<div class="error-message">{error}</div>
				{/if}

				<aside class="settings-sidebar">
					<div class="sidebar-header">
						<h2 class="title">Settings</h2>
						<p class="username">@{username}</p>
					</div>
					<SettingsNav
						bind:value={activeSection}
						{element}
						items={navItems}
					/>
				</aside>

				<main class="settings-content" bind:this={contentElement} onscroll={checkScrollPosition}>
					{#if isLoading}
						<div class="loading-state">
							<div class="spinner"></div>
							<span>Loading settings...</span>
						</div>
					{:else if activeSection === 'account'}
						<AccountSettings
							username={formUsername}
							email={formEmail}
							{currentPassword}
							{newPassword}
							{confirmPassword}
							{bahamut}
							{role}
							{element}
							onUsernameChange={(v) => (formUsername = v)}
							onEmailChange={(v) => (formEmail = v)}
							onCurrentPasswordChange={(v) => (currentPassword = v)}
							onNewPasswordChange={(v) => (newPassword = v)}
							onConfirmPasswordChange={(v) => (confirmPassword = v)}
							onBahamutChange={(v) => (bahamut = v)}
						/>
					{:else if activeSection === 'profile'}
						<ProfileSettings
							{picture}
							{element}
							{granblueId}
							{gender}
							{language}
							{theme}
							onPictureChange={(v) => (picture = v)}
							onElementChange={(v) => (element = v as ElementType)}
							onGranblueIdChange={(v) => (granblueId = v)}
							onGenderChange={(v) => (gender = v)}
							onLanguageChange={(v) => (language = v)}
							onThemeChange={(v) => (theme = v)}
						/>
					{:else if activeSection === 'privacy'}
						<PrivacySettings
							{showGranblueId}
							{collectionPrivacy}
							{showCrewGamertag}
							{isInCrew}
							{crewGamertag}
							{element}
							onShowGranblueIdChange={(v) => (showGranblueId = v)}
							onCollectionPrivacyChange={(v) => (collectionPrivacy = v)}
							onShowCrewGamertagChange={(v) => (showCrewGamertag = v)}
						/>
					{/if}
				</main>
			</div>
		</ModalBody>

		<ModalFooter
			onCancel={handleClose}
			cancelDisabled={saving}
			primaryAction={{
				label: saving ? 'Saving...' : 'Save Changes',
				onclick: handleSave,
				disabled: saving || isLoading
			}}
			showShadow={!isScrolledToBottom}
		/>
	{/snippet}
</Dialog>

<style lang="scss">
	@use '$src/themes/spacing' as spacing;
	@use '$src/themes/colors' as colors;
	@use '$src/themes/typography' as typography;
	@use '$src/themes/layout' as layout;

	.settings-layout {
		display: flex;
		height: 480px;
	}

	.error-message {
		background-color: rgba(colors.$error, 0.1);
		border: 1px solid colors.$error;
		border-radius: layout.$card-corner;
		color: colors.$error;
		padding: spacing.$unit-2x;
		margin-bottom: spacing.$unit-2x;
		width: 100%;
	}

	.settings-sidebar {
		flex-shrink: 0;
		padding: spacing.$unit;
		padding-right: 0;
		display: flex;
		flex-direction: column;
		gap: spacing.$unit-2x;
	}

	.sidebar-header {
		padding: spacing.$unit spacing.$unit-2x;

		.title {
			font-size: typography.$font-large;
			font-weight: typography.$medium;
			color: var(--text-primary);
			margin: 0;
		}

		.username {
			font-size: typography.$font-small;
			color: var(--text-secondary);
			margin: 0;
			margin-top: spacing.$unit-half;
		}
	}

	.settings-content {
		flex: 1;
		overflow-y: auto;
		padding: spacing.$unit-3x;
	}

	.loading-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		height: 100%;
		gap: spacing.$unit-2x;
		color: var(--text-secondary);
	}

	.spinner {
		width: 24px;
		height: 24px;
		border: 2px solid var(--border-color);
		border-top-color: var(--text-secondary);
		border-radius: 50%;
		animation: spin 0.8s linear infinite;
	}

	@keyframes spin {
		to {
			transform: rotate(360deg);
		}
	}

	:global(fieldset) {
		border: none;
		padding: 0;
		margin: 0;
	}
</style>
