import { memo, useCallback, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import { useKanbanBoard } from '../../components/kanban/useKanbanBoard';
import { KanbanCard } from '../../components/kanban/KanbanCard';
import { CardModal } from '../../components/kanban/CardModal';
import { RunningAgentsBar } from '../../components/kanban/RunningAgentsBar';
import { MergeAllModal } from '../../components/kanban/MergeAllModal';
import { useOrchestrator } from '../../components/kanban/useOrchestrator';
import { useCustomPages } from '../../lib/customPagesStore';
import type { Card, Column } from '../../lib/kanbanApi';
import type { BatchMergeResult } from '../../lib/orchestratorApi';

const COLUMNS: { key: Column; title: string; color: string; bgColor: string }[] = [
  { key: 'done', title: 'DONE', color: 'var(--green)', bgColor: 'rgba(34,197,94,0.05)' },
  { key: 'in-progress', title: 'IN PROGRESS', color: 'var(--accent)', bgColor: 'rgba(240,160,48,0.05)' },
  { key: 'todo', title: 'TODO', color: 'var(--red)', bgColor: 'rgba(239,68,68,0.05)' },
  { key: 'backlog', title: 'BACKLOG', color: 'var(--muted)', bgColor: 'var(--surface-raised)' },
];

const CATEGORIES = [
  'Onboarding', 'Core', 'Content', 'In-System', 'UI', 'Navigation', 'Economy', 'Ships',
  'Combat', 'NPCs', 'Social', 'Progression', 'Industry', 'Narrative', 'UX', 'Infrastructure',
];

const DEFAULT_AUTHOR = 'User';

export function KanbanBoardPage() {
  const {
    board,
    pages,
    loading,
    error,
    reload,
    moveCard,
    addComment,
    deleteComment,
    addTag,
    removeTag,
    addReference,
    removeReference,
  } = useKanbanBoard();

  // Custom pages power the "custom page reference" picker on each card.
  const { pages: customPages } = useCustomPages();

  // Agentic orchestrator: launch/watch/steer pi runs from the board.
  const orch = useOrchestrator();

  const [openCardId, setOpenCardId] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [justSaved, setJustSaved] = useState(false);
  const [mergeAllResult, setMergeAllResult] = useState<BatchMergeResult | null>(null);
  const [mergeAllBusy, setMergeAllBusy] = useState(false);

  // Stable identity across renders — memoized cards receive a referentially
  // stable `onOpen` so they don't re-render just because the parent did.
  const openById = useCallback((id: string) => setOpenCardId(id), []);

  /** Sequentially merge every reviewable agent branch into the main branch. */
  const mergeAll = async () => {
    setMergeAllBusy(true);
    try {
      const result = await orch.mergeAll();
      setMergeAllResult(result);
      // Branches that landed change the board's underlying git state; reload so
      // diffs/merge state reflect reality.
      await reload();
    } catch (e) {
      setMergeAllResult({
        target: '?',
        items: [],
        haltedOn: null,
        aborted: true,
        reason: e instanceof Error ? e.message : 'merge-all failed',
        recoveryRef: null,
      });
    } finally {
      setMergeAllBusy(false);
    }
  };

  // The card whose detail modal is open (null when closed).
  const openCard = board?.cards.find((c) => c.id === openCardId) ?? null;

  // Manually re-sync with the backend, confirming every optimistic change is
  // persisted. The board already auto-saves on each mutation; this gives the
  // operator an explicit save affordance with clear feedback.
  const save = async () => {
    setSaving(true);
    try {
      await reload();
      setJustSaved(true);
      window.setTimeout(() => setJustSaved(false), 1500);
    } finally {
      setSaving(false);
    }
  };

  const byColumn = useMemo(() => {
    const groups: Record<Column, Card[]> = { done: [], 'in-progress': [], todo: [], backlog: [] };
    if (board) {
      for (const card of board.cards) {
        groups[card.status].push(card);
      }
    }
    return groups;
  }, [board]);

  // Card-id index for the floating active-agents dock (titles/categories). Built
  // from the board so it's stable between unrelated renders.
  const cardById = useMemo(() => {
    const m = new Map<string, Card>();
    if (board) for (const c of board.cards) m.set(c.id, c);
    return m;
  }, [board]);

  const counts = useMemo(() => {
    const c = { done: 0, 'in-progress': 0, todo: 0, backlog: 0, total: 0 };
    if (board) {
      for (const card of board.cards) {
        c[card.status]++;
        c.total++;
      }
    }
    return c;
  }, [board]);

  const completionRate = useMemo(() => {
    if (counts.total === 0) return 0;
    const weighted = counts.done + counts['in-progress'] * 0.3;
    return Math.round((weighted / counts.total) * 100);
  }, [counts]);

  return (
    <div className="mx-auto max-w-content">
      {/* Header */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' }}>
        <h1 style={{ marginBottom: '0' }}>Implementation Board</h1>
        <div style={{ display: 'flex', gap: 'var(--sp-2)', alignItems: 'center' }}>
          <SyncStatus loading={loading} error={error} />
          <button
            type="button"
            onClick={() => void save()}
            disabled={saving}
            style={primaryHeaderButtonStyle}
          >
            {saving ? 'Saving…' : justSaved ? '✓ Saved' : 'Save'}
          </button>
          <button type="button" onClick={() => void reload()} style={headerButtonStyle}>
            Reload
          </button>
          <button
            type="button"
            onClick={() => void mergeAll()}
            disabled={mergeAllBusy}
            title="Merge every reviewable agent branch into the main branch"
            style={headerButtonStyle}
          >
            {mergeAllBusy ? 'Merging…' : '⬇ Merge all'}
          </button>
        </div>
      </div>
      <p style={{ color: 'var(--fg-dim)', fontSize: '0.95rem', maxWidth: '720px' }}>
        Interactive implementation board, backed by{' '}
        <code style={{ fontSize: '0.85em' }}>apps/api</code> (SQLite). Cards reference the{' '}
        <Link to="/docs/overview" style={{ color: 'var(--cyan)', textDecoration: 'underline' }}>
          design docs
        </Link>{' '}
        — click a card to comment, tag, move, or add references. Comments persist to the database.
      </p>

      {/* Error banner */}
      {error && (
        <div
          style={{
            marginTop: 'var(--sp-4)',
            padding: '10px 14px',
            border: '1px solid var(--red)',
            background: 'rgba(239,68,68,0.08)',
            color: 'var(--red)',
            borderRadius: 'var(--radius-sm)',
            fontSize: '0.85rem',
          }}
        >
          ⚠ {error} — <button onClick={() => void reload()} style={{ background: 'none', border: 'none', color: 'inherit', textDecoration: 'underline', cursor: 'pointer' }}>retry</button>
        </div>
      )}

      {/* Loading state */}
      {loading && !board && (
        <div style={{ marginTop: 'var(--sp-6)', color: 'var(--muted)', fontSize: '0.9rem' }}>Loading board…</div>
      )}

      {board && (
        <>
          {/* Stats */}
          <div
            className="grid gap-4"
            style={{
              marginTop: 'var(--sp-5)',
              gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))',
            }}
          >
            {COLUMNS.map((col) => (
              <StatCard key={col.key} label={col.title} value={counts[col.key]} color={col.color} />
            ))}
          </div>

          {/* Progress */}
          <div style={{ marginTop: 'var(--sp-4)', marginBottom: 'var(--sp-4)', padding: 'var(--sp-4)', border: '1px solid var(--border)', background: 'var(--surface)', borderRadius: 'var(--radius-lg)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', marginBottom: 'var(--sp-2)' }}>
              <span style={{ fontSize: '0.85rem', color: 'var(--fg)', fontWeight: 500 }}>Overall Implementation Progress</span>
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: '0.85rem', color: 'var(--fg-dim)' }}>
                {completionRate}%
              </span>
            </div>
            <div style={{ width: '100%', height: '8px', borderRadius: '4px', background: 'var(--surface-raised)', overflow: 'hidden' }}>
              <div
                style={{
                  width: `${completionRate}%`,
                  height: '100%',
                  borderRadius: '4px',
                  background: completionRate > 50 ? 'var(--green)' : completionRate > 25 ? 'var(--accent)' : 'var(--red)',
                }}
              />
            </div>
          </div>

          {/* Board */}
          <div
            style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(4, minmax(280px, 1fr))',
              gap: 'var(--sp-4)',
              overflowX: 'auto',
              paddingBottom: 'var(--sp-4)',
            }}
          >
            {COLUMNS.map((col) => (
              <div
                key={col.key}
                style={{
                  background: col.bgColor,
                  borderRadius: 'var(--radius-md)',
                  padding: 'var(--sp-3)',
                  border: '1px solid var(--border)',
                  minHeight: '400px',
                  display: 'flex',
                  flexDirection: 'column',
                }}
              >
                <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--sp-2)', marginBottom: 'var(--sp-3)', paddingBottom: 'var(--sp-2)', borderBottom: '2px solid var(--border)' }}>
                  <span style={{ width: '10px', height: '10px', borderRadius: '50%', background: col.color, boxShadow: `0 0 8px ${col.color}66` }} />
                  <h3 style={{ margin: 0, fontSize: '0.9rem', fontWeight: 600, color: 'var(--fg)' }}>{col.title}</h3>
                  <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: '0.75rem', color: 'var(--muted)', background: 'var(--surface)', padding: '2px 8px', borderRadius: 'var(--radius-pill)' }}>
                    {byColumn[col.key].length}
                  </span>
                </div>

                <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--sp-2)', flex: 1 }}>
                  {byColumn[col.key].map((card) => {
                    const active = orch.activeByCard.get(card.id);
                    return (
                      <KanbanCard
                        key={card.id}
                        card={card}
                        pages={pages}
                        customPages={customPages}
                        isRunning={!!active?.running}
                        bevyRunning={!!active?.bevy}
                        onOpen={openById}
                      />
                    );
                  })}
                </div>
              </div>
            ))}
          </div>

          {/* Legend */}
          <CategoryLegend />
        </>
      )}

      {openCard && (
        <CardModal
          card={openCard}
          pages={pages}
          customPages={customPages}
          orch={orch}
          onClose={() => setOpenCardId(null)}
          onMove={(status) => void moveCard(openCard.id, status)}
          onAddComment={(text) => void addComment(openCard.id, text, DEFAULT_AUTHOR)}
          onDeleteComment={(commentId) => void deleteComment(commentId, openCard.id)}
          onAddTag={(tag) => void addTag(openCard.id, tag)}
          onRemoveTag={(tag) => void removeTag(openCard.id, tag)}
          onAddReference={(ref) => void addReference(openCard.id, ref)}
          onRemoveReference={(href) => void removeReference(openCard.id, href)}
        />
      )}

      {/* Floating dock: jump to any agent currently running. */}
      <RunningAgentsBar runs={orch.runs} cardById={cardById} onOpenCard={openById} />

      {/* Batch-merge results overlay. */}
      {mergeAllResult && (
        <MergeAllModal
          result={mergeAllResult}
          busy={mergeAllBusy}
          onClose={() => setMergeAllResult(null)}
        />
      )}
    </div>
  );
}

const StatCard = memo(function StatCard({ label, value, color }: { label: string; value: number; color: string }) {
  return (
    <div
      className="rounded-xl border border-border bg-surface p-4 max-md:rounded-lg max-md:p-3"
      style={{ borderTop: `3px solid ${color}` }}
    >
      <div className="font-mono text-[1.4rem] font-bold tabular-nums" style={{ color }}>
        {value}
      </div>
      <div className="mt-1 text-[0.7rem] uppercase tracking-[0.05em] text-muted">{label}</div>
    </div>
  );
});

function SyncStatus({ loading, error }: { loading: boolean; error: string | null }) {
  const state = error ? 'error' : loading ? 'loading' : 'synced';
  const conf = {
    loading: { label: 'Syncing…', color: 'var(--muted)', tip: 'Talking to the API…' },
    synced: { label: 'Synced', color: 'var(--green)', tip: 'Changes persist to the SQLite backend.' },
    error: { label: 'Error', color: 'var(--red)', tip: 'Last request failed — see banner.' },
  }[state];
  return (
    <span title={conf.tip} style={syncPillStyle(conf.color)}>
      <span style={{ width: '7px', height: '7px', borderRadius: '50%', background: conf.color, boxShadow: `0 0 6px ${conf.color}` }} />
      {conf.label}
    </span>
  );
}

function syncPillStyle(color: string): React.CSSProperties {
  return {
    display: 'inline-flex',
    alignItems: 'center',
    gap: '6px',
    fontSize: '0.72rem',
    color,
    padding: '3px 8px',
    borderRadius: 'var(--radius-pill)',
    border: '1px solid var(--border)',
    background: 'var(--surface)',
    whiteSpace: 'nowrap',
  };
}

const headerButtonStyle: React.CSSProperties = {
  padding: '4px 12px',
  fontSize: '0.8rem',
  background: 'var(--surface)',
  border: '1px solid var(--border)',
  borderRadius: 'var(--radius-sm)',
  cursor: 'pointer',
  color: 'var(--fg)',
};

/**
 * Fully static category legend. Extracted to a module-scope constant so the
 * component tree is created once and never re-evaluated — the parent's renders
 * during an active run no longer reconcile these ~16 chips.
 */
const CategoryLegend = memo(function CategoryLegend() {
  return (
    <div style={{ marginTop: 'var(--sp-6)', padding: 'var(--sp-3)', background: 'var(--surface-raised)', borderRadius: 'var(--radius-md)', border: '1px solid var(--border)' }}>
      <h4 style={{ margin: '0 0 var(--sp-2) 0', fontSize: '0.85rem', color: 'var(--fg)' }}>Categories</h4>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--sp-2)', fontSize: '0.75rem', color: 'var(--fg-dim)' }}>
        {CATEGORIES.map((cat) => (
          <span key={cat} style={{ padding: '2px 8px', background: 'var(--surface)', borderRadius: 'var(--radius-sm)', border: '1px solid var(--border)' }}>
            {cat}
          </span>
        ))}
      </div>
    </div>
  );
});

const primaryHeaderButtonStyle: React.CSSProperties = {
  ...headerButtonStyle,
  background: 'var(--accent)',
  border: '1px solid var(--accent)',
  color: 'var(--surface)',
  fontWeight: 500,
};
