import { useState } from 'react';
import { Link } from '@tanstack/react-router';
import { charactersRepo } from '@/lib/db/repositories';
import type { Campaign, Character } from '@/lib/schemas';
import { getSystem } from '@/lib/rules';
import { exportCharacter, parseCharacterImport, CharacterImportError } from '@/lib/io/character';
import { pickTextFile } from '@/lib/io/file';
import { useCharacters } from './hooks';
import { Page, PageHeader, EmptyState, RequireCampaign } from '@/components/ui/Page';
import { Button } from '@/components/ui/Button';
import { Modal } from '@/components/ui/Modal';
import { Field, Input, Select } from '@/components/ui/Input';

export function CharactersPage() {
  return <RequireCampaign>{(campaign) => <CharactersList campaign={campaign} />}</RequireCampaign>;
}

function CharactersList({ campaign }: { campaign: Campaign }) {
  const characters = useCharacters(campaign.id);
  const [creating, setCreating] = useState(false);
  const [importError, setImportError] = useState<string | null>(null);
  const pcs = characters.filter((c) => c.kind === 'pc');
  const npcs = characters.filter((c) => c.kind === 'npc');

  const importCharacter = async () => {
    setImportError(null);
    const text = await pickTextFile();
    if (text === null) return;
    try {
      const character = parseCharacterImport(text, campaign.id);
      await charactersRepo.insert(character);
    } catch (e) {
      setImportError(e instanceof CharacterImportError ? e.message : 'Import failed.');
    }
  };

  return (
    <Page>
      <PageHeader
        title="Characters"
        subtitle={campaign.name}
        actions={
          <>
            <Button variant="secondary" onClick={importCharacter}>
              Import
            </Button>
            <Button variant="primary" onClick={() => setCreating(true)}>
              + New character
            </Button>
          </>
        }
      />

      {importError && (
        <p className="mb-4 rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-sm text-danger">
          {importError}
        </p>
      )}

      {characters.length === 0 ? (
        <EmptyState
          title="No characters yet"
          hint="Add player characters and NPCs, or import a character file."
          action={
            <Button variant="primary" onClick={() => setCreating(true)}>
              + New character
            </Button>
          }
        />
      ) : (
        <div className="space-y-6">
          <CharacterGroup title="Player Characters" items={pcs} />
          <CharacterGroup title="NPCs" items={npcs} />
        </div>
      )}

      {creating && <CharacterFormModal campaign={campaign} onClose={() => setCreating(false)} />}
    </Page>
  );
}

function CharacterGroup({ title, items }: { title: string; items: Character[] }) {
  if (items.length === 0) return null;
  return (
    <section>
      <h2 className="mb-2 text-xs font-semibold uppercase tracking-wide text-muted">{title}</h2>
      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
        {items.map((c) => (
          <CharacterCard key={c.id} c={c} />
        ))}
      </div>
    </section>
  );
}

function CharacterCard({ c }: { c: Character }) {
  const [confirming, setConfirming] = useState(false);
  const ac = getSystem(c.system).baseArmorClass({ level: c.level, abilities: c.abilities, armorBonus: c.armorBonus });

  return (
    <div className="flex flex-col rounded-lg border border-line bg-panel transition-colors hover:border-accent/50">
      <Link
        to="/characters/$characterId"
        params={{ characterId: c.id }}
        className="block p-4"
      >
        <div className="flex items-baseline justify-between">
          <h3 className="font-display text-lg font-semibold text-ink">{c.name}</h3>
          <span className="text-sm text-muted">Lv {c.level}</span>
        </div>
        <p className="mt-0.5 text-sm text-muted">
          {[c.ancestry, c.className].filter(Boolean).join(' ') || '—'}
        </p>
        <div className="mt-3 flex gap-4 text-sm">
          <span className="text-muted">
            HP <span className="font-medium text-ink">{c.hp.current}/{c.hp.max}</span>
          </span>
          <span className="text-muted">
            AC <span className="font-medium text-ink">{ac}</span>
          </span>
        </div>
      </Link>
      <div className="flex items-center gap-1 border-t border-line px-2 py-1.5">
        <Button size="sm" variant="ghost" onClick={() => exportCharacter(c)} title="Export to JSON file">
          Export
        </Button>
        <Button
          size="sm"
          variant="ghost"
          className="ml-auto text-danger hover:bg-danger/10"
          onClick={() => setConfirming(true)}
        >
          Delete
        </Button>
      </div>

      <Modal
        open={confirming}
        onClose={() => setConfirming(false)}
        title="Delete character?"
        footer={
          <>
            <Button variant="ghost" onClick={() => setConfirming(false)}>
              Cancel
            </Button>
            <Button
              variant="danger"
              onClick={async () => {
                await charactersRepo.remove(c.id);
                setConfirming(false);
              }}
            >
              Delete
            </Button>
          </>
        }
      >
        <p className="text-sm text-muted">
          Permanently delete <strong className="text-ink">{c.name}</strong>? This cannot be undone.
          {' '}Consider exporting first.
        </p>
      </Modal>
    </div>
  );
}

function CharacterFormModal({ campaign, onClose }: { campaign: Campaign; onClose: () => void }) {
  const [name, setName] = useState('');
  const [kind, setKind] = useState<Character['kind']>('pc');
  const [ancestry, setAncestry] = useState('');
  const [className, setClassName] = useState('');
  const [level, setLevel] = useState(1);
  const [error, setError] = useState<string | null>(null);

  const save = async () => {
    if (name.trim() === '') {
      setError('Name is required');
      return;
    }
    await charactersRepo.create(campaign.id, {
      system: campaign.system,
      name: name.trim(),
      kind,
      ancestry: ancestry.trim(),
      className: className.trim(),
      level,
    });
    onClose();
  };

  return (
    <Modal
      open
      onClose={onClose}
      title="New character"
      footer={
        <>
          <Button variant="ghost" onClick={onClose}>
            Cancel
          </Button>
          <Button variant="primary" onClick={save}>
            Create
          </Button>
        </>
      }
    >
      <div className="space-y-4">
        <Field label="Name">
          <Input data-autofocus value={name} onChange={(e) => { setName(e.target.value); setError(null); }} placeholder="Aria Stormwind" />
        </Field>
        <div className="grid grid-cols-2 gap-3">
          <Field label="Type">
            <Select value={kind} onChange={(e) => setKind(e.target.value as Character['kind'])}>
              <option value="pc">Player Character</option>
              <option value="npc">NPC</option>
            </Select>
          </Field>
          <Field label="Level">
            <Input
              type="number"
              min={1}
              max={20}
              value={level}
              onChange={(e) => setLevel(Math.max(1, Math.min(20, Number(e.target.value) || 1)))}
            />
          </Field>
        </div>
        <div className="grid grid-cols-2 gap-3">
          <Field label={campaign.system === 'pf2e' ? 'Ancestry' : 'Race'}>
            <Input value={ancestry} onChange={(e) => setAncestry(e.target.value)} placeholder={campaign.system === 'pf2e' ? 'Dwarf' : 'Half-Elf'} />
          </Field>
          <Field label="Class">
            <Input value={className} onChange={(e) => setClassName(e.target.value)} placeholder="Fighter" />
          </Field>
        </div>
        {error && <p className="text-sm text-danger">{error}</p>}
      </div>
    </Modal>
  );
}
