"use client";

import { useMemo, useState } from "react";
import { AlertTriangle, ArrowDown, Check, ChevronRight, CircleDashed, Database, FileOutput, GitBranch, Link2, ScrollText } from "lucide-react";
import { RichText } from "@/components/ui/RichText";
import { ValueView } from "@/components/ui/ValueView";
import type { CardBusinessData, CardDataCompleteness, CardDataField, CardDataSourceKind, RuntimeUnit } from "@/lib/types";

interface Props {
  data?: CardBusinessData;
  loading?: boolean;
  error?: string;
  missingRef?: boolean;
}

const sourceLabels: Record<CardDataSourceKind, string> = {
  database: "数据库",
  "runtime-event": "运行事件",
  artifact: "产物",
  calculation: "计算生成",
  "log-anchor": "日志锚点",
};

const relationLabels: Record<CardBusinessData["relationKind"], string> = {
  "single-event": "单次运行事件",
  "event-sequence": "事件序列",
  "business-record": "业务记录",
  aggregate: "多条记录聚合",
  calculated: "计算生成",
  missing: "运行关系缺失",
};

const completenessLabels: Record<CardDataCompleteness, string> = {
  complete: "记录完整",
  partial: "部分记录",
  missing: "记录缺失",
};

export function DataFlowRenderer({ data, loading, error, missingRef }: Props) {
  if (loading) return <DataFlowSkeleton />;
  if (error) return <DataFlowState title="数据流暂时不可用" description={error} />;
  if (missingRef) return <DataFlowState title="没有稳定的数据定位" description="这张摘要卡没有独立业务详情，不会推断或拼接它与运行记录的关系。" />;
  if (!data) return <DataFlowState title="还没有数据流记录" description="打开其他卡片，查看其业务输入、运行过程和业务输出。" />;

  const sourceIndex = new Map<string, number>();
  [...data.businessInputs, ...data.businessOutputs].forEach((field) => {
    if (!sourceIndex.has(field.id)) sourceIndex.set(field.id, sourceIndex.size + 1);
  });
  data.runtime.units.forEach((unit) => {
    if (!sourceIndex.has(unit.id)) sourceIndex.set(unit.id, sourceIndex.size + 1);
  });

  return <div className="dataFlow" aria-label="卡片数据流">
    <header className="dataFlowOverview">
      <div className="dataFlowOverviewIcon" aria-hidden="true"><GitBranch size={18} /></div>
      <div>
        <span>{data.cardKind || "业务卡片"}</span>
        <h3>数据关系与完整性</h3>
      </div>
      <div className="dataFlowOverviewBadges">
        <span>{relationLabels[data.relationKind] || data.relationKind}</span>
        <span className={`is-${data.completeness}`}>{completenessLabels[data.completeness]}</span>
      </div>
    </header>

    {data.notices.length ? <div className="dataFlowNotices" aria-label="数据说明">
      {data.notices.map((notice, index) => <p key={`${notice.message}-${index}`} className={`is-${notice.level}`}><AlertTriangle size={14} aria-hidden="true" />{notice.message}</p>)}
    </div> : null}

    <FlowSection stage="input" title="业务输入" description="这一步开始前，可确认获得的信息。">
      <FieldList fields={data.businessInputs} sourceIndex={sourceIndex} empty="没有记录到可确认的业务输入。" />
    </FlowSection>
    <FlowConnector />
    <FlowSection stage="runtime" title="运行过程 / I/O" description={data.runtime.summary || "本次运行没有留下过程概要。"}>
      {data.runtime.units.length ? <div className="runtimeUnitList">
        {data.runtime.units.map((unit, index) => <RuntimeUnitDisclosure key={unit.id || index} unit={unit} index={index + 1} sourceNumber={sourceIndex.get(unit.id)} />)}
      </div> : <EmptyLine>没有保存可下钻的运行单元。</EmptyLine>}
      {data.runtime.calculation ? <div className="dataFlowCalculation"><strong>聚合方式</strong><LongValue value={data.runtime.calculation} /></div> : null}
    </FlowSection>
    <FlowConnector />
    <FlowSection stage="output" title="业务输出" description="运行完成后实际形成或保存的结果。">
      <FieldList fields={data.businessOutputs} sourceIndex={sourceIndex} empty="没有记录到可确认的业务输出。" />
    </FlowSection>
    <FlowConnector muted />
    <DisplayUse data={data} sourceIndex={sourceIndex} />
  </div>;
}

function FlowSection({ stage, title, description, children }: { stage: "input" | "runtime" | "output"; title: string; description: string; children: React.ReactNode }) {
  return <section className="dataFlowStage" data-stage={stage} aria-labelledby={`data-flow-${stage}`}>
    <header>
      <span className="dataFlowStageIcon" aria-hidden="true">{stage === "input" ? <Database size={16} /> : stage === "runtime" ? <CircleDashed size={16} /> : <FileOutput size={16} />}</span>
      <div><h3 id={`data-flow-${stage}`}>{title}</h3><p>{description}</p></div>
    </header>
    {children}
  </section>;
}

function FlowConnector({ muted = false }: { muted?: boolean }) {
  return <div className={`dataFlowConnector ${muted ? "is-muted" : ""}`} aria-hidden="true"><ArrowDown size={14} /></div>;
}

function FieldList({ fields, sourceIndex, empty }: { fields: CardDataField[]; sourceIndex: Map<string, number>; empty: string }) {
  if (!fields.length) return <EmptyLine>{empty}</EmptyLine>;
  return <div className="dataFieldList">
    {fields.map((field, index) => <article className="dataField" key={`${field.id}-${index}`}>
      <header>
        <SourceMarker number={sourceIndex.get(field.id)} />
        <h4>{field.label}</h4>
        <span className={`dataCompleteness is-${field.completeness}`}>{completenessLabels[field.completeness]}</span>
      </header>
      <LongValue value={field.value} />
      <footer>
        <SourceBadge kind={field.source.kind} />
        <span>{field.source.label}</span>
        {field.source.ref ? <code>{field.source.ref}</code> : null}
        {field.source.fieldPath ? <code>{field.source.fieldPath}</code> : null}
        <span className="dataRelation">{fieldRelationLabel(field)}</span>
      </footer>
    </article>)}
  </div>;
}

function RuntimeUnitDisclosure({ unit, index, sourceNumber }: { unit: RuntimeUnit; index: number; sourceNumber?: number }) {
  const [open, setOpen] = useState(false);
  const title = unit.label || `运行单元 ${index}`;
  return <details className="runtimeUnit" open={open}>
    <summary aria-expanded={open} onClick={(event) => { event.preventDefault(); setOpen((current) => !current); }}>
      <ChevronRight className="dataDisclosureChevron" size={15} aria-hidden="true" />
      <SourceMarker number={sourceNumber} />
      <strong>{title}</strong>
      {unit.status ? <span className={`runtimeStatus is-${statusClass(unit.status)}`}>{unit.status}</span> : null}
      {typeof unit.durationMs === "number" ? <small>{formatDuration(unit.durationMs)}</small> : null}
    </summary>
    <div className="runtimeUnitBody">
      {unit.summary ? <LongValue value={unit.summary} /> : null}
      {unit.input !== undefined ? <RuntimeValue label="输入" value={unit.input} /> : null}
      {unit.output !== undefined ? <RuntimeValue label="输出" value={unit.output} /> : null}
      {unit.eventRef ? <p className="runtimeEventRef"><span>运行事件</span><code>{unit.eventRef}</code></p> : null}
      {unit.completeness ? <p className="runtimeCompleteness"><Check size={13} aria-hidden="true" />{completenessLabels[unit.completeness]}</p> : null}
    </div>
  </details>;
}

function RuntimeValue({ label, value }: { label: string; value: unknown }) {
  return <section className="runtimeValue"><h5>{label}</h5><LongValue value={value} /></section>;
}

function DisplayUse({ data, sourceIndex }: { data: CardBusinessData; sourceIndex: Map<string, number> }) {
  const { businessModules, cardFields, unusedSourceIds } = data.displayUse;
  return <section className="displayUse" aria-labelledby="data-flow-display-use">
    <header><span className="dataFlowStageIcon" aria-hidden="true"><Link2 size={16} /></span><div><h3 id="data-flow-display-use">页面如何使用这些数据</h3><p>同一编号把原始字段、业务详情模块与卡片摘要对应起来。</p></div></header>
    <div className="displayUseGroups">
      <MappingGroup title="业务详情" items={businessModules.map((module) => ({ key: module.id, title: module.title, sourceIds: module.sourceIds }))} sourceIndex={sourceIndex} />
      <MappingGroup title="卡片摘要" items={cardFields.map((field) => ({ key: field.key, title: field.label, sourceIds: field.sourceIds, note: field.transform }))} sourceIndex={sourceIndex} />
    </div>
    {unusedSourceIds.length ? <div className="unusedSources"><strong>未用于页面展示</strong><SourceReferences ids={unusedSourceIds} sourceIndex={sourceIndex} /></div> : null}
  </section>;
}

function MappingGroup({ title, items, sourceIndex }: { title: string; items: Array<{ key: string; title: string; sourceIds: string[]; note?: string }>; sourceIndex: Map<string, number> }) {
  return <section className="mappingGroup"><h4>{title}</h4>{items.length ? <ul>{items.map((item) => <li key={item.key}><div><strong>{item.title}</strong>{item.note ? <small>{item.note}</small> : null}</div><SourceReferences ids={item.sourceIds} sourceIndex={sourceIndex} /></li>)}</ul> : <EmptyLine>没有配置展示映射。</EmptyLine>}</section>;
}

function SourceReferences({ ids, sourceIndex }: { ids: string[]; sourceIndex: Map<string, number> }) {
  if (!ids.length) return <span className="sourceReferenceEmpty">无直接来源</span>;
  return <span className="sourceReferences">{ids.map((id) => <span key={id} title={id}>F{sourceIndex.get(id) || "?"}</span>)}</span>;
}

function SourceMarker({ number }: { number?: number }) {
  return <span className="sourceMarker" title={number ? `数据字段 F${number}` : "运行单元"}>{number ? `F${number}` : "I/O"}</span>;
}

function SourceBadge({ kind }: { kind: CardDataSourceKind }) {
  const Icon = kind === "database" ? Database : kind === "artifact" ? FileOutput : kind === "log-anchor" ? ScrollText : kind === "runtime-event" ? CircleDashed : GitBranch;
  return <span className={`dataSourceBadge is-${kind}`}><Icon size={12} aria-hidden="true" />{sourceLabels[kind]}</span>;
}

function LongValue({ value }: { value: unknown }) {
  const { text, structured } = useMemo(() => displayValue(value), [value]);
  const [open, setOpen] = useState(false);
  if (text.length <= 800) return structured ? <ValueView value={value} /> : <RichText className="dataFlowText" value={text || "（空）"} />;
  const preview = `${text.slice(0, 240).trimEnd()}…`;
  return <details className="longDataValue" open={open}>
    <summary aria-expanded={open} onClick={(event) => { event.preventDefault(); setOpen((current) => !current); }}>
      <span className="longDataSummaryLine"><ChevronRight className="dataDisclosureChevron" size={15} aria-hidden="true" /><span>{open ? "收起完整内容" : "展开完整内容"}</span><small>{text.length.toLocaleString("zh-CN")} 字符</small></span>
      {!open ? <span className="longDataPreview">{preview}</span> : null}
    </summary>
    {open ? structured ? <ValueView value={value} /> : <RichText className="dataFlowText" value={text} /> : null}
  </details>;
}

function EmptyLine({ children }: { children: React.ReactNode }) { return <p className="dataFlowEmpty">{children}</p>; }

function DataFlowState({ title, description }: { title: string; description: string }) {
  return <div className="dataFlowState" role="status"><GitBranch size={20} aria-hidden="true" /><h3>{title}</h3><p>{description}</p></div>;
}

function DataFlowSkeleton() {
  return <div className="dataFlowSkeleton" aria-label="正在加载数据流"><div /><span /><span /><div /><span /><span /><div /><span /></div>;
}

function displayValue(value: unknown) {
  if (typeof value === "string") return { text: value, structured: false };
  if (value === undefined) return { text: "（未记录）", structured: false };
  if (value === null) return { text: "（空）", structured: false };
  try { return { text: JSON.stringify(value, null, 2), structured: true }; }
  catch { return { text: String(value), structured: false }; }
}

function fieldRelationLabel(field: CardDataField) {
  if (field.relation === "available-upstream") return "可确认是上游信息，但无法确认是否被本次决策采用";
  return ({
    "direct-input": "本次运行的直接输入",
    "previous-result": "上一步形成的结果",
    "standing-constraint": "持续生效的约束",
    "explicit-basis": "记录明确采用的依据",
    "persisted-output": "已保存的业务输出",
  } as Record<string, string>)[field.relation] || field.relation;
}

function statusClass(value: string) {
  const normalized = value.toLowerCase();
  if (["success", "completed", "hit", "passed"].includes(normalized)) return "success";
  if (["failed", "failure", "error"].includes(normalized)) return "failure";
  if (["running", "processing"].includes(normalized)) return "running";
  return "neutral";
}

function formatDuration(value: number) {
  if (value < 1000) return `${value}ms`;
  if (value < 60_000) return `${(value / 1000).toFixed(value < 10_000 ? 1 : 0)}s`;
  return `${Math.floor(value / 60_000)}m ${Math.round((value % 60_000) / 1000)}s`;
}
