import * as React from "react";
import { Building2, Info } from "lucide-react";
import { cn } from "@/lib/utils";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { Progress } from "@/components/ui/progress";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { PolicyVerdictBadge } from "./policy-ai-primitives";
import type {
  PolicyBankVerdict,
  PolicyCitationItem,
  PolicyQueryContext,
  PolicyRankedBankItem,
  PolicyVerdict,
} from "./policy-ai-primitives";

// ---------------------------------------------------------------------------
// PolicySingleBankAnswer props
// ---------------------------------------------------------------------------

export interface PolicySingleBankAnswerProps {
  bankName: string;
  verdict: PolicyVerdict;
  /** Prose answer text. May contain inline [N] citation markers. */
  answer: string;
  citations: PolicyCitationItem[];
  /**
   * Optional query context — when provided, policy type and categories are
   * rendered as an Info icon tooltip inside the bank header.
   */
  queryContext?: PolicyQueryContext;
  className?: string;
}

// ---------------------------------------------------------------------------
// PolicyComparisonTable props
// ---------------------------------------------------------------------------

export interface PolicySummaryCounts {
  yes: number;
  softNo: number;
  no: number;
  total: number;
}

export interface PolicyComparisonTableProps {
  /** Column headers — one per policy category queried. */
  categories: string[];
  banks: PolicyBankVerdict[];
  summaryCounts: PolicySummaryCounts;
  citations: PolicyCitationItem[];
  /** Optional query context — shown as Info icon tooltip in the summary header. */
  queryContext?: PolicyQueryContext;
  className?: string;
}

// ---------------------------------------------------------------------------
// PolicyRankedList props
// ---------------------------------------------------------------------------

export interface PolicyRankedListProps {
  /** Categories used in the TOPSIS ranking (shown in header). */
  categories: string[];
  banks: PolicyRankedBankItem[];
  citations: PolicyCitationItem[];
  /** Optional query context — shown as Info icon tooltip in the ranking header. */
  queryContext?: PolicyQueryContext;
  className?: string;
}

// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------

/** Bank initial avatar — consistent across all response formats. */
function BankAvatar({ name }: { name: string }) {
  return (
    <Avatar aria-hidden="true" className="size-7 shrink-0">
      <AvatarFallback>{name.charAt(0).toUpperCase()}</AvatarFallback>
    </Avatar>
  );
}

/** Info icon with a tooltip. Pass `label` as the tooltip text. */
function QueryContextInfo({ label }: { label: string }) {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger
          render={
            <span
              className="shrink-0 text-muted-foreground/60 hover:text-muted-foreground cursor-default transition-colors"
              aria-label={label}
            >
              <Info className="size-3.5" aria-hidden="true" />
            </span>
          }
        />
        <TooltipContent side="top">{label}</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

/** Format a PolicyQueryContext into a human-readable tooltip label. */
function queryContextLabel(context: PolicyQueryContext): string {
  return [
    context.policyType,
    ...context.categories,
    context.queryType.replace(/_/g, " "),
  ].join(" · ");
}

/** Inline [N] badge that opens a Popover with the source citation details. */
function CitationBadge({ citation }: { citation: PolicyCitationItem }) {
  return (
    <Popover>
      <PopoverTrigger
        render={
          <button type="button" aria-label={`View source ${citation.index}`}>
            <Badge
              variant="secondary"
              className="cursor-pointer px-1.5 py-0 text-xs mx-0.5 align-baseline hover:bg-secondary/80 transition-colors"
            >
              {citation.index}
            </Badge>
          </button>
        }
      />
      <PopoverContent className="w-72 p-3" sideOffset={6}>
        <div className="flex flex-col gap-2">
          <div className="flex items-center gap-1.5 flex-wrap">
            <span className="text-sm font-semibold text-foreground">
              {citation.bankName}
            </span>
            <Badge variant="secondary" className="text-xs px-1.5 py-0">
              {citation.category}
            </Badge>
          </div>
          <p className="text-sm text-muted-foreground">{citation.excerpt}</p>
        </div>
      </PopoverContent>
    </Popover>
  );
}

/** Renders answer prose with [N] markers replaced by inline CitationBadge. */
function AnswerWithCitations({
  answer,
  citations,
}: {
  answer: string;
  citations: PolicyCitationItem[];
}) {
  const citationMap = new Map(citations.map((c) => [c.index, c]));
  const parts = answer.split(/(\[\d+\])/g);

  return (
    <p className="text-sm text-foreground leading-relaxed whitespace-pre-line">
      {parts.map((part, i) => {
        const match = part.match(/^\[(\d+)\]$/);
        if (match) {
          const citation = citationMap.get(parseInt(match[1], 10));
          if (citation) return <CitationBadge key={i} citation={citation} />;
          return (
            <span key={i} className="text-caption text-muted-foreground">
              {part}
            </span>
          );
        }
        return <React.Fragment key={i}>{part}</React.Fragment>;
      })}
    </p>
  );
}

// ---------------------------------------------------------------------------
// PolicySingleBankAnswer (Molecule) — Type A response
// ---------------------------------------------------------------------------

/**
 * Displays a single-bank policy answer (Type A RAG retrieval).
 * Shows the bank name, verdict badge, AI-generated prose with inline citation
 * markers, and a collapsible citation panel listing source excerpts.
 *
 * @example
 * <PolicySingleBankAnswer
 *   bankName="AMP"
 *   verdict="yes"
 *   answer="AMP accepts casual income after 6 months [1]."
 *   citations={citations}
 * />
 */
export function PolicySingleBankAnswer({
  bankName,
  verdict,
  answer,
  citations,
  queryContext,
  className,
}: PolicySingleBankAnswerProps) {
  return (
    <div
      data-slot="policy-single-bank-answer"
      className={cn("border border-border bg-card flex flex-col", className)}
    >
      {/* Bank header */}
      <div className="flex items-center gap-3 px-4 py-3 border-b border-border">
        <BankAvatar name={bankName} />
        <div className="flex-1 flex items-center gap-1.5 min-w-0">
          <span className="font-semibold text-sm text-foreground truncate">
            {bankName}
          </span>
          {queryContext && (
            <QueryContextInfo label={queryContextLabel(queryContext)} />
          )}
        </div>
        <PolicyVerdictBadge verdict={verdict} />
      </div>

      {/* Answer prose */}
      <div className="px-4 py-3">
        <AnswerWithCitations answer={answer} citations={citations} />
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// PolicyComparisonTable (Molecule) — Type B/C cross-bank response
// ---------------------------------------------------------------------------

type VerdictFilter = "all" | PolicyVerdict;

/**
 * Displays a cross-bank policy comparison matrix (Type B/C retrieval).
 * Shows a summary count row, search input, verdict filter tabs, a table
 * with one row per bank and one column per policy category, and a
 * collapsible citation panel at the bottom.
 *
 * @example
 * <PolicyComparisonTable
 *   categories={["Casual Income"]}
 *   banks={banks}
 *   summaryCounts={{ yes: 11, softNo: 5, no: 4, total: 20 }}
 *   citations={citations}
 * />
 */
export function PolicyComparisonTable({
  categories,
  banks,
  summaryCounts,
  citations,
  queryContext,
  className,
}: PolicyComparisonTableProps) {
  const [search, setSearch] = React.useState("");
  const [filter, setFilter] = React.useState<VerdictFilter>("all");

  const filtered = React.useMemo(() => {
    let result = banks;
    if (search.trim()) {
      const q = search.toLowerCase();
      result = result.filter((b) => b.bankName.toLowerCase().includes(q));
    }
    if (filter !== "all") {
      result = result.filter((b) => b.verdict === filter);
    }
    return result;
  }, [banks, search, filter]);

  return (
    <div
      data-slot="policy-comparison-table"
      className={cn("border border-border bg-card flex flex-col", className)}
    >
      {/* Summary counts */}
      <div className="flex items-center gap-3 px-4 py-2.5 border-b border-border bg-muted/30">
        <Building2
          className="size-3.5 text-muted-foreground shrink-0"
          aria-hidden="true"
        />
        <div className="flex items-center gap-2 text-sm flex-wrap flex-1 min-w-0">
          <span className="font-semibold text-foreground">
            {summaryCounts.total} banks
          </span>
          <span className="text-muted-foreground">·</span>
          <Badge variant="success" className="text-xs px-1.5 py-0">
            {summaryCounts.yes} Yes
          </Badge>
          <Badge variant="warning" className="text-xs px-1.5 py-0">
            {summaryCounts.softNo} Soft No
          </Badge>
          <Badge variant="destructive" className="text-xs px-1.5 py-0">
            {summaryCounts.no} No
          </Badge>
        </div>
        {queryContext && (
          <QueryContextInfo label={queryContextLabel(queryContext)} />
        )}
      </div>

      {/* Search input */}
      <div className="px-4 py-2.5 border-b border-border">
        <Input
          aria-label="Search banks"
          placeholder="Search banks…"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="h-8 text-sm"
        />
      </div>

      {/* Verdict filter tabs */}
      <div className="border-b border-border px-4 pt-1">
        <Tabs
          value={filter}
          onValueChange={(v) => setFilter(v as VerdictFilter)}
        >
          <TabsList variant="line" className="justify-start h-8 gap-0 -mb-px">
            <TabsTrigger value="all" className="text-sm px-3 h-7">
              All
            </TabsTrigger>
            <TabsTrigger value="yes" className="text-sm px-3 h-7">
              Yes
            </TabsTrigger>
            <TabsTrigger value="soft_no" className="text-sm px-3 h-7">
              Soft No
            </TabsTrigger>
            <TabsTrigger value="no" className="text-sm px-3 h-7">
              No
            </TabsTrigger>
          </TabsList>
        </Tabs>
      </div>

      {/* Bank table */}
      <div className="overflow-x-auto">
        <table className="w-full text-sm border-collapse">
          <thead>
            <tr className="border-b border-border bg-muted/20">
              <th className="text-left text-sm font-medium text-muted-foreground px-4 py-2">
                Bank
              </th>
              {categories.map((cat) => (
                <th
                  key={cat}
                  className="text-left text-sm font-medium text-muted-foreground px-3 py-2 w-px whitespace-nowrap"
                >
                  {cat}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {filtered.length === 0 ? (
              <tr>
                <td
                  colSpan={categories.length + 1}
                  className="px-4 py-6 text-center text-sm text-muted-foreground"
                >
                  No banks match your search.
                </td>
              </tr>
            ) : (
              filtered.map((bank) => (
                <tr key={bank.bankName} className="border-b border-border">
                  <td className="px-4 py-2.5">
                    <div className="flex items-center gap-2">
                      <BankAvatar name={bank.bankName} />
                      <div className="flex flex-col gap-0.5 min-w-0">
                        <span className="text-sm font-medium text-foreground leading-snug">
                          {bank.bankName}
                        </span>
                        {bank.details && (
                          <span className="text-caption text-muted-foreground">
                            {bank.details}
                          </span>
                        )}
                      </div>
                    </div>
                  </td>
                  {categories.map((cat) => (
                    <td
                      key={cat}
                      className="px-3 py-2.5 align-top w-px whitespace-nowrap"
                    >
                      <PolicyVerdictBadge verdict={bank.verdict} />
                    </td>
                  ))}
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Internal: verdict → progress bar colour map (track + indicator)
// ---------------------------------------------------------------------------

const VERDICT_SCORE_COLORS: Record<
  string,
  { track: string; indicator: string }
> = {
  yes: { track: "bg-success/20", indicator: "bg-success" },
  soft_no: { track: "bg-warning/20", indicator: "bg-warning" },
  no: { track: "bg-destructive/20", indicator: "bg-destructive" },
  unknown: { track: "bg-muted", indicator: "bg-muted-foreground" },
};

// ---------------------------------------------------------------------------
// PolicyRankedList (Molecule) — Type C ranking response
// ---------------------------------------------------------------------------

/**
 * Displays a TOPSIS-ranked list of banks (Type C retrieval).
 * Each bank row shows rank number, name, a colour-coded score progress bar,
 * percentage, verdict badge, and key policy highlights as bullet points.
 * A collapsible citation panel appears at the bottom.
 *
 * @example
 * <PolicyRankedList
 *   categories={["Bonus Income", "Add Backs"]}
 *   banks={rankedBanks}
 *   citations={citations}
 * />
 */
export function PolicyRankedList({
  categories,
  banks,
  citations,
  queryContext,
  className,
}: PolicyRankedListProps) {
  return (
    <div
      data-slot="policy-ranked-list"
      className={cn("border border-border bg-card flex flex-col", className)}
    >
      {/* Header */}
      <div className="flex items-center gap-2 px-4 py-2.5 border-b border-border bg-muted/30">
        <span className="text-sm text-muted-foreground shrink-0">Ranked:</span>
        <div className="flex items-center gap-1 flex-wrap flex-1 min-w-0">
          {categories.map((cat, i) => (
            <React.Fragment key={cat}>
              {i > 0 && (
                <span className="text-sm text-muted-foreground">+</span>
              )}
              <Badge variant="secondary" className="text-xs px-1.5 py-0">
                {cat}
              </Badge>
            </React.Fragment>
          ))}
        </div>
        <span className="text-sm text-muted-foreground shrink-0">
          {banks.length} banks
        </span>
        {queryContext && (
          <QueryContextInfo label={queryContextLabel(queryContext)} />
        )}
      </div>

      {/* Ranked rows */}
      <div className="divide-y divide-border">
        {banks.map((bank) => {
          const scorePercent = Math.round(bank.score * 100);

          return (
            <div key={bank.bankName} className="flex flex-col">
              <div className="flex items-center gap-3 px-4 py-3">
                <span className="shrink-0 w-6 text-center text-sm font-bold text-muted-foreground">
                  #{bank.rank}
                </span>

                <div className="flex-1 min-w-0 flex flex-col gap-1.5">
                  <div className="flex items-center justify-between gap-2">
                    <span className="text-sm font-medium text-foreground truncate">
                      {bank.bankName}
                    </span>
                    <div className="flex items-center gap-2 shrink-0">
                      <span className="text-sm text-muted-foreground font-mono">
                        {scorePercent}%
                      </span>
                      <PolicyVerdictBadge verdict={bank.verdict} />
                    </div>
                  </div>
                  <Progress
                    value={scorePercent}
                    className={cn(
                      "h-1.5",
                      (
                        VERDICT_SCORE_COLORS[bank.verdict] ??
                        VERDICT_SCORE_COLORS.unknown
                      ).track,
                    )}
                    indicatorClassName={
                      (
                        VERDICT_SCORE_COLORS[bank.verdict] ??
                        VERDICT_SCORE_COLORS.unknown
                      ).indicator
                    }
                    aria-label={`${bank.bankName} policy score: ${scorePercent}%`}
                  />
                </div>
              </div>

              {bank.highlights.length > 0 && (
                <div className="px-4 pb-3 pl-[52px]">
                  <ul className="flex flex-col gap-0.5">
                    {bank.highlights.map((h, i) => (
                      <li
                        key={i}
                        className="text-sm text-muted-foreground leading-relaxed list-disc list-inside"
                      >
                        {h}
                      </li>
                    ))}
                  </ul>
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}
