'use client';

import { useState, useMemo, useEffect } from 'react';
import Link from 'next/link';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
  AlertTriangle, CheckCircle, ChevronDown, ChevronUp,
  RefreshCw, Loader2, Info,
} from 'lucide-react';
import { useAuthStore } from '@/store/useAuthStore';
import {
  fetchLintResults, resolveLintResult, bulkResolveLintResults,
  runLintForTeam, recomputeLintStatus, fetchTeamSettings, updateTeamSettings,
} from '@/lib/api';
import ColumnPicker from '@/components/shared/ColumnPicker';
import { useColumnPreferences } from '@/hooks/useColumnPreferences';
import styles from './page.module.css';
import f from '@/components/shared/FormField.module.css';

const LINTING_COLUMN_DEFS = [
  { id: 'severity', label: 'Severity' },
  { id: 'rule',     label: 'Rule' },
  { id: 'video',    label: 'Video', required: true },
  { id: 'field',    label: 'Field' },
  { id: 'message',  label: 'Message' },
  { id: 'date',     label: 'Date' },
];

const LINTING_DEFAULTS = {
  visible: ['severity', 'rule', 'video', 'field', 'message', 'date'],
  order:   ['severity', 'rule', 'video', 'field', 'message', 'date'],
};

// ── Static rule catalog ────────────────────────────────────────────────────────

const RULE_CATALOG = [
  { code: 'TITLE_WEAK',                 severity: 'WARNING', label: 'Weak title',             desc: 'Title contains weak/filler words that may hurt click-through rate.' },
  { code: 'TITLE_TOO_LONG',             severity: 'WARNING', label: 'Title too long',          desc: 'Title exceeds the 100-character YouTube limit.' },
  { code: 'DESC_MISSING_CTA',           severity: 'WARNING', label: 'Missing CTA',             desc: 'Description has no call-to-action (subscribe, follow, etc.).' },
  { code: 'DESC_MISSING_CHAPTERS',      severity: 'WARNING', label: 'Missing chapters',        desc: 'Description has no timestamp chapters for navigation.' },
  { code: 'DESC_EMPTY_PLACEHOLDER',     severity: 'ERROR',   label: 'Unfilled placeholder',   desc: 'Description still contains an unfilled template placeholder like [TODO].' },
  { code: 'DESC_DUPLICATE_HASHTAG',     severity: 'WARNING', label: 'Duplicate hashtag',       desc: 'The same hashtag appears more than once in the description.' },
  { code: 'DESC_REQUIRED_LINK_MISSING', severity: 'ERROR',   label: 'Required link missing',  desc: 'A required link (e.g. affiliate, sponsor) is absent from the description.' },
  { code: 'DESC_OUTDATED_SPONSOR_COPY', severity: 'ERROR',   label: 'Outdated sponsor copy',  desc: 'A campaign block with an expired end date is still active in the description.' },
  { code: 'REMOTE_CONFLICT',            severity: 'ERROR',   label: 'Remote conflict',         desc: 'The video was modified on YouTube after the last sync — local and remote diverged.' },
] as const;

// ── Helpers ───────────────────────────────────────────────────────────────────

function SevBadge({ sev }: { sev: string }) {
  const cls = sev === 'ERROR' ? styles.sevERROR : sev === 'WARNING' ? styles.sevWARNING : styles.sevINFO;
  const Icon = sev === 'ERROR' ? AlertTriangle : sev === 'WARNING' ? AlertTriangle : Info;
  return (
    <span className={`${styles.sevBadge} ${cls}`}>
      <Icon size={11} />
      {sev}
    </span>
  );
}

function fmtDate(iso: string) {
  return new Date(iso).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
}

// ── Page ──────────────────────────────────────────────────────────────────────

export default function LintingPage() {
  const user = useAuthStore((s) => s.user);
  const teamId = user?.teamId ?? '';
  const qc = useQueryClient();

  const { visible: colVisible, order: colOrder, setColumns } = useColumnPreferences('linting');
  const show = (id: string) => colVisible.includes(id);

  // ── Queries ──
  const { data: results = [], isLoading } = useQuery({
    queryKey: ['lintResults'],
    queryFn: () => fetchLintResults(),
    refetchInterval: 30_000,
  });

  const { data: settings } = useQuery({
    queryKey: ['teamSettings', teamId],
    queryFn: () => fetchTeamSettings(teamId),
    enabled: !!teamId,
  });

  // ── Rule config state ──
  const [rulesOpen, setRulesOpen] = useState(false);
  const [localDisabled, setLocalDisabled] = useState<string[] | null>(null);
  const [rulesSaved, setRulesSaved] = useState(false);
  const [rulesSaving, setRulesSaving] = useState(false);

  const disabledRules = localDisabled ?? settings?.disabledLintRules ?? [];

  function toggleRule(code: string) {
    const current = disabledRules;
    setLocalDisabled(
      current.includes(code) ? current.filter((c) => c !== code) : [...current, code],
    );
    setRulesSaved(false);
  }

  async function saveRules() {
    setRulesSaving(true);
    try {
      await updateTeamSettings(teamId, { disabledLintRules: disabledRules });
      qc.invalidateQueries({ queryKey: ['teamSettings', teamId] });
      qc.invalidateQueries({ queryKey: ['lintResults'] });
      setRulesSaved(true);
      setTimeout(() => setRulesSaved(false), 3000);
    } finally {
      setRulesSaving(false);
    }
  }

  // ── Re-run lint state ──
  const [rerunMsg, setRerunMsg] = useState('');
  const [rerunning, setRerunning] = useState(false);

  async function handleRerun() {
    setRerunning(true);
    setRerunMsg('');
    try {
      const res = await runLintForTeam();
      setRerunMsg(`Queued ${res.queued} video${res.queued !== 1 ? 's' : ''}`);
    } catch {
      setRerunMsg('Failed to queue');
    } finally {
      setRerunning(false);
    }
  }

  // Silently heal any stale lintStatus badges whenever this page is opened
  const { mutate: healLintStatus } = useMutation({ mutationFn: recomputeLintStatus });
  useEffect(() => { healLintStatus(); }, []);

  // ── Filters ──
  const [sevFilter, setSevFilter] = useState<'ALL' | 'ERROR' | 'WARNING'>('ALL');
  const [ruleFilter, setRuleFilter] = useState('');
  const [search, setSearch] = useState('');
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [expandedFix, setExpandedFix] = useState<Set<string>>(new Set());

  const filtered = useMemo(() => {
    return results.filter((r) => {
      if (sevFilter !== 'ALL' && r.severity !== sevFilter) return false;
      if (ruleFilter && r.ruleCode !== ruleFilter) return false;
      if (search && !r.video.title.toLowerCase().includes(search.toLowerCase())) return false;
      return true;
    });
  }, [results, sevFilter, ruleFilter, search]);

  function toggleSelect(id: string) {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  }

  function toggleAll() {
    if (selected.size === filtered.length) {
      setSelected(new Set());
    } else {
      setSelected(new Set(filtered.map((r) => r.id)));
    }
  }

  function toggleFix(id: string) {
    setExpandedFix((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  }

  // ── Mutations ──
  const resolveOneMutation = useMutation({
    mutationFn: resolveLintResult,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['lintResults'] });
      qc.invalidateQueries({ queryKey: ['videos'] });
    },
  });

  const bulkResolveMutation = useMutation({
    mutationFn: bulkResolveLintResults,
    onSuccess: () => {
      setSelected(new Set());
      qc.invalidateQueries({ queryKey: ['lintResults'] });
      qc.invalidateQueries({ queryKey: ['videos'] });
    },
  });

  // ── Summary stats ──
  const errorCount   = results.filter((r) => r.severity === 'ERROR').length;
  const warnCount    = results.filter((r) => r.severity === 'WARNING').length;
  const videosAffected = new Set(results.map((r) => r.video.id)).size;

  return (
    <div className={styles.container}>

      {/* Header */}
      <div className={styles.header}>
        <div className={styles.headerLeft}>
          <span className={styles.eyebrow}>Quality</span>
          <h1>Metadata Linting</h1>
        </div>
        <div className={styles.headerRight}>
          <button
            className="btn btn-secondary"
            onClick={handleRerun}
            disabled={rerunning}
          >
            {rerunning
              ? <><Loader2 size={14} className={styles.spin} /> Running…</>
              : <><RefreshCw size={14} /> Re-run lint</>}
          </button>
          {rerunMsg && <span className={styles.rerunResult}>{rerunMsg}</span>}
        </div>
      </div>

      {/* Summary cards */}
      <div className={styles.cards}>
        <div className={styles.card}>
          <span className={styles.cardLabel}>Open issues</span>
          <span className={styles.cardValue}>{results.length}</span>
          <span className={styles.cardSub}>{errorCount} errors · {warnCount} warnings</span>
        </div>
        <div className={styles.card}>
          <span className={styles.cardLabel}>Videos affected</span>
          <span className={styles.cardValue}>{videosAffected}</span>
          <span className={styles.cardSub}>unique videos with at least one open issue</span>
        </div>
        <div className={styles.card}>
          <span className={styles.cardLabel}>Errors</span>
          <span className={`${styles.cardValue} ${errorCount > 0 ? styles.cardValueError : ''}`}>{errorCount}</span>
          <span className={styles.cardSub}>require immediate attention</span>
        </div>
      </div>

      {/* Rule configuration */}
      <div className={styles.section}>
        <div className={styles.sectionHeader}>
          <span className={styles.sectionTitle}>Rule Configuration</span>
          <button className={styles.collapseBtn} onClick={() => setRulesOpen((o) => !o)}>
            {rulesOpen ? <><ChevronUp size={14} /> Collapse</> : <><ChevronDown size={14} /> Expand</>}
          </button>
        </div>

        {rulesOpen && (
          <>
            <div className={styles.rulesPanel}>
              {RULE_CATALOG.map((rule) => {
                const enabled = !disabledRules.includes(rule.code);
                return (
                  <div key={rule.code} className={styles.ruleRow}>
                    <input
                      type="checkbox"
                      className={styles.ruleToggle}
                      checked={enabled}
                      onChange={() => toggleRule(rule.code)}
                    />
                    <span className={`${styles.ruleLabel} ${!enabled ? styles.ruleLabelDisabled : ''}`}>
                      {rule.label}
                    </span>
                    <SevBadge sev={rule.severity} />
                    <span className={styles.ruleDesc}>{rule.desc}</span>
                  </div>
                );
              })}
            </div>
            <div className={styles.rulesSaveRow}>
              <button
                className="btn btn-primary"
                onClick={saveRules}
                disabled={rulesSaving}
              >
                {rulesSaving ? 'Saving…' : 'Save rule config'}
              </button>
              {rulesSaved && (
                <span className={styles.rulesSaved}>
                  <CheckCircle size={13} /> Saved
                </span>
              )}
            </div>
          </>
        )}
      </div>

      {/* Issue table */}
      <div className={styles.section}>
        <div className={styles.sectionHeader}>
          <span className={styles.sectionTitle}>Open Issues</span>
          <ColumnPicker
            columns={LINTING_COLUMN_DEFS}
            visible={colVisible}
            order={colOrder}
            onChange={(v, o) => setColumns(v, o)}
            defaultVisible={LINTING_DEFAULTS.visible}
            defaultOrder={LINTING_DEFAULTS.order}
          />
        </div>

        {/* Filter bar */}
        <div className={styles.filterBar}>
          <div className={styles.sevPills}>
            {(['ALL', 'ERROR', 'WARNING'] as const).map((s) => (
              <button
                key={s}
                className={`${styles.sevPill} ${sevFilter === s ? styles.sevPillActive : ''}`}
                onClick={() => setSevFilter(s)}
              >
                {s === 'ALL' ? 'All' : s === 'ERROR' ? 'Errors' : 'Warnings'}
                {s !== 'ALL' && (
                  <> · {results.filter((r) => r.severity === s).length}</>
                )}
              </button>
            ))}
          </div>

          <select
            className={`${f.input} ${f.select} ${styles.ruleFilter}`}
            value={ruleFilter}
            onChange={(e) => setRuleFilter(e.target.value)}
          >
            <option value="">All rules</option>
            {RULE_CATALOG.map((r) => (
              <option key={r.code} value={r.code}>{r.label}</option>
            ))}
          </select>

          <input
            className={`${f.input} ${styles.searchInput}`}
            placeholder="Search video title…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />

          {selected.size > 0 && (
            <div className={styles.bulkActions}>
              <button
                className="btn btn-primary"
                onClick={() => bulkResolveMutation.mutate([...selected])}
                disabled={bulkResolveMutation.isPending}
              >
                {bulkResolveMutation.isPending
                  ? 'Resolving…'
                  : `Resolve selected (${selected.size})`}
              </button>
            </div>
          )}
        </div>

        {isLoading ? (
          <div className={styles.state}>
            <Loader2 size={16} className={styles.spin} />
            Loading issues…
          </div>
        ) : filtered.length === 0 ? (
          <div className={styles.empty}>
            <CheckCircle size={40} className={styles.emptyIcon} />
            <span className={styles.emptyTitle}>No open issues</span>
            <span>All metadata looks good! Re-run lint to check for new problems.</span>
          </div>
        ) : (
          <div className={styles.tableWrap}>
            <table className={styles.table}>
              <thead>
                <tr>
                  <th className={styles.checkboxCell}>
                    <input
                      type="checkbox"
                      checked={selected.size === filtered.length && filtered.length > 0}
                      onChange={toggleAll}
                    />
                  </th>
                  {show('severity') && <th>Severity</th>}
                  {show('rule') && <th>Rule</th>}
                  {show('video') && <th>Video</th>}
                  {show('field') && <th>Field</th>}
                  {show('message') && <th>Message</th>}
                  {show('date') && <th>Date</th>}
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((r) => {
                  const ruleMeta = RULE_CATALOG.find((x) => x.code === r.ruleCode);
                  const fixOpen = expandedFix.has(r.id);
                  return (
                    <tr key={r.id}>
                      <td className={styles.checkboxCell}>
                        <input
                          type="checkbox"
                          checked={selected.has(r.id)}
                          onChange={() => toggleSelect(r.id)}
                        />
                      </td>
                      {show('severity') && <td><SevBadge sev={r.severity} /></td>}
                      {show('rule') && <td>{ruleMeta?.label ?? r.ruleCode}</td>}
                      {show('video') && (
                        <td>
                          <Link href={`/videos/${r.video.id}`} className={styles.videoTitle}>
                            {r.video.title}
                          </Link>
                        </td>
                      )}
                      {show('field') && (
                        <td>
                          {r.targetField
                            ? <span className={styles.targetChip}>{r.targetField}</span>
                            : <span style={{ color: 'var(--color-text-faint)' }}>—</span>}
                        </td>
                      )}
                      {show('message') && (
                        <td className={styles.messageCell}>
                          <div className={styles.message}>{r.message}</div>
                          {r.fixSuggestion && (
                            <>
                              <button className={styles.fixBtn} onClick={() => toggleFix(r.id)}>
                                {fixOpen
                                  ? <><ChevronUp size={11} /> Hide suggestion</>
                                  : <><ChevronDown size={11} /> Show fix suggestion</>}
                              </button>
                              {fixOpen && (
                                <div className={styles.fixSuggestion}>{r.fixSuggestion}</div>
                              )}
                            </>
                          )}
                        </td>
                      )}
                      {show('date') && <td className={styles.dateCell}>{fmtDate(r.createdAt)}</td>}
                      <td>
                        <button
                          className={`btn btn-secondary ${styles.resolveBtn}`}
                          onClick={() => resolveOneMutation.mutate(r.id)}
                          disabled={resolveOneMutation.isPending}
                        >
                          Resolve
                        </button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  );
}
