import { useEffect, useRef, useState, type FormEvent } from 'react';
import { Moon, Pencil, Plus, Search, Sun, Trash2 } from '@lucide/icons';
import { FayeMark } from '@fayegram-ai/faye-ui/icons';
import { Icon } from '@fayegram-ai/faye-ui/core/icon';
import { Heading, Text } from '@fayegram-ai/faye-ui/core/text';
import { Button, IconButton } from '@fayegram-ai/faye-ui/controls/button';
import { Input, Textarea } from '@fayegram-ai/faye-ui/controls/input';
import { InputGroup, InputAdornment } from '@fayegram-ai/faye-ui/controls/input-group';
import { TextField } from '@fayegram-ai/faye-ui/controls/text-field';
import { NativeSelect } from '@fayegram-ai/faye-ui/controls/native-select';
import { Checkbox } from '@fayegram-ai/faye-ui/controls/checkbox';
import { Form } from '@fayegram-ai/faye-ui/controls/form';
import { Dialog } from '@fayegram-ai/faye-ui/overlays/dialog';
import { AlertDialog } from '@fayegram-ai/faye-ui/overlays/alert-dialog';
import { Alert } from '@fayegram-ai/faye-ui/feedback/alert';
import { FayeUIProvider, useColorScheme } from '@fayegram-ai/faye-ui/provider/provider';
import { MAX_TASKS, readTasks, writeTasks, STORAGE_KEY, type Task, type StorageKind } from './tasks';
export function App() {
    const [density, setDensity] = useState<'comfortable' | 'compact'>('comfortable');
    const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr');
    return <FayeUIProvider density={density} direction={direction} storageKey="faye-ui.example.preference"><Tasks density={density} setDensity={setDensity} direction={direction} setDirection={setDirection}/></FayeUIProvider>;
}
function Tasks({ density, setDensity, direction, setDirection }: {
    density: 'comfortable' | 'compact';
    setDensity: (value: 'comfortable' | 'compact') => void;
    direction: 'ltr' | 'rtl';
    setDirection: (value: 'ltr' | 'rtl') => void;
}) {
    const [ready, setReady] = useState(false);
    useEffect(() => { setReady(true); }, []);
    const [initial] = useState(readTasks), [tasks, setTasks] = useState(initial.tasks), [storage, setStorage] = useState<StorageKind>(initial.kind);
    const [query, setQuery] = useState(''), [filter, setFilter] = useState('all'), [editor, setEditor] = useState<{
        task: Task | null;
    } | null>(null), [titleError, setTitleError] = useState('');
    const addButton = useRef<HTMLButtonElement>(null), titleInput = useRef<HTMLInputElement>(null);
    const { scheme, setPreference } = useColorScheme();
    const visible = tasks.filter(task => (filter === 'all' || task.completed === (filter === 'completed')) && `${task.title} ${task.notes}`.toLocaleLowerCase('en').includes(query.trim().toLocaleLowerCase('en')));
    function commit(next: Task[]) {
        setTasks(next);
        if (storage === 'invalid' || storage === 'read-error')
            return;
        try {
            writeTasks(next);
            setStorage('saved');
        }
        catch {
            setStorage('unavailable');
        }
    }
    function openEditor(task: Task | null) { setTitleError(''); setEditor({ task }); }
    function submit(event: FormEvent<HTMLFormElement>) {
        event.preventDefault();
        if (!editor)
            return;
        const data = new FormData(event.currentTarget), title = String(data.get('title') ?? '').trim(), notes = String(data.get('notes') ?? '').trim();
        if (!title) {
            setTitleError('Enter a task title.');
            titleInput.current?.focus();
            return;
        }
        if (title.length > 120 || notes.length > 1000) {
            setTitleError('Keep the title under 121 characters and notes under 1001.');
            titleInput.current?.focus();
            return;
        }
        const task: Task = { id: editor.task?.id ?? crypto.randomUUID(), title, notes, completed: data.get('completed') === 'true' };
        if (!editor.task && tasks.length >= MAX_TASKS)
            return;
        commit(editor.task ? tasks.map(item => item.id === task.id ? task : item) : [...tasks, task]);
        setEditor(null);
    }
    function resetStored() {
        try {
            window.localStorage.removeItem(STORAGE_KEY);
            setTasks([]);
            setStorage('new');
        }
        catch {
            setStorage('unavailable');
        }
        requestAnimationFrame(() => addButton.current?.focus());
    }
    return <Dialog.Root open={editor !== null} onOpenChange={open => { if (!open)
        setEditor(null); }}>
      <a className="task-skip" href="#task-main">Skip to tasks</a>
      <div className="task-app" data-example-ready={ready ? 'true' : undefined}>
        <header className="task-header"><div className="task-brand"><Icon icon={FayeMark} size="lg" label="Faye"/><div><Heading level={1} size="lg">Tasks</Heading><Text size="sm" tone="muted">A small place to keep work moving.</Text></div></div><div className="task-settings"><details><summary>Display settings</summary><div className="task-settings-panel"><label>Density<NativeSelect aria-label="Density" value={density} onChange={event => setDensity(event.target.value === 'compact' ? 'compact' : 'comfortable')}><option value="comfortable">Comfortable</option><option value="compact">Compact</option></NativeSelect></label><label>Direction<NativeSelect aria-label="Direction" value={direction} onChange={event => setDirection(event.target.value === 'rtl' ? 'rtl' : 'ltr')}><option value="ltr">Left to right</option><option value="rtl">Right to left</option></NativeSelect></label></div></details><IconButton aria-label={scheme === 'dark' ? 'Use light theme' : 'Use dark theme'} onClick={() => setPreference(scheme === 'dark' ? 'light' : 'dark')}><Icon icon={scheme === 'dark' ? Sun : Moon} size="sm"/></IconButton></div></header>
        <main id="task-main" tabIndex={-1}>
          <div className="task-toolbar"><InputGroup className="task-search"><InputAdornment><Icon icon={Search} size="sm"/></InputAdornment><Input type="search" aria-label="Search tasks" placeholder="Search tasks" value={query} onChange={event => setQuery(event.target.value)}/></InputGroup><label className="task-filter">Status<NativeSelect aria-label="Task status" value={filter} onChange={event => setFilter(event.target.value)}><option value="all">All tasks</option><option value="active">Active</option><option value="completed">Completed</option></NativeSelect></label><Dialog.Trigger render={<Button ref={addButton} variant="solid" tone="accent" disabled={tasks.length >= MAX_TASKS}/>} onClick={() => openEditor(null)}><Icon icon={Plus} size="sm"/>New task</Dialog.Trigger></div>
          {(storage === 'invalid' || storage === 'read-error' || storage === 'unavailable') && <Alert tone="warning" title={storage === 'invalid' ? 'Saved data needs attention' : storage === 'read-error' ? 'Saved tasks could not be restored' : 'Browser storage unavailable'}><p>{storage === 'read-error' ? 'Current changes remain in this tab. Retry reading to restore saved tasks before saving, or explicitly reset saved data.' : storage === 'invalid' ? 'Saved tasks could not be read and have been left unchanged. New changes remain in this tab until you reset saved data.' : 'Changes are kept in this tab, but could not be saved. Keep this page open until browser storage is available.'}</p><div className="task-actions">{storage === 'read-error' && <Button onClick={() => { const restored = readTasks(); if (restored.kind === 'read-error')
        return; if (restored.kind === 'invalid') {
        setStorage('invalid');
        return;
    } const merged = [...new Map([...restored.tasks, ...tasks].map(task => [task.id, task])).values()]; if (merged.length > MAX_TASKS)
        return; setTasks(merged); try {
        writeTasks(merged);
        setStorage('saved');
    }
    catch {
        setStorage('unavailable');
    } }}>Retry reading</Button>}{storage === 'unavailable' && <Button onClick={() => { try {
        writeTasks(tasks);
        setStorage('saved');
    }
    catch {
        setStorage('unavailable');
    } }}>Retry saving</Button>}<AlertDialog.Root><AlertDialog.Trigger render={<Button />}>Reset saved data</AlertDialog.Trigger><AlertDialog.Portal><AlertDialog.Backdrop /><AlertDialog.Popup><AlertDialog.Title>Reset saved tasks?</AlertDialog.Title><AlertDialog.Description>This removes this example's stored tasks and clears the current list. Theme preferences and other browser data are kept.</AlertDialog.Description><div className="task-dialog-actions"><AlertDialog.Close render={<Button />}>Cancel reset</AlertDialog.Close><AlertDialog.Close render={<Button variant="solid" tone="danger"/>} onClick={resetStored}>Reset tasks</AlertDialog.Close></div></AlertDialog.Popup></AlertDialog.Portal></AlertDialog.Root></div></Alert>}
          <Text as="p" size="sm" tone="muted" role="status">{visible.length} of {tasks.length} tasks · {tasks.filter(task => task.completed).length} completed</Text>
          {visible.length === 0 ? <section className="task-empty"><Heading level={2} size="md">{tasks.length === 0 ? 'No tasks yet' : 'No matching tasks'}</Heading><Text as="p" tone="muted">{tasks.length === 0 ? 'Create a task to get started. Everything stays in this browser.' : 'Try another search or choose a different status.'}</Text>{tasks.length > 0 && <Button onClick={() => { setQuery(''); setFilter('all'); }}>Clear filters</Button>}</section> : <ul className="task-list" aria-label="Tasks">{visible.map(task => <li key={task.id} data-task-id={task.id} data-completed={task.completed}><div className="task-control"><Checkbox.Root checked={task.completed} onCheckedChange={completed => commit(tasks.map(item => item.id === task.id ? { ...item, completed } : item))} aria-label={`Complete ${task.title}`}><Checkbox.Indicator /></Checkbox.Root><span className="task-copy"><strong>{task.title}</strong>{task.notes && <span>{task.notes}</span>}</span></div><div className="task-row-actions"><Dialog.Trigger render={<IconButton variant="ghost" aria-label={`Edit ${task.title}`}><Icon icon={Pencil} size="sm"/></IconButton>} onClick={() => openEditor(task)}/><AlertDialog.Root><AlertDialog.Trigger render={<IconButton variant="ghost" aria-label={`Delete ${task.title}`}><Icon icon={Trash2} size="sm"/></IconButton>}/><AlertDialog.Portal><AlertDialog.Backdrop /><AlertDialog.Popup><AlertDialog.Title>Delete task?</AlertDialog.Title><AlertDialog.Description>Delete “{task.title}” from this browser? This cannot be undone.</AlertDialog.Description><div className="task-dialog-actions"><AlertDialog.Close render={<Button />}>Keep task</AlertDialog.Close><AlertDialog.Close render={<Button variant="solid" tone="danger"/>} onClick={() => { commit(tasks.filter(item => item.id !== task.id)); requestAnimationFrame(() => addButton.current?.focus()); }}>Delete task</AlertDialog.Close></div></AlertDialog.Popup></AlertDialog.Portal></AlertDialog.Root></div></li>)}</ul>}
          <footer className="task-footer"><Text size="xs" tone="muted">{storage === 'saved' || storage === 'new' ? 'Saved in this browser.' : 'Current changes may be available only in this tab.'} No account or server connection.</Text>{tasks.length >= MAX_TASKS && <Text size="sm">The example holds up to {MAX_TASKS} tasks. Remove a task before adding another.</Text>}</footer>
        </main>
      </div>
      <Dialog.Portal><Dialog.Backdrop /><Dialog.Popup className="task-editor"><Dialog.Title>{editor?.task ? 'Edit task' : 'New task'}</Dialog.Title><Dialog.Description>Give the task a clear title. Notes are optional.</Dialog.Description>{editor && <Form key={editor.task?.id ?? 'new'} onSubmit={submit}><TextField ref={titleInput} label="Task title" name="title" required maxLength={120} defaultValue={editor.task?.title ?? ''} error={titleError || undefined} autoFocus/><label className="task-field">Notes<Textarea name="notes" maxLength={1000} defaultValue={editor.task?.notes ?? ''} rows={3}/></label><label className="task-field">Task state<NativeSelect name="completed" defaultValue={String(editor.task?.completed ?? false)}><option value="false">Active</option><option value="true">Completed</option></NativeSelect></label><div className="task-dialog-actions"><Dialog.Close render={<Button />}>Cancel</Dialog.Close><Button type="submit" variant="solid" tone="accent">Save task</Button></div></Form>}</Dialog.Popup></Dialog.Portal>
    </Dialog.Root>;
}
