'use client';

import { useState, useEffect, useMemo } from 'react';
import { useInventoryStore } from '@/store/useInventoryStore';

import shared from '../../styles/shared.module.css';
import styles from '../../styles/Customizations.module.css';

import { getFileName, cleanFolderName, isKiller } from '../../lib/utils';
import { fetchCharacters, fetchCustomizations } from '../../lib/db';
import {
	Character,
	CustomizationItem,
	RoleFilter,
	Tab,
	TAB_CATEGORIES,
	CATEGORY_ORDER
} from './types';
import CharacterPicker from './CharacterPicker';
import CharacterCosmetics from './CharacterCosmetics';
import FlatCategory from './FlatCategory';

/*
    constants
*/
const PAGE_SIZE = 60;

export default function CustomizationsPage() {
	const store = useInventoryStore();

	const [allItems, setAllItems] = useState<CustomizationItem[]>([]);
	const [characters, setCharacters] = useState<Character[]>([]);
	const [tab, setTab] = useState<Tab>('cosmetics');
	const [selectedChar, setSelectedChar] = useState<number | null>(null);
	const [charSearch, setCharSearch] = useState('');
	const [charRole, setCharRole] = useState<RoleFilter>('all');
	const [search, setSearch] = useState('');
	const [page, setPage] = useState(1);

	useEffect(() => {
		Promise.all([fetchCustomizations(), fetchCharacters()]).then(
			([items, chars]) => {
				setAllItems(items);
				setCharacters(chars);
			}
		);
	}, []);

	useEffect(() => {
		setPage(1);
	}, [tab, search]);

	/*
        derived data
    */
	const characterMap = useMemo(() => {
		const m = new Map<number, string>();
		characters.forEach((c) => m.set(c.idx, c.name));
		return m;
	}, [characters]);

	const unlockedSet = useMemo(
		() => new Set(store.unlockedCustomizations),
		[store.unlockedCustomizations]
	);

	const itemsByCharacter = useMemo(() => {
		const map = new Map<number, CustomizationItem[]>();
		allItems.forEach((item) => {
			if (
				item.category >= 1 &&
				item.category <= 7 &&
				item.associatedCharacter > -1
			) {
				if (!map.has(item.associatedCharacter))
					map.set(item.associatedCharacter, []);
				map.get(item.associatedCharacter)!.push(item);
			}
		});
		return map;
	}, [allItems]);

	const charFullyUnlocked = useMemo(() => {
		const result = new Map<number, boolean>();
		characters.forEach((char) => {
			const items = itemsByCharacter.get(char.idx) ?? [];
			result.set(
				char.idx,
				items.length > 0 && items.every((i) => unlockedSet.has(i.id))
			);
		});
		return result;
	}, [characters, itemsByCharacter, unlockedSet]);

	const filteredChars = useMemo(() => {
		return characters.filter((c) => {
			if (charRole === 'survivors' && isKiller(c.idx)) return false;
			if (charRole === 'killers' && !isKiller(c.idx)) return false;
			if (
				charSearch.trim() &&
				!c.name.toLowerCase().includes(charSearch.toLowerCase())
			)
				return false;
			return true;
		});
	}, [characters, charRole, charSearch]);

	const flatItems = useMemo(() => {
		if (tab === 'cosmetics') return [];
		const cat = TAB_CATEGORIES[tab];
		if (cat === undefined) return [];
		return allItems.filter((item) => {
			if (item.category !== cat) return false;
			if (
				search.trim() &&
				!item.name.toLowerCase().includes(search.toLowerCase())
			)
				return false;
			return true;
		});
	}, [allItems, tab, search]);

	const totalPages = Math.max(1, Math.ceil(flatItems.length / PAGE_SIZE));
	const pagedItems = useMemo(
		() => flatItems.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE),
		[flatItems, page]
	);

	const charCosmetics = useMemo(() => {
		if (selectedChar === null) return {};
		const items = itemsByCharacter.get(selectedChar) ?? [];
		const groups: Record<number, CustomizationItem[]> = {};
		CATEGORY_ORDER.forEach((cat) => {
			const group = items.filter((i) => i.category === cat);
			if (group.length > 0) groups[cat] = group;
		});
		return groups;
	}, [itemsByCharacter, selectedChar]);

	/*
        lock/unlock helpers
    */
	const mergeUnlock = (ids: string[]) => {
		const merged = Array.from(
			new Set([...store.unlockedCustomizations, ...ids])
		);
		store.unlockAllInCategory('customizations', merged);
	};

	const removeLock = (ids: string[]) => {
		const toRemove = new Set(ids);
		const remaining = store.unlockedCustomizations.filter(
			(id) => !toRemove.has(id)
		);
		store.unlockAllInCategory('customizations', remaining);
	};

	/*
        handlers
    */
	const handleToggle = (id: string) => store.toggleItem(id, 'customizations');

	const handleUnlockShownCosmetics = () => {
		const charSet = new Set(filteredChars.map((c) => c.idx));
		mergeUnlock(
			allItems
				.filter(
					(i) =>
						charSet.has(i.associatedCharacter) &&
						i.category >= 1 &&
						i.category <= 7
				)
				.map((i) => i.id)
		);
	};

	const handleLockShownCosmetics = () => {
		const charSet = new Set(filteredChars.map((c) => c.idx));
		removeLock(
			allItems
				.filter(
					(i) =>
						charSet.has(i.associatedCharacter) &&
						i.category >= 1 &&
						i.category <= 7
				)
				.map((i) => i.id)
		);
	};

	const handleUnlockCharCosmetics = () =>
		mergeUnlock(
			Object.values(charCosmetics)
				.flat()
				.map((i) => i.id)
		);
	const handleLockCharCosmetics = () =>
		removeLock(
			Object.values(charCosmetics)
				.flat()
				.map((i) => i.id)
		);

	const handleUnlockAll = () => mergeUnlock(flatItems.map((i) => i.id));
	const handleLockAll = () => removeLock(flatItems.map((i) => i.id));

	const handleUnlockPage = () => mergeUnlock(pagedItems.map((i) => i.id));
	const handleLockPage = () => removeLock(pagedItems.map((i) => i.id));

	return (
		<div className={shared.container}>
			<header className={shared.header}>
				<div>
					<h1 className={shared.title}>Customizations</h1>
					<p className={shared.subtitle}>
						{store.unlockedCustomizations.length} of {allItems.length || '-'}{' '}
						unlocked
					</p>
				</div>
				<button
					className={shared.clearBtn}
					onClick={() => store.clearCategory('customizations')}
				>
					Clear All
				</button>
			</header>
			<div className={styles.tabs}>
				{(
					['cosmetics', 'charms', 'badges', 'banners', 'portraits'] as Tab[]
				).map((t) => (
					<button
						key={t}
						className={`${styles.tab} ${tab === t ? styles.tabActive : ''}`}
						onClick={() => {
							setTab(t);
							setSelectedChar(null);
						}}
					>
						{t === 'cosmetics' ? 'Character Cosmetics' : t}
					</button>
				))}
			</div>
			{tab === 'cosmetics' && selectedChar === null && (
				<CharacterPicker
					filteredChars={filteredChars}
					charSearch={charSearch}
					charRole={charRole}
					charFullyUnlocked={charFullyUnlocked}
					onSelect={setSelectedChar}
					onSearchChange={setCharSearch}
					onRoleChange={setCharRole}
					onUnlockShownCosmetics={handleUnlockShownCosmetics}
					onLockShownCosmetics={handleLockShownCosmetics}
				/>
			)}
			{tab === 'cosmetics' && selectedChar !== null && (
				<CharacterCosmetics
					charName={characterMap.get(selectedChar) ?? selectedChar.toString()}
					charCosmetics={charCosmetics}
					unlockedSet={unlockedSet}
					characterMap={characterMap}
					onBack={() => setSelectedChar(null)}
					onUnlockAll={handleUnlockCharCosmetics}
					onLockAll={handleLockCharCosmetics}
					onToggle={handleToggle}
				/>
			)}
			{tab !== 'cosmetics' && (
				<FlatCategory
					tab={tab}
					allFilteredItems={flatItems}
					pagedItems={pagedItems}
					page={page}
					totalPages={totalPages}
					search={search}
					unlockedSet={unlockedSet}
					characterMap={characterMap}
					onSearchChange={setSearch}
					onUnlockAll={handleUnlockAll}
					onLockAll={handleLockAll}
					onUnlockPage={handleUnlockPage}
					onLockPage={handleLockPage}
					onToggle={handleToggle}
					onPageChange={setPage}
				/>
			)}
		</div>
	);
}
