"use client";

import { useMemo, useState } from "react";
import { Activity, Calculator, Database, FileText, History, ScrollText } from "lucide-react";
import type { InspectorComparisonRow, InspectorModule, SourceBinding, SourceRecord, SourceSelector } from "@/lib/types";
import { BindingBadge, selectorDescription } from "@/components/inspector/BindingBadge";
import { BusinessValueRenderer } from "@/components/inspector/BusinessValueRenderer";
import { LongValueDisclosure } from "@/components/inspector/LongValueDisclosure";

interface RowProps {
  row: InspectorComparisonRow;
  module: InspectorModule;
  businessProjection: unknown;
  sources: Record<string, SourceRecord>;
  markers: Map<string, string>;
  activeBindingId?: string;
  onActivate: (bindingId: string, toggle?: boolean) => void;
}

export function ComparisonRowCells(props: RowProps) {
  const bindings = props.row.bindingIds
    .map((id) => props.module.bindings.find((binding) => binding.id === id))
    .filter((binding): binding is SourceBinding => Boolean(binding));
  const businessResult = pointerValue(props.businessProjection, props.row.businessSelector);
  const active = bindings.some((binding) => binding.id === props.activeBindingId);
  return <article className={`comparisonItemRow ${active ? "is-active" : ""}`} data-row-id={props.row.id}>
    <section className="comparisonItemBusiness" aria-label="业务详情中的这一项">
      {props.row.label ? <h4>{props.row.label}</h4> : null}
      {businessResult.found
        ? <BusinessValueRenderer module={props.module} value={businessResult.value} label={props.row.label || props.module.title} />
        : <p className="comparisonEmptyValue">业务详情中的这一项无法定位。</p>}
    </section>
    <section className="comparisonItemEvidence" aria-label="这一项的数据依据">
      {bindings.length ? bindings.map((binding) => <EvidenceSummary
        key={binding.id}
        binding={binding}
        source={props.sources[binding.sourceId]}
        marker={props.markers.get(binding.id) || "S?"}
        active={props.activeBindingId === binding.id}
        onActivate={props.onActivate}
      />) : <p className="comparisonEmptyValue">没有返回来源绑定。</p>}
    </section>
    <section className="comparisonItemSource" aria-label="对应的原始字段或原文">
      {bindings.length ? bindings.map((binding) => <SourceExcerpt
        key={binding.id}
        binding={binding}
        source={props.sources[binding.sourceId]}
        sources={props.sources}
        marker={props.markers.get(binding.id) || "S?"}
      />) : <p className="comparisonEmptyValue">没有可展示的原始记录。</p>}
    </section>
  </article>;
}

function EvidenceSummary({ binding, source, marker, active, onActivate }: { binding: SourceBinding; source?: SourceRecord; marker: string; active: boolean; onActivate: RowProps["onActivate"] }) {
  return <div className={`comparisonEvidenceSummary ${active ? "is-active" : ""}`} data-binding-id={binding.id}>
    <BindingBadge binding={binding} marker={marker} active={active} onActivate={onActivate} />
    <div className="comparisonEvidenceCopy">
      <strong>{source?.label || (binding.selector.kind === "unresolved" ? "无法定位来源" : binding.sourceId)}</strong>
      <small>{roleLabel(binding.role)} · {transformLabel(binding)}</small>
      <details className="comparisonLocatorDetails">
        <summary>定位详情</summary>
        <code>{selectorDescription(binding)}</code>
        <small>{confidenceLabel(binding.evidence.confidence)}{binding.resolution !== "resolved" ? ` · ${resolutionLabel(binding.resolution)}` : ""}</small>
      </details>
    </div>
  </div>;
}

function SourceExcerpt({ binding, source, sources, marker }: { binding: SourceBinding; source?: SourceRecord; sources: Record<string, SourceRecord>; marker: string }) {
  const [rawOpen, setRawOpen] = useState(false);
  const excerpt = useMemo(() => resolveExcerpt(binding.selector, source, sources), [binding.selector, source, sources]);
  const Icon = sourceIcon(source?.kind);
  return <div className={`comparisonSourceExcerpt is-${source?.resultState || "present"}`} data-binding-id={binding.id}>
    <header>
      <Icon aria-hidden="true" size={15} />
      <div><strong>{source?.label || "原始记录不可用"}</strong><small>{sourceKindLabel(source?.kind)}</small></div>
      <span className="sourceExcerptMarker">{marker}</span>
    </header>
    {source ? <SourceMeta source={source} /> : null}
    {source?.resultState === "empty" ? <div className="sourceEmptyResult"><strong>查询完成，返回 0 条</strong><span>这不是记录缺失。</span></div> : null}
    {excerpt.kind === "span" ? <TextSpanExcerpt before={excerpt.before} exact={excerpt.exact} after={excerpt.after} />
      : excerpt.kind === "members" ? <div className="sourceMemberList">{excerpt.items.map((item, index) => <section key={`${item.label}-${index}`}><strong>{item.label}</strong><LongValueDisclosure value={item.value} label="完整成员值" /></section>)}</div>
        : excerpt.kind === "missing" ? <p className="sourceMissingReason">{excerpt.reason}</p>
          : <LongValueDisclosure value={excerpt.value} label="完整字段值" />}
    {source?.rawRecord !== undefined && source?.rawRecord !== null ? <details className="rawRecordDisclosure" onToggle={(event) => setRawOpen(event.currentTarget.open)}>
      <summary><span>完整原始记录</span><small>{source.truncated ? `已省略 ${source.omittedCharacters || 0} 字符` : "按需展开"}</small></summary>
      {rawOpen ? <div><LongValueDisclosure value={source.rawRecord} label="完整原始记录" threshold={Number.MAX_SAFE_INTEGER} /></div> : null}
    </details> : null}
  </div>;
}

type Excerpt =
  | { kind: "value"; value: unknown }
  | { kind: "span"; before: string; exact: string; after: string }
  | { kind: "members"; items: Array<{ label: string; value: unknown }> }
  | { kind: "missing"; reason: string };

function resolveExcerpt(selector: SourceSelector, source: SourceRecord | undefined, sources: Record<string, SourceRecord>): Excerpt {
  if (selector.kind === "unresolved") return { kind: "missing", reason: selector.reason };
  if (!source) return { kind: "missing", reason: "来源记录没有随接口响应返回。" };
  if (selector.kind === "whole-record") return { kind: "value", value: source.rawRecord };
  if (selector.kind === "json-pointer") {
    const selected = pointerValue(source.rawRecord, selector.path);
    return selected.found ? { kind: "value", value: selected.value } : { kind: "missing", reason: `原始记录中不存在字段 ${selector.path}` };
  }
  if (selector.kind === "text-span") {
    const selected = pointerValue(source.rawRecord, selector.path);
    if (!selected.found || typeof selected.value !== "string") return { kind: "missing", reason: `原始记录中不存在文本字段 ${selector.path}` };
    const characters = Array.from(selected.value);
    const start = selector.startCodePoint;
    const end = selector.endCodePoint;
    return {
      kind: "span",
      before: characters.slice(Math.max(0, start - 80), start).join(""),
      exact: characters.slice(start, end).join("") || selector.exactText,
      after: characters.slice(end, end + 80).join(""),
    };
  }
  const items = selector.members.map((member, index) => {
    const memberSource = sources[member.sourceId];
    const resolved = resolveExcerpt(member.selector, memberSource, sources);
    return {
      label: memberSource?.label || `参与记录 ${index + 1}`,
      value: resolved.kind === "value" ? resolved.value
        : resolved.kind === "span" ? `${resolved.before}${resolved.exact}${resolved.after}`
          : resolved.kind === "missing" ? resolved.reason
            : resolved.items.map((item) => item.value),
    };
  });
  return { kind: "members", items };
}

function TextSpanExcerpt({ before, exact, after }: { before: string; exact: string; after: string }) {
  return <p className="comparisonTextExcerpt">{before ? <span>{before}</span> : null}<mark>{exact}</mark>{after ? <span>{after}</span> : null}</p>;
}

function pointerValue(value: unknown, pointer: string): { found: boolean; value: unknown } {
  if (!pointer) return { found: true, value };
  let current = value;
  for (const rawPart of pointer.replace(/^\//, "").split("/")) {
    const part = rawPart.replaceAll("~1", "/").replaceAll("~0", "~");
    if (Array.isArray(current)) {
      const index = Number(part);
      if (!Number.isInteger(index) || index < 0 || index >= current.length) return { found: false, value: undefined };
      current = current[index];
    } else if (current && typeof current === "object" && Object.prototype.hasOwnProperty.call(current, part)) {
      current = (current as Record<string, unknown>)[part];
    } else return { found: false, value: undefined };
  }
  return { found: true, value: current };
}

function SourceMeta({ source }: { source: SourceRecord }) {
  const locator = typeof source.locator === "string" ? undefined : source.locator;
  const fields = locator ? Object.entries(locator).filter(([, value]) => value !== undefined && value !== null && value !== "") : [];
  return fields.length || source.status || typeof source.durationMs === "number" ? <dl className="sourceMeta">
    {fields.map(([key, value]) => <div key={key}><dt>{locatorLabel(key)}</dt><dd><code>{printMeta(value)}</code></dd></div>)}
    {source.status ? <div><dt>状态</dt><dd>{source.status}</dd></div> : null}
    {typeof source.durationMs === "number" ? <div><dt>耗时</dt><dd>{source.durationMs >= 1000 ? `${(source.durationMs / 1000).toFixed(1)} 秒` : `${source.durationMs} ms`}</dd></div> : null}
  </dl> : null;
}

function sourceIcon(kind?: string) {
  if (kind === "database") return Database;
  if (kind === "runtime-event") return Activity;
  if (kind === "artifact") return FileText;
  if (kind === "log-anchor") return ScrollText;
  if (kind === "calculation") return Calculator;
  return History;
}
function sourceKindLabel(kind?: string) { return ({ database: "数据库记录", "runtime-event": "运行事件 / Event Body", artifact: "脚本或候选产物", "log-anchor": "日志锚点", calculation: "可视化确定性计算", "historical-fallback": "历史回退", missing: "原始记录缺失" } as Record<string, string>)[kind || "missing"] || kind || "原始记录缺失"; }
function roleLabel(role: SourceBinding["role"]) { return ({ input: "输入", basis: "判断依据", constraint: "约束", process: "运行过程", output: "产出", status: "状态" } as const)[role]; }
function transformLabel(binding: SourceBinding) { const value = binding.transform; return value.kind === "direct" ? "直接展示" : value.kind === "parsed" ? "确定性解析" : value.kind === "combined" ? "多来源组合" : value.kind === "calculated" ? "确定性计算" : "历史回退"; }
function confidenceLabel(value: SourceBinding["evidence"]["confidence"]) { return ({ exact: "精确对应", "safe-association": "可安全关联", deterministic: "确定性生成", unconfirmed: "关联未确认" } as const)[value]; }
function resolutionLabel(value: SourceBinding["resolution"]) { return ({ partial: "部分定位", missing: "记录缺失", unsafe: "无法安全关联", resolved: "已定位" } as const)[value]; }
function locatorLabel(key: string) { return ({ table: "数据库表", recordId: "记录 ID", eventId: "Event ID", eventName: "Event 名称", eventType: "Event 类型", artifactRef: "产物", logAnchor: "日志锚点", fieldPath: "字段路径", filters: "查询条件", resultCount: "结果数量", reason: "缺失原因" } as Record<string, string>)[key] || key; }
function printMeta(value: unknown) { if (typeof value === "string") return value; try { return JSON.stringify(value); } catch { return String(value); } }
