"use client";

/**
 * Sortable keyword table with expandable rows that reveal the position
 * history chart inline. Supports checkbox selection for bulk delete,
 * text/tag/position/device filters, and column sorting.
 */

import { useMemo, useState } from "react";
import { ArrowUpRight, ArrowDownRight, Minus, ChevronDown, Trash2, ExternalLink, MapPin, Star, FileText, Video, Image as ImageIcon, HelpCircle, BookOpen, ShoppingCart } from "lucide-react";
import PositionChart from "./position-chart";

export interface Competitor {
  domain: string;
  position: number;
  url: string;
  title: string;
}

export interface KeywordRow {
  id: string;
  keyword: string;
  currentPosition: number | null;
  previousPosition: number | null;
  change: number | null;
  bestPosition: number | null;
  url: string | null;
  location: string;
  device: string;
  daysTracked: number;
  tags: string[];
  lastChecked: string | null;
  /** SERP features detected by the search-data provider on the most recent check. */
  serpFeatures?: string[];
  /** Top organic competitors on the same SERP. */
  competitors?: Competitor[];
}

// SERP feature → tooltip + icon. Friendly names match the docs +
// what the AddKeywordsModal already uses.
const SERP_FEATURE_META: Record<string, { label: string; Icon: typeof MapPin }> = {
  local_pack:        { label: "Local Pack",        Icon: MapPin },
  reviews:           { label: "Reviews",           Icon: Star },
  featured_snippet:  { label: "Featured Snippet",  Icon: FileText },
  video:             { label: "Video",             Icon: Video },
  images:            { label: "Images",            Icon: ImageIcon },
  people_also_ask:   { label: "People Also Ask",   Icon: HelpCircle },
  knowledge_graph:   { label: "Knowledge Graph",   Icon: BookOpen },
  shopping:          { label: "Shopping",          Icon: ShoppingCart },
};

interface Props {
  keywords: KeywordRow[];
  query: string;
  tagFilter: string;
  positionFilter: string;
  deviceFilter: string;
  locationFilter?: string;
  onDelete: (ids: string[]) => void;
}

type SortKey = "keyword" | "currentPosition" | "change" | "bestPosition" | "daysTracked";
type SortDir = "asc" | "desc";

function posColor(pos: number | null): string {
  if (pos == null) return "text-slate-400";
  if (pos <= 3) return "text-green-600";
  if (pos <= 10) return "text-blue-600";
  if (pos <= 20) return "text-amber-600";
  return "text-red-500";
}

function matchesPositionFilter(pos: number | null, filter: string): boolean {
  if (filter === "all") return true;
  if (filter === "top3") return pos != null && pos <= 3;
  if (filter === "top10") return pos != null && pos <= 10;
  if (filter === "top20") return pos != null && pos <= 20;
  if (filter === "not_ranking") return pos == null;
  return true;
}

export default function KeywordTable({ keywords, query, tagFilter, positionFilter, deviceFilter, locationFilter = "all", onDelete }: Props) {
  const [sortKey, setSortKey] = useState<SortKey>("keyword");
  const [sortDir, setSortDir] = useState<SortDir>("asc");
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const filtered = useMemo(() => {
    const q = query.toLowerCase();
    return keywords
      .filter((k) => {
        if (q && !k.keyword.toLowerCase().includes(q)) return false;
        if (tagFilter && !k.tags.includes(tagFilter)) return false;
        if (!matchesPositionFilter(k.currentPosition, positionFilter)) return false;
        if (deviceFilter !== "all" && k.device !== deviceFilter) return false;
        if (locationFilter !== "all" && k.location !== locationFilter) return false;
        return true;
      })
      .sort((a, b) => {
        const av = a[sortKey] ?? (sortDir === "asc" ? 999 : -999);
        const bv = b[sortKey] ?? (sortDir === "asc" ? 999 : -999);
        if (typeof av === "string" && typeof bv === "string") return sortDir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
        return sortDir === "asc" ? Number(av) - Number(bv) : Number(bv) - Number(av);
      });
  }, [keywords, query, tagFilter, positionFilter, deviceFilter, sortKey, sortDir]);

  function toggleSort(key: SortKey) {
    if (sortKey === key) setSortDir((d) => (d === "asc" ? "desc" : "asc"));
    else { setSortKey(key); setSortDir("asc"); }
  }
  function toggleExpand(id: string) { setExpanded((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; }); }
  function toggleSelect(id: string) { setSelected((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; }); }
  function toggleAll() { setSelected((s) => s.size === filtered.length ? new Set() : new Set(filtered.map((k) => k.id))); }

  const th = "px-3 py-2.5 text-[10px] font-bold uppercase tracking-widest text-slate-400 text-left cursor-pointer hover:text-slate-700 select-none";
  const sortIcon = (key: SortKey) => sortKey === key ? (sortDir === "asc" ? " ↑" : " ↓") : "";

  return (
    <div>
      {selected.size > 0 && (
        <div className="flex items-center gap-3 mb-3 px-3 py-2 rounded-lg bg-red-50 border border-red-200">
          <span className="text-xs font-semibold text-red-700">{selected.size} selected</span>
          <button onClick={() => { if (confirm(`Delete ${selected.size} keyword(s)?`)) { onDelete(Array.from(selected)); setSelected(new Set()); } }} className="flex items-center gap-1 px-3 py-1.5 bg-red-600 text-white text-xs font-semibold rounded-lg hover:bg-red-700">
            <Trash2 className="w-3 h-3" /> Delete Selected
          </button>
        </div>
      )}

      <div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b border-slate-100 bg-slate-50/80">
                <th className="w-10 px-3 py-2.5"><input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleAll} className="rounded" /></th>
                <th className={th} onClick={() => toggleSort("keyword")}>Keyword{sortIcon("keyword")}</th>
                <th className={`${th} text-center w-20`} onClick={() => toggleSort("currentPosition")}>Pos{sortIcon("currentPosition")}</th>
                <th className={`${th} text-center w-20`} onClick={() => toggleSort("change")}>Change{sortIcon("change")}</th>
                <th className={`${th} text-center w-16`} onClick={() => toggleSort("bestPosition")}>Best{sortIcon("bestPosition")}</th>
                <th className={th}>URL</th>
                <th className={`${th} w-20`}>Loc</th>
                <th className={`${th} w-16`}>Device</th>
                <th className={`${th} w-28`}>SERP</th>
                <th className={`${th} text-center w-16`} onClick={() => toggleSort("daysTracked")}>Days{sortIcon("daysTracked")}</th>
                <th className={th}>Tags</th>
                <th className="w-8" />
              </tr>
            </thead>
            <tbody>
              {filtered.map((kw) => (
                <KeywordRowEl key={kw.id} kw={kw} expanded={expanded.has(kw.id)} selected={selected.has(kw.id)} onToggleExpand={() => toggleExpand(kw.id)} onToggleSelect={() => toggleSelect(kw.id)} />
              ))}
              {filtered.length === 0 && (
                <tr><td colSpan={12} className="py-12 text-center text-sm text-slate-400">No keywords match your filters.</td></tr>
              )}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function KeywordRowEl({ kw, expanded, selected, onToggleExpand, onToggleSelect }: {
  kw: KeywordRow; expanded: boolean; selected: boolean; onToggleExpand: () => void; onToggleSelect: () => void;
}) {
  const changeIcon = kw.change != null && kw.change > 0
    ? <span className="flex items-center gap-0.5 text-green-600 font-bold"><ArrowUpRight className="w-3.5 h-3.5" />{kw.change}</span>
    : kw.change != null && kw.change < 0
      ? <span className="flex items-center gap-0.5 text-red-500 font-bold"><ArrowDownRight className="w-3.5 h-3.5" />{Math.abs(kw.change)}</span>
      : <Minus className="w-3 h-3 text-slate-300" />;

  const shortUrl = kw.url ? kw.url.replace(/^https?:\/\/(www\.)?/, "").slice(0, 40) : "—";

  return (
    <>
      <tr className={`border-b border-slate-100 hover:bg-slate-50 cursor-pointer ${selected ? "bg-brand-50/30" : ""}`} onClick={onToggleExpand}>
        <td className="px-3 py-2.5" onClick={(e) => e.stopPropagation()}>
          <input type="checkbox" checked={selected} onChange={onToggleSelect} className="rounded" />
        </td>
        <td className="px-3 py-2.5 font-semibold text-slate-900">{kw.keyword}</td>
        <td className="px-3 py-2.5 text-center">
          <span className={`text-lg font-bold tabular-nums ${posColor(kw.currentPosition)}`}>
            {kw.currentPosition ?? "—"}
          </span>
        </td>
        <td className="px-3 py-2.5 text-center text-xs">{changeIcon}</td>
        <td className={`px-3 py-2.5 text-center text-xs font-bold tabular-nums ${posColor(kw.bestPosition)}`}>{kw.bestPosition ?? "—"}</td>
        <td className="px-3 py-2.5 text-xs text-slate-600 truncate max-w-[180px]">
          {kw.url ? (
            <a href={kw.url} target="_blank" rel="noopener noreferrer" onClick={(e) => e.stopPropagation()} className="flex items-center gap-1 text-brand-600 hover:underline">
              {shortUrl} <ExternalLink className="w-3 h-3 shrink-0" />
            </a>
          ) : "—"}
        </td>
        <td className="px-3 py-2.5 text-xs text-slate-500">{kw.location.replace("United States", "US")}</td>
        <td className="px-3 py-2.5 text-xs text-slate-500 capitalize">{kw.device.slice(0, 3)}</td>
        <td className="px-3 py-2.5">
          {/* SERP feature badges rendered as small icon chips. Tooltip
              on each chip names the feature. Empty array → em-dash so
              the column alignment stays consistent across rows that
              had a live SERP check vs ones backfilled from GSC. */}
          {kw.serpFeatures && kw.serpFeatures.length > 0 ? (
            <div className="flex flex-wrap gap-0.5">
              {kw.serpFeatures.slice(0, 5).map((f) => {
                const meta = SERP_FEATURE_META[f];
                if (!meta) return null;
                const Icon = meta.Icon;
                return (
                  <span
                    key={f}
                    title={meta.label}
                    className="inline-flex items-center justify-center w-5 h-5 rounded bg-violet-50 text-violet-600 border border-violet-200"
                  >
                    <Icon className="w-3 h-3" />
                  </span>
                );
              })}
            </div>
          ) : (
            <span className="text-slate-300 text-xs">—</span>
          )}
        </td>
        <td className="px-3 py-2.5 text-center text-xs text-slate-500 tabular-nums">{kw.daysTracked}</td>
        <td className="px-3 py-2.5">
          <div className="flex flex-wrap gap-1">{kw.tags.map((t) => <span key={t} className="px-1.5 py-0.5 rounded-md bg-slate-100 text-[10px] font-semibold text-slate-600">{t}</span>)}</div>
        </td>
        <td className="px-3 py-2.5"><ChevronDown className={`w-3.5 h-3.5 text-slate-400 transition-transform ${expanded ? "rotate-180" : ""}`} /></td>
      </tr>
      {expanded && (
        <tr>
          <td colSpan={12} className="bg-slate-50 border-b border-slate-200 px-6 py-4">
            <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-2">Position History — Last 90 Days</p>
            <PositionChart keywordId={kw.id} />

            {/* Competitor panel — only renders when the SERP provider
                captured organic competitor positions for this keyword. Color-coded:
                positions ABOVE the brand's (better rank) = red threat,
                positions BELOW (worse rank) = green opportunity. The brand
                row itself is intentionally not in this list — they're the
                competitors only. */}
            {kw.competitors && kw.competitors.length > 0 && (
              <div className="mt-4">
                <p className="text-[10px] font-bold uppercase tracking-widest text-slate-400 mb-2">
                  Competitors for &quot;{kw.keyword}&quot;
                </p>
                <ul className="space-y-1.5 bg-white rounded-lg border border-slate-200 p-3">
                  {kw.competitors.slice(0, 5).map((comp) => {
                    const isThreat = kw.currentPosition != null && comp.position < kw.currentPosition;
                    const colour = isThreat ? "text-red-600" : "text-emerald-600";
                    return (
                      <li key={`${comp.domain}-${comp.position}`} className="flex items-center gap-3 text-xs">
                        <span className={`tabular-nums font-bold w-8 ${colour}`}>#{comp.position}</span>
                        <span className="text-slate-700 font-semibold w-48 truncate" title={comp.domain}>{comp.domain}</span>
                        {comp.url && (
                          <a
                            href={comp.url}
                            target="_blank"
                            rel="noopener noreferrer"
                            className="text-slate-500 hover:text-brand-600 truncate flex-1 text-[11px]"
                            title={comp.url}
                          >
                            {comp.url.replace(/^https?:\/\/(www\.)?/, "").slice(0, 70)}
                          </a>
                        )}
                      </li>
                    );
                  })}
                </ul>
                <p className="mt-2 text-[10px] text-slate-400">
                  Red = ranks above you (threat) · Green = ranks below you
                </p>
              </div>
            )}
          </td>
        </tr>
      )}
    </>
  );
}
