import { useState, type ComponentType, type ReactNode } from 'react';
import { useNavigate } from '@tanstack/react-router';
import {
  Palette,
  Sun,
  Moon,
  Download,
  Upload,
  Sparkles,
  Cloud,
  ScrollText,
  TriangleAlert,
  type LucideProps,
} from 'lucide-react';
import { useUiStore, type Theme } from '@/stores/uiStore';
import { exportBackup, restoreBackup, clearAllData, BackupError } from '@/lib/io/backup';
import { pickTextFile } from '@/lib/io/file';
import { seedSampleCampaign } from '@/lib/sample';
import { cloudUsername, register as cloudRegister, login as cloudLogin, logout as cloudLogout, pushBackup, pullBackup, CloudError } from '@/lib/cloud/client';
import { AssistantSettings } from './AssistantSettings';
import { CloudCampaigns } from './CloudCampaigns';
import { Page, PageHeader } from '@/components/ui/Page';
import { Button } from '@/components/ui/Button';
import { Modal } from '@/components/ui/Modal';
import { Input } from '@/components/ui/Input';
import { cn } from '@/lib/cn';

/** A Living-Codex setting card: section eyebrow + a gilt hairline over its rows. */
function SettingsCard({ label, children, className }: { label: string; children: ReactNode; className?: string }) {
  return (
    <section className={cn('rounded-xl border border-line bg-panel p-4 sm:p-5', className)}>
      <h2 className="smallcaps text-[11px] text-muted">{label}</h2>
      <hr className="gilt-rule mt-2 mb-1" />
      <div>{children}</div>
    </section>
  );
}

/** An icon-tile row: leading rounded tile, title + description, trailing controls. */
function SettingsRow({
  icon: Icon,
  title,
  desc,
  children,
}: {
  icon: ComponentType<LucideProps>;
  title: ReactNode;
  desc?: ReactNode;
  children?: ReactNode;
}) {
  return (
    <div className="flex flex-wrap items-center gap-3 border-b border-line py-4 last:border-b-0">
      <span className="grid size-10 shrink-0 place-items-center rounded-lg bg-surface-2 text-accent-deep" aria-hidden>
        <Icon size={18} />
      </span>
      <div className="min-w-0 flex-1">
        <div className="font-display text-[15px] font-semibold text-ink">{title}</div>
        {desc && <div className="mt-0.5 text-xs text-faint">{desc}</div>}
      </div>
      {children && <div className="flex shrink-0 flex-wrap items-center gap-2">{children}</div>}
    </div>
  );
}

export function SettingsPage() {
  const theme = useUiStore((s) => s.theme);
  const setTheme = useUiStore((s) => s.setTheme);
  const setActiveCampaign = useUiStore((s) => s.setActiveCampaign);
  const navigate = useNavigate();
  const [msg, setMsg] = useState<string | null>(null);
  const [confirmRestore, setConfirmRestore] = useState<string | null>(null);
  const [confirmClear, setConfirmClear] = useState(false);

  const doImport = async () => {
    const text = await pickTextFile();
    if (text) setConfirmRestore(text);
  };
  const runRestore = async () => {
    if (!confirmRestore) return;
    try {
      await restoreBackup(confirmRestore);
      setMsg('Backup restored.');
    } catch (e) {
      setMsg(e instanceof BackupError ? e.message : 'Restore failed.');
    }
    setConfirmRestore(null);
  };
  const loadSample = async () => {
    const id = await seedSampleCampaign();
    setActiveCampaign(id);
    void navigate({ to: '/dashboard' });
  };

  return (
    <Page>
      <PageHeader eyebrow="Preferences" title="Settings" subtitle="Appearance, backups, and data." />

      <div className="space-y-6">
        <SettingsCard label="Appearance">
          <SettingsRow
            icon={theme === 'dark' ? Moon : Sun}
            title="Theme"
            desc="Parchment by day, candlelight by night."
          >
            {(['dark', 'light'] as Theme[]).map((t) => (
              <Button key={t} variant={theme === t ? 'primary' : 'secondary'} size="sm" onClick={() => setTheme(t)} className="capitalize">
                {t}
              </Button>
            ))}
          </SettingsRow>
        </SettingsCard>

        <SettingsCard label="Data">
          <SettingsRow icon={Download} title="Export backup" desc="Download a single JSON file with every campaign and all of its data.">
            <Button variant="secondary" size="sm" onClick={() => void exportBackup()}>Export backup</Button>
          </SettingsRow>
          <SettingsRow icon={Upload} title="Import backup" desc="Restore from a previously exported file. Replaces current data.">
            <Button variant="secondary" size="sm" onClick={doImport}>Import backup…</Button>
          </SettingsRow>
          <SettingsRow icon={Sparkles} title="Sample campaign" desc="Load a ready-made campaign to explore the app.">
            <Button variant="secondary" size="sm" onClick={loadSample}>Load sample campaign</Button>
          </SettingsRow>
          {msg && <p className={cn('mt-3 text-sm', msg.includes('fail') || msg.includes('not') ? 'text-danger' : 'text-success')}>{msg}</p>}
        </SettingsCard>

        <AssistantSettings />

        <CloudSync />

        <CloudCampaigns />

        <SettingsCard label="Data sources & licenses">
          <SettingsRow icon={ScrollText} title="Attribution" desc="Open-licensed game content powering the compendium.">
            <Palette className="text-faint" size={18} aria-hidden />
          </SettingsRow>
          <ul className="space-y-1 pt-3 text-sm text-muted">
            <li><span className="text-ink">D&amp;D 5e</span> — SRD content via <a className="text-accent hover:underline" href="https://open5e.com" target="_blank" rel="noreferrer">Open5e</a> (OGL 1.0a / CC-BY-4.0).</li>
            <li><span className="text-ink">Pathfinder 2e</span> — content from the <a className="text-accent hover:underline" href="https://github.com/foundryvtt/pf2e" target="_blank" rel="noreferrer">Foundry VTT pf2e</a> project &amp; Archives of Nethys (OGL / ORC / Paizo Community Use).</li>
            <li className="text-xs">Map import follows the Universal VTT (.dd2vtt) format used by Dungeondraft, Foundry &amp; others.</li>
          </ul>
        </SettingsCard>

        <section className="rounded-xl border border-danger/40 bg-danger/5 p-4 sm:p-5">
          <h2 className="flex items-center gap-1.5 text-sm font-semibold text-danger">
            <TriangleAlert size={15} aria-hidden /> Danger zone
          </h2>
          <p className="mb-3 mt-1 text-sm text-muted">Permanently delete all campaigns and data on this device.</p>
          <Button variant="danger" onClick={() => setConfirmClear(true)}>Clear all data</Button>
        </section>
      </div>

      <Modal
        open={!!confirmRestore}
        onClose={() => setConfirmRestore(null)}
        title="Restore backup?"
        footer={
          <>
            <Button variant="ghost" onClick={() => setConfirmRestore(null)}>Cancel</Button>
            <Button variant="danger" onClick={runRestore}>Replace all data</Button>
          </>
        }
      >
        <p className="text-sm text-muted">Restoring <strong className="text-ink">replaces all current data</strong> with the backup. Export first if unsure.</p>
      </Modal>

      <Modal
        open={confirmClear}
        onClose={() => setConfirmClear(false)}
        title="Clear all data?"
        footer={
          <>
            <Button variant="ghost" onClick={() => setConfirmClear(false)}>Cancel</Button>
            <Button variant="danger" onClick={async () => { await clearAllData(); setActiveCampaign(null); setConfirmClear(false); setMsg('All data cleared.'); }}>Delete everything</Button>
          </>
        }
      >
        <p className="text-sm text-muted">This deletes every campaign, character, encounter, note, map, and homebrew entry. This cannot be undone.</p>
      </Modal>
    </Page>
  );
}

function CloudSync() {
  const [user, setUser] = useState<string | null>(cloudUsername());
  const [u, setU] = useState('');
  const [p, setP] = useState('');
  const [msg, setMsg] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const [confirmPull, setConfirmPull] = useState(false);

  const run = async (fn: () => Promise<void>) => {
    setBusy(true); setMsg(null);
    try { await fn(); } catch (e) { setMsg(e instanceof CloudError ? e.message : 'Something went wrong.'); } finally { setBusy(false); }
  };
  const auth = (which: 'in' | 'up') => run(async () => {
    const r = await (which === 'in' ? cloudLogin(u, p) : cloudRegister(u, p));
    setUser(r.username); setP(''); setMsg(which === 'up' ? 'Account created.' : 'Signed in.');
  });
  const push = () => run(async () => {
    const r = await pushBackup();
    if (r.ok) { setMsg(`Backed up to cloud (${Math.round(r.bytes / 1024)} KB).`); return; }
    // Conflict: the cloud changed on another device since this one last synced.
    const useCloud = window.confirm('The cloud copy was changed on another device since you last synced.\n\nOK — replace THIS device with the cloud copy.\nCancel — overwrite the CLOUD with this device.');
    if (useCloud) { const ok = await pullBackup(); setMsg(ok ? 'Pulled the cloud copy — reloading…' : 'No cloud backup.'); if (ok) setTimeout(() => location.reload(), 600); }
    else { await pushBackup({ force: true }); setMsg('Overwrote the cloud with this device.'); }
  });
  const pull = () => run(async () => { const ok = await pullBackup(); setMsg(ok ? 'Restored — reloading…' : 'No cloud backup yet.'); if (ok) setTimeout(() => location.reload(), 600); });
  const signOut = () => run(async () => { await cloudLogout(); setUser(null); setMsg(null); });

  return (
    <SettingsCard label="Cloud sync (optional)">
      <SettingsRow
        icon={Cloud}
        title="Cloud sync"
        desc="Sign in to back up your campaigns and sync them across devices. Local-first stays the default — nothing leaves this device until you push."
      >
        {user && <span className="text-sm text-ink">Signed in as <span className="font-semibold">{user}</span></span>}
      </SettingsRow>
      {user ? (
        <div className="space-y-3 pt-4">
          <div className="flex flex-wrap gap-2">
            <Button variant="primary" disabled={busy} onClick={push}>⬆ Back up to cloud</Button>
            <Button variant="secondary" disabled={busy} onClick={() => setConfirmPull(true)}>⬇ Restore from cloud</Button>
            <Button variant="ghost" disabled={busy} onClick={signOut}>Sign out</Button>
          </div>
        </div>
      ) : (
        <div className="flex flex-wrap items-center gap-2 pt-4">
          <Input className="max-w-40" placeholder="Username" value={u} onChange={(e) => setU(e.target.value)} aria-label="Cloud username" />
          <Input className="max-w-40" type="password" placeholder="Password" value={p} onChange={(e) => setP(e.target.value)} aria-label="Cloud password" />
          <Button variant="primary" disabled={busy || !u || !p} onClick={() => auth('in')}>Sign in</Button>
          <Button variant="secondary" disabled={busy || !u || !p} onClick={() => auth('up')}>Create account</Button>
        </div>
      )}
      {msg && <p className="mt-3 text-sm text-accent">{msg}</p>}

      <Modal open={confirmPull} onClose={() => setConfirmPull(false)} title="Restore from cloud?"
        footer={<><Button variant="ghost" onClick={() => setConfirmPull(false)}>Cancel</Button><Button variant="danger" onClick={() => { setConfirmPull(false); void pull(); }}>Replace all data</Button></>}>
        <p className="text-sm text-muted">This <strong className="text-ink">replaces all data on this device</strong> with your cloud backup.</p>
      </Modal>
    </SettingsCard>
  );
}
