<svelte:options runes={true} />

<script lang="ts">
	import { goto } from '$app/navigation'
	import { entityAdapter, type CharacterSuggestions } from '$lib/api/adapters/entity.adapter'
	import { fetchWikiPages, buildWikiDataMap } from '$lib/api/wiki'
	import { getGameCdnCharacterImage, getPlaceholderImage } from '$lib/utils/images'
	import {
		buildWikiEnUrl,
		buildWikiJaUrl,
		buildGamewithUrl,
		buildKamigameUrl
	} from '$lib/utils/external-links'

	// Components
	import CharacterUncapSection from '$lib/features/database/characters/sections/CharacterUncapSection.svelte'
	import CharacterTaxonomySection from '$lib/features/database/characters/sections/CharacterTaxonomySection.svelte'
	import CharacterStatsSection from '$lib/features/database/characters/sections/CharacterStatsSection.svelte'
	import CharacterMetadataSection from '$lib/features/database/characters/sections/CharacterMetadataSection.svelte'
	import TabbedEntitySelector from '$lib/features/database/import/TabbedEntitySelector.svelte'
	import type { EntityTab } from '$lib/features/database/import/TabbedEntitySelector.svelte'
	import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
	import DetailItem from '$lib/components/ui/DetailItem.svelte'
	import SuggestionDetailItem from '$lib/components/ui/SuggestionDetailItem.svelte'
	import SidebarHeader from '$lib/components/ui/SidebarHeader.svelte'
	import Button from '$lib/components/ui/Button.svelte'
	import Input from '$lib/components/ui/Input.svelte'
	import Icon from '$lib/components/Icon.svelte'
	import TagInput from '$lib/components/ui/TagInput.svelte'

	import type { PageData } from './$types'

	// Internal entity state including loading status
	interface EntityState {
		wikiPage: string
		status: 'loading' | 'success' | 'error'
		granblueId?: string
		suggestions?: CharacterSuggestions
		wikiRaw?: string
		error?: string
	}

	let { data }: { data: PageData } = $props()

	// Input phase
	let wikiPagesInputs = $state<string[]>(['', '', ''])
	let isFetching = $state(false)
	let fetchError = $state<string | null>(null)

	// Fetched entities
	let entities = $state<Map<string, EntityState>>(new Map())
	let selectedWikiPage = $state<string | null>(null)

	// Form data per entity (keyed by wikiPage) - using Record for proper reactivity
	let formDataByPage = $state<Record<string, any>>({})
	let dismissedByPage = $state<Record<string, Set<string>>>({})
	let savedEntities = $state<Set<string>>(new Set())

	// Store wiki raw data per entity for sending with create request
	let wikiRawByPage = $state<Record<string, string>>({})

	// Saving state
	let isSaving = $state(false)
	let saveError = $state<string | null>(null)

	// Empty character for form sections
	const emptyCharacter = {
		id: '',
		name: { en: '', jp: '' },
		granblueId: '',
		characterId: '',
		rarity: 3,
		element: 0,
		race: [],
		gender: 0,
		proficiency: [0, 0],
		hp: { minHp: 0, maxHp: 0, maxHpFlb: 0 },
		atk: { minAtk: 0, maxAtk: 0, maxAtkFlb: 0 },
		uncap: { flb: false, ulb: false, transcendence: false },
		special: false
	}

	// Get selected entity data
	const selectedEntity = $derived(selectedWikiPage ? entities.get(selectedWikiPage) : null)

	// Entity tabs for TabbedEntitySelector
	const entityTabs = $derived<EntityTab[]>(
		Array.from(entities.entries()).map(([wikiPage, entity]) => ({
			wikiPage,
			granblueId: entity.granblueId,
			status: entity.status,
			imageUrl: entity.granblueId
				? getGameCdnCharacterImage(entity.granblueId)
				: getPlaceholderImage('character', 'square'),
			error: entity.error,
			saved: savedEntities.has(wikiPage)
		}))
	)

	// Initialize empty form data for an entity
	function createEmptyFormData(wikiPage: string, suggestions?: CharacterSuggestions) {
		return {
			name: suggestions?.nameEn ?? '',
			nameJp: suggestions?.nameJp ?? '',
			granblueId: suggestions?.granblueId ?? '',
			characterId: suggestions?.characterId?.join(', ') ?? '',
			rarity: suggestions?.rarity ?? 3,
			element: suggestions?.element ?? 0,
			race1: suggestions?.race1 ?? null,
			race2: suggestions?.race2 ?? null,
			gender: suggestions?.gender ?? 0,
			proficiency1: suggestions?.proficiency1 ?? 0,
			proficiency2: suggestions?.proficiency2 ?? 0,
			season: null as number | null,
			series: suggestions?.series ?? ([] as number[]),
			promotions: [] as number[],
			gacha_available: true,
			minHp: suggestions?.minHp ?? 0,
			maxHp: suggestions?.maxHp ?? 0,
			maxHpFlb: suggestions?.maxHpFlb ?? 0,
			maxHpUlb: 0,
			minAtk: suggestions?.minAtk ?? 0,
			maxAtk: suggestions?.maxAtk ?? 0,
			maxAtkFlb: suggestions?.maxAtkFlb ?? 0,
			maxAtkUlb: 0,
			baseDa: 0,
			baseTa: 0,
			ougiRatio: 0,
			ougiRatioFlb: 0,
			flb: suggestions?.flb ?? false,
			ulb: suggestions?.ulb ?? false,
			transcendence: false,
			special: false,
			releaseDate: suggestions?.releaseDate ?? '',
			flbDate: suggestions?.flbDate ?? '',
			ulbDate: suggestions?.ulbDate ?? '',
			wikiEn: wikiPage ? wikiPage.replace(/ /g, '_') : '',
			wikiJa: '',
			gamewith: suggestions?.gamewith ?? '',
			kamigame: suggestions?.kamigame ?? '',
			nicknamesEn: [] as string[],
			nicknamesJp: [] as string[]
		}
	}

	// Add/remove input fields
	function addInput() {
		wikiPagesInputs = [...wikiPagesInputs, '']
	}

	function removeInput(index: number) {
		if (wikiPagesInputs.length > 1) {
			wikiPagesInputs = wikiPagesInputs.filter((_, i) => i !== index)
		}
	}

	// Fetch wiki data for entered pages
	async function fetchWikiData() {
		const pages = wikiPagesInputs
			.map((p) => p.trim())
			.filter((p) => p.length > 0)
			.slice(0, 10)

		if (pages.length === 0) {
			fetchError = 'Please enter at least one wiki page name'
			return
		}

		isFetching = true
		fetchError = null

		// Initialize entities as loading
		const newEntities = new Map<string, EntityState>()
		pages.forEach((page) => {
			newEntities.set(page, {
				wikiPage: page,
				status: 'loading'
			})
		})
		entities = newEntities
		selectedWikiPage = pages[0] ?? null

		try {
			// Step 1: Fetch wiki data client-side (bypasses CloudFlare)
			const wikiResults = await fetchWikiPages(pages)
			const wikiData = buildWikiDataMap(wikiResults)

			// Store wiki raw data for sending with create request
			wikiRawByPage = { ...wikiData }

			// Update pages array with any redirects
			const finalPages = wikiResults.map((r) => r.wikiPage)

			// Step 2: Send to API for parsing (with pre-fetched wiki data)
			const response = await entityAdapter.batchPreviewCharacters(finalPages, wikiData)

			// Update entities with results
			const updatedEntities = new Map<string, EntityState>()
			response.results.forEach((result) => {
				updatedEntities.set(result.wikiPage, {
					wikiPage: result.wikiPage,
					status: result.status,
					granblueId: result.granblueId,
					suggestions: result.suggestions,
					wikiRaw: result.wikiRaw,
					error: result.error
				})

				// Create form data for successful results
				if (result.status === 'success') {
					formDataByPage[result.wikiPage] = createEmptyFormData(result.wikiPage, result.suggestions)
					dismissedByPage[result.wikiPage] = new Set<string>()
				}
			})
			entities = updatedEntities

			// Trigger reactivity by reassigning
			formDataByPage = { ...formDataByPage }
			dismissedByPage = { ...dismissedByPage }
		} catch (error) {
			console.error('Batch preview error:', error)
			fetchError = 'Failed to fetch wiki data. Please try again.'
		} finally {
			isFetching = false
		}
	}

	// Handle entity selection
	function handleSelectEntity(wikiPage: string) {
		selectedWikiPage = wikiPage
	}

	// Accept a suggestion
	function handleAcceptSuggestion(field: string, value: any) {
		if (!selectedWikiPage || !formDataByPage[selectedWikiPage]) return

		formDataByPage[selectedWikiPage][field] = value
		formDataByPage = { ...formDataByPage }
	}

	// Dismiss a suggestion
	function handleDismissSuggestion(field: string) {
		if (!selectedWikiPage) return

		const dismissed = dismissedByPage[selectedWikiPage] ?? new Set<string>()
		dismissed.add(field)
		dismissedByPage[selectedWikiPage] = dismissed
		dismissedByPage = { ...dismissedByPage }
	}

	// Save current entity
	async function saveCurrentEntity() {
		if (!selectedWikiPage) return
		const formData = formDataByPage[selectedWikiPage]
		if (!formData) return
		const entity = entities.get(selectedWikiPage)

		isSaving = true
		saveError = null

		try {
			const payload = {
				granblue_id: formData.granblueId,
				name_en: formData.name,
				name_jp: formData.nameJp,
				character_id:
					formData.characterId.trim() === ''
						? []
						: formData.characterId
								.split(',')
								.map((id: string) => Number(id.trim()))
								.filter((id: number) => !isNaN(id)),
				rarity: formData.rarity,
				element: formData.element,
				race1: formData.race1,
				race2: formData.race2,
				gender: formData.gender,
				proficiency1: formData.proficiency1,
				proficiency2: formData.proficiency2,
				season: formData.season === 0 ? null : formData.season,
				series: formData.series,
				promotions: formData.promotions,
				gacha_available: formData.gacha_available,
				min_hp: formData.minHp,
				max_hp: formData.maxHp,
				max_hp_flb: formData.maxHpFlb,
				max_hp_ulb: formData.maxHpUlb,
				min_atk: formData.minAtk,
				max_atk: formData.maxAtk,
				max_atk_flb: formData.maxAtkFlb,
				max_atk_ulb: formData.maxAtkUlb,
				base_da: formData.baseDa,
				base_ta: formData.baseTa,
				ougi_ratio: formData.ougiRatio,
				ougi_ratio_flb: formData.ougiRatioFlb,
				flb: formData.flb,
				ulb: formData.ulb,
				special: formData.special,
				release_date: formData.releaseDate || null,
				flb_date: formData.flbDate || null,
				ulb_date: formData.ulbDate || null,
				wiki_en: formData.wikiEn,
				wiki_ja: formData.wikiJa,
				gamewith: formData.gamewith,
				kamigame: formData.kamigame,
				nicknames_en: formData.nicknamesEn,
				nicknames_jp: formData.nicknamesJp,
				wiki_raw: wikiRawByPage[selectedWikiPage] || undefined
			}

			const newCharacter = await entityAdapter.createCharacter(payload)
			// Trigger image download in background (don't await - it queues a job)
			entityAdapter.downloadCharacterImages(newCharacter.id).catch(console.error)
			savedEntities.add(selectedWikiPage)
			savedEntities = new Set(savedEntities)

			// Select next unsaved entity
			const unsaved = entityTabs.find(
				(e) => !savedEntities.has(e.wikiPage) && e.status === 'success'
			)
			if (unsaved) {
				selectedWikiPage = unsaved.wikiPage
			}
		} catch (error) {
			saveError = 'Failed to save character. Please try again.'
			console.error('Save error:', error)
		} finally {
			isSaving = false
		}
	}

	function handleCancel() {
		goto('/database/characters')
	}

	// Can save current entity
	const canSave = $derived.by(() => {
		if (!selectedWikiPage) return false
		const formData = formDataByPage[selectedWikiPage]
		if (!formData) return false
		return (
			formData.name.trim() !== '' &&
			formData.granblueId.trim() !== '' &&
			!savedEntities.has(selectedWikiPage)
		)
	})

	// All entities saved
	const allSaved = $derived(
		entityTabs.length > 0 &&
			entityTabs.filter((e) => e.status === 'success').every((e) => savedEntities.has(e.wikiPage))
	)
</script>

<div class="page">
	<SidebarHeader title="Batch Import Characters">
		{#snippet leftAccessory()}
			<Button variant="secondary" size="small" onclick={handleCancel}>
				{allSaved ? 'Done' : 'Cancel'}
			</Button>
		{/snippet}
		{#snippet rightAccessory()}
			{#if selectedEntity?.status === 'success'}
				<Button
					variant="primary"
					size="small"
					onclick={saveCurrentEntity}
					disabled={!canSave || isSaving}
				>
					{isSaving ? 'Saving...' : 'Save Character'}
				</Button>
			{/if}
		{/snippet}
	</SidebarHeader>

	{#if saveError}
		<div class="error-banner">{saveError}</div>
	{/if}

	<!-- Input phase -->
	{#if entities.size === 0}
		<form class="input-phase" onsubmit={(e) => { e.preventDefault(); fetchWikiData(); }}>
			<p class="hint">Enter up to 10 wiki page names to import data</p>
			<div class="wiki-inputs">
				{#each wikiPagesInputs as _, index}
					<div class="input-row">
						<Input
							bind:value={wikiPagesInputs[index]}
							placeholder="Narmaya_(Summer)"
							contained
							fullWidth
						/>
						{#if wikiPagesInputs.length > 1}
							<button
								type="button"
								class="remove-button"
								onclick={() => removeInput(index)}
								aria-label="Remove input"
							>
								<Icon name="close" size={16} />
							</button>
						{/if}
					</div>
				{/each}
				<Button
					variant="ghost"
					class="add-input-button"
					leftIcon="plus"
					size="small"
					type="button"
					onclick={addInput}
				>
					Add another
				</Button>
			</div>
			{#if fetchError}
				<p class="error">{fetchError}</p>
			{/if}
			<div class="fetch-button">
				<Button variant="primary" type="submit" disabled={isFetching}>
					{isFetching ? 'Fetching...' : 'Fetch data'}
				</Button>
			</div>
		</form>
	{:else}
		<!-- Entity selector -->
		<div class="entity-selector-container">
			<TabbedEntitySelector
				entities={entityTabs}
				{selectedWikiPage}
				onSelect={handleSelectEntity}
				entityType="character"
			/>
		</div>

		<!-- Form for selected entity -->
		{#if selectedEntity}
			{#if selectedEntity.status === 'error'}
				<div class="entity-error">
					<h3>Failed to load: {selectedWikiPage}</h3>
					<p>{selectedEntity.error}</p>
				</div>
			{:else if selectedEntity.status === 'loading'}
				<div class="entity-loading">
					<p>Loading wiki data...</p>
				</div>
			{:else if selectedWikiPage && formDataByPage[selectedWikiPage]}
				{@const suggestions = selectedEntity.suggestions}
				{@const dismissed = dismissedByPage[selectedWikiPage] ?? new Set<string>()}
				<section class="details">
					<DetailsContainer title="Basic Info">
						<SuggestionDetailItem
							label="Name (EN)"
							bind:value={formDataByPage[selectedWikiPage].name}
							editable={true}
							type="text"
							placeholder="Character name"
							suggestion={suggestions?.nameEn}
							dismissedSuggestion={dismissed.has('name')}
							onAcceptSuggestion={() => handleAcceptSuggestion('name', suggestions?.nameEn)}
							onDismissSuggestion={() => handleDismissSuggestion('name')}
						/>
						<SuggestionDetailItem
							label="Name (JP)"
							bind:value={formDataByPage[selectedWikiPage].nameJp}
							editable={true}
							type="text"
							placeholder="キャラクター名"
							suggestion={suggestions?.nameJp}
							dismissedSuggestion={dismissed.has('nameJp')}
							onAcceptSuggestion={() => handleAcceptSuggestion('nameJp', suggestions?.nameJp)}
							onDismissSuggestion={() => handleDismissSuggestion('nameJp')}
						/>
						<DetailItem
							label="Character ID"
							sublabel="Separate multiple IDs with commas"
							bind:value={formDataByPage[selectedWikiPage].characterId}
							editable={true}
							type="text"
							placeholder="Character IDs"
						/>
					</DetailsContainer>

					<CharacterMetadataSection
						character={emptyCharacter}
						editMode={true}
						bind:editData={formDataByPage[selectedWikiPage]}
						{suggestions}
						dismissedSuggestions={dismissed}
						onAcceptSuggestion={handleAcceptSuggestion}
						onDismissSuggestion={handleDismissSuggestion}
					/>

					<CharacterUncapSection
						character={emptyCharacter}
						editMode={true}
						bind:editData={formDataByPage[selectedWikiPage]}
						{suggestions}
						dismissedSuggestions={dismissed}
						onAcceptSuggestion={handleAcceptSuggestion}
						onDismissSuggestion={handleDismissSuggestion}
					/>

					<CharacterTaxonomySection
						character={emptyCharacter}
						editMode={true}
						bind:editData={formDataByPage[selectedWikiPage]}
						{suggestions}
						dismissedSuggestions={dismissed}
						onAcceptSuggestion={handleAcceptSuggestion}
						onDismissSuggestion={handleDismissSuggestion}
					/>

					<CharacterStatsSection
						character={emptyCharacter}
						editMode={true}
						bind:editData={formDataByPage[selectedWikiPage]}
						{suggestions}
						dismissedSuggestions={dismissed}
						onAcceptSuggestion={handleAcceptSuggestion}
						onDismissSuggestion={handleDismissSuggestion}
					/>

					<DetailsContainer title="Nicknames">
						<DetailItem label="Nicknames (EN)">
							<TagInput bind:value={formDataByPage[selectedWikiPage].nicknamesEn} placeholder="Add nickname..." contained />
						</DetailItem>
						<DetailItem label="Nicknames (JP)">
							<TagInput bind:value={formDataByPage[selectedWikiPage].nicknamesJp} placeholder="ニックネーム..." contained />
						</DetailItem>
					</DetailsContainer>

					<DetailsContainer title="Dates">
						<SuggestionDetailItem
							label="Release Date"
							bind:value={formDataByPage[selectedWikiPage].releaseDate}
							editable={true}
							type="text"
							placeholder="YYYY-MM-DD"
							suggestion={suggestions?.releaseDate}
							dismissedSuggestion={dismissed.has('releaseDate')}
							onAcceptSuggestion={() =>
								handleAcceptSuggestion('releaseDate', suggestions?.releaseDate)}
							onDismissSuggestion={() => handleDismissSuggestion('releaseDate')}
						/>
						{#if formDataByPage[selectedWikiPage].flb}
							<SuggestionDetailItem
								label="FLB Date"
								bind:value={formDataByPage[selectedWikiPage].flbDate}
								editable={true}
								type="text"
								placeholder="YYYY-MM-DD"
								suggestion={suggestions?.flbDate}
								dismissedSuggestion={dismissed.has('flbDate')}
								onAcceptSuggestion={() => handleAcceptSuggestion('flbDate', suggestions?.flbDate)}
								onDismissSuggestion={() => handleDismissSuggestion('flbDate')}
							/>
						{/if}
						{#if formDataByPage[selectedWikiPage].ulb}
							<SuggestionDetailItem
								label="ULB Date"
								bind:value={formDataByPage[selectedWikiPage].ulbDate}
								editable={true}
								type="text"
								placeholder="YYYY-MM-DD"
								suggestion={suggestions?.ulbDate}
								dismissedSuggestion={dismissed.has('ulbDate')}
								onAcceptSuggestion={() => handleAcceptSuggestion('ulbDate', suggestions?.ulbDate)}
								onDismissSuggestion={() => handleDismissSuggestion('ulbDate')}
							/>
						{/if}
					</DetailsContainer>

					<DetailsContainer title="Links">
						<DetailItem
							label="Wiki (EN)"
							bind:value={formDataByPage[selectedWikiPage].wikiEn}
							editable={true}
							type="text"
							placeholder="Page name (e.g., Narmaya)"
							width="480px"
							hasLinkButton={true}
							linkUrl={buildWikiEnUrl(formDataByPage[selectedWikiPage].wikiEn)}
						/>
						<DetailItem
							label="Wiki (JP)"
							bind:value={formDataByPage[selectedWikiPage].wikiJa}
							editable={true}
							type="text"
							placeholder="Japanese page name"
							width="480px"
							hasLinkButton={true}
							linkUrl={buildWikiJaUrl(formDataByPage[selectedWikiPage].wikiJa)}
						/>
						<SuggestionDetailItem
							label="Gamewith"
							bind:value={formDataByPage[selectedWikiPage].gamewith}
							editable={true}
							type="text"
							placeholder="Article ID (e.g., 519325)"
							width="480px"
							hasLinkButton={true}
							linkUrl={buildGamewithUrl(formDataByPage[selectedWikiPage].gamewith)}
							suggestion={suggestions?.gamewith}
							dismissedSuggestion={dismissed.has('gamewith')}
							onAcceptSuggestion={() => handleAcceptSuggestion('gamewith', suggestions?.gamewith)}
							onDismissSuggestion={() => handleDismissSuggestion('gamewith')}
						/>
						<SuggestionDetailItem
							label="Kamigame"
							bind:value={formDataByPage[selectedWikiPage].kamigame}
							editable={true}
							type="text"
							placeholder="Slug (e.g., SSR闇フロレンス)"
							width="480px"
							hasLinkButton={true}
							linkUrl={buildKamigameUrl(formDataByPage[selectedWikiPage].kamigame, 'character')}
							suggestion={suggestions?.kamigame}
							dismissedSuggestion={dismissed.has('kamigame')}
							onAcceptSuggestion={() => handleAcceptSuggestion('kamigame', suggestions?.kamigame)}
							onDismissSuggestion={() => handleDismissSuggestion('kamigame')}
						/>
					</DetailsContainer>

					{#if selectedEntity?.wikiRaw}
						<DetailsContainer title="Raw Wiki Data">
							<div class="wiki-raw">
								<pre>{selectedEntity.wikiRaw}</pre>
							</div>
						</DetailsContainer>
					{/if}
				</section>
			{/if}
		{/if}
	{/if}
</div>

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

	.page {
		background: white;
		border-radius: layout.$card-corner;
		box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
	}

	.input-phase {
		display: flex;
		flex-direction: column;
		gap: spacing.$unit-2x;
		padding: spacing.$unit-2x;
	}

	.wiki-inputs {
		display: flex;
		flex-direction: column;
		gap: spacing.$unit;
	}

	.input-row {
		display: flex;
		gap: spacing.$unit;
		align-items: center;
	}

	:global(.wiki-inputs .add-input-button) {
		width: fit-content;
	}

	.remove-button {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 32px;
		height: 32px;
		padding: 0;
		background: transparent;
		border: none;
		border-radius: layout.$input-corner;
		color: colors.$grey-50;
		cursor: pointer;
		flex-shrink: 0;

		&:hover {
			background: colors.$grey-90;
			color: colors.$grey-30;
		}

		:global(svg) {
			fill: currentColor;
		}
	}

	.hint {
		font-size: typography.$font-small;
		color: colors.$grey-50;
		margin: 0;
	}

	.error {
		color: colors.$error;
		font-size: typography.$font-small;
		margin: spacing.$unit 0;
	}

	.fetch-button {
		display: flex;
		justify-content: flex-end;
		margin-top: spacing.$unit-2x;
	}

	.entity-selector-container {
		padding: spacing.$unit-2x;
		border-bottom: 1px solid colors.$grey-90;
	}

	.details {
		display: flex;
		flex-direction: column;
	}

	.error-banner {
		color: colors.$error;
		font-size: typography.$font-small;
		padding: spacing.$unit-2x;
		background: colors.$error--bg--light;
	}

	.entity-error,
	.entity-loading {
		padding: spacing.$unit-4x;
		text-align: center;
		color: colors.$grey-50;

		h3 {
			margin: 0 0 spacing.$unit 0;
			color: colors.$error;
		}

		p {
			margin: 0;
		}
	}

	.wiki-raw {
		padding: spacing.$unit;

		pre {
			margin: 0;
			padding: spacing.$unit;
			background: colors.$grey-95;
			border-radius: 4px;
			font-size: typography.$font-small;
			white-space: pre-wrap;
			word-break: break-word;
			max-height: 300px;
			overflow-y: auto;
		}
	}
</style>
