import { useState } from 'react';
import type { Campaign, Quest, Objective } from '@/lib/schemas';
import { questsRepo } from '@/lib/db/repositories';
import { newId } from '@/lib/ids';
import { useDebouncedCallback } from '@/lib/useDebouncedCallback';
import { useQuests } from './hooks';
import { Page, PageHeader, EmptyState, RequireCampaign } from '@/components/ui/Page';
import { Button } from '@/components/ui/Button';
import { Input, Select } from '@/components/ui/Input';
import { cn } from '@/lib/cn';

const STATUSES: Quest['status'][] = ['active', 'on-hold', 'completed', 'failed'];
const STATUS_COLOR: Record<Quest['status'], string> = {
  active: 'text-info', 'on-hold': 'text-muted', completed: 'text-success', failed: 'text-danger',
};

export function QuestsPage() {
  return <RequireCampaign>{(c) => <Quests campaign={c} />}</RequireCampaign>;
}

function Quests({ campaign }: { campaign: Campaign }) {
  const quests = useQuests(campaign.id);
  const order = { active: 0, 'on-hold': 1, completed: 2, failed: 3 };
  const sorted = [...quests].sort((a, b) => order[a.status] - order[b.status] || a.title.localeCompare(b.title));

  return (
    <Page>
      <PageHeader
        title="Quests"
        subtitle={campaign.name}
        actions={<Button variant="primary" onClick={() => questsRepo.create(campaign.id, 'New quest')}>+ New quest</Button>}
      />
      {quests.length === 0 ? (
        <EmptyState title="No quests yet" hint="Track objectives, rewards, and progress." action={<Button variant="primary" onClick={() => questsRepo.create(campaign.id, 'New quest')}>+ New quest</Button>} />
      ) : (
        <div className="space-y-3">
          {sorted.map((q) => <QuestCard key={q.id} quest={q} />)}
        </div>
      )}
    </Page>
  );
}

function QuestCard({ quest }: { quest: Quest }) {
  const [q, setQ] = useState(quest);
  const [newObj, setNewObj] = useState('');
  const save = useDebouncedCallback((next: Quest) => void questsRepo.update(next.id, {
    title: next.title, status: next.status, description: next.description, reward: next.reward, objectives: next.objectives,
  }), 350);
  const update = (patch: Partial<Quest>) => setQ((p) => { const next = { ...p, ...patch }; save(next); return next; });

  const setObjective = (id: string, patch: Partial<Objective>) =>
    update({ objectives: q.objectives.map((o) => (o.id === id ? { ...o, ...patch } : o)) });
  const addObjective = () => {
    if (newObj.trim() === '') return;
    update({ objectives: [...q.objectives, { id: newId(), text: newObj.trim(), done: false }] });
    setNewObj('');
  };
  const done = q.objectives.filter((o) => o.done).length;

  return (
    <div className="rounded-lg border border-line bg-panel p-4">
      <div className="flex flex-wrap items-center gap-2">
        <Input className="flex-1 font-display font-semibold" value={q.title} onChange={(e) => update({ title: e.target.value })} aria-label="Quest title" />
        <Select className={cn('w-auto py-1 text-xs font-medium', STATUS_COLOR[q.status])} value={q.status} onChange={(e) => update({ status: e.target.value as Quest['status'] })} aria-label="Quest status">
          {STATUSES.map((s) => <option key={s} value={s}>{s}</option>)}
        </Select>
        <Button size="icon" variant="ghost" className="text-danger" onClick={() => questsRepo.remove(quest.id)} aria-label={`Delete ${q.title}`}>✕</Button>
      </div>

      <textarea
        value={q.description}
        onChange={(e) => update({ description: e.target.value })}
        placeholder="What's this quest about?"
        className="mt-2 min-h-16 w-full resize-y rounded-md border border-line bg-surface px-3 py-2 text-sm text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/60"
      />

      <label className="mt-2 block text-xs text-muted">
        Reward
        <Input value={q.reward} onChange={(e) => update({ reward: e.target.value })} placeholder="500 gp, a favour, a magic sword…" />
      </label>

      <div className="mt-3">
        <div className="mb-1 text-xs font-semibold uppercase tracking-wide text-muted">
          Objectives {q.objectives.length > 0 && `(${done}/${q.objectives.length})`}
        </div>
        <ul className="space-y-1">
          {q.objectives.map((o) => (
            <li key={o.id} className="flex items-center gap-2 text-sm">
              <input type="checkbox" checked={o.done} onChange={(e) => setObjective(o.id, { done: e.target.checked })} aria-label={o.text} />
              <input
                className={cn('flex-1 bg-transparent text-sm focus:outline-none', o.done ? 'text-muted line-through' : 'text-ink')}
                value={o.text}
                onChange={(e) => setObjective(o.id, { text: e.target.value })}
              />
              <button className="text-muted hover:text-danger" onClick={() => update({ objectives: q.objectives.filter((x) => x.id !== o.id) })} aria-label="Remove objective">✕</button>
            </li>
          ))}
        </ul>
        <div className="mt-1 flex gap-2">
          <Input className="h-8 text-sm" value={newObj} onChange={(e) => setNewObj(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && addObjective()} placeholder="Add objective…" />
          <Button size="sm" onClick={addObjective}>Add</Button>
        </div>
      </div>
    </div>
  );
}
