import { useState } from "react";

import { getApiErrorMessage } from "../../../api/client";
import { Icon } from "../../../components/Icon";
import type { RejectionReason, ReviewBundle } from "../types";

interface DocumentReviewPanelProps {
  bundle: ReviewBundle | undefined;
  error: unknown;
  isLoading: boolean;
  isDecisionPending: boolean;
  decisionError: unknown;
  onApprove: () => void;
  onReject: (reason: RejectionReason) => void;
  onRetry: () => void;
}

const REJECTION_REASONS: { value: RejectionReason; label: string }[] = [
  { value: "RIGHTS_NOT_VERIFIED", label: "资料权利或授权未核实" },
  { value: "CONTENT_QUALITY_REJECTED", label: "内容质量不满足入库要求" },
  { value: "CLOUD_PROCESSING_REJECTED", label: "不允许提交云端处理" },
];

function reviewStateLabel(state: string): string {
  const labels: Record<string, string> = {
    LOCAL_PARSED_PENDING_CLOUD_REVIEW: "等待人工复核",
    CLOUD_APPROVED: "已批准出域",
    REJECTED: "已拒绝出域",
    OCR_REQUIRED: "需要可靠 OCR",
  };
  return labels[state] ?? state;
}

export function DocumentReviewPanel({
  bundle,
  error,
  isLoading,
  isDecisionPending,
  decisionError,
  onApprove,
  onReject,
  onRetry,
}: DocumentReviewPanelProps) {
  const [confirmed, setConfirmed] = useState(false);
  const [rejectionReason, setRejectionReason] = useState<RejectionReason>("RIGHTS_NOT_VERIFIED");
  if (isLoading) {
    return (
      <section className="document-panel document-review-panel" aria-live="polite">
        <div className="document-review-state">
          <span className="button-spinner button-spinner--forest" aria-hidden="true" />
          <h2>正在加载完整复核包</h2>
          <p>系统会校验分页期间版本与 revision 保持一致。</p>
        </div>
      </section>
    );
  }

  if (error !== null) {
    return (
      <section className="document-panel document-review-panel">
        <div className="document-review-state document-review-state--error" role="alert">
          <Icon name="alert" size={24} />
          <h2>复核资料暂不可用</h2>
          <p>{getApiErrorMessage(error)}</p>
          <button className="secondary-button" onClick={onRetry} type="button">
            重新加载
          </button>
        </div>
      </section>
    );
  }

  if (bundle === undefined) {
    return (
      <section className="document-panel document-review-panel">
        <div className="document-review-state">
          <Icon name="document" size={28} />
          <h2>选择文档开始复核</h2>
          <p>上传与解析成功不代表允许向量化，必须先检查出域清单。</p>
        </div>
      </section>
    );
  }

  const version = bundle.version;
  if (version === null) {
    return (
      <section className="document-panel document-review-panel">
        <div className="document-review-state">
          <Icon name="layers" size={28} />
          <h2>{bundle.document.filename}</h2>
          <p>解析版本尚未生成，请等待本地 Worker 或刷新文档。</p>
        </div>
      </section>
    );
  }

  const expectedChunksMatch = version.expected_chunk_count === bundle.chunks.length;
  const reviewable =
    version.review_state === "LOCAL_PARSED_PENDING_CLOUD_REVIEW" &&
    version.status === "PROCESSING" &&
    version.outbound_manifest_sha256 !== null &&
    bundle.chunks.length > 0 &&
    expectedChunksMatch;

  return (
    <section
      className="document-panel document-review-panel"
      aria-labelledby="document-review-title"
    >
      <div className="document-review-header">
        <div>
          <span className="eyebrow">MANIFEST-BOUND REVIEW</span>
          <h2 id="document-review-title">{bundle.document.filename}</h2>
          <span className="document-review-state-badge">
            {reviewStateLabel(version.review_state)}
          </span>
        </div>
        <dl>
          <div>
            <dt>Revision</dt>
            <dd>{version.review_revision}</dd>
          </div>
          <div>
            <dt>版本状态</dt>
            <dd>{version.status}</dd>
          </div>
          <div>
            <dt>页 / 块 / Chunk</dt>
            <dd>
              {bundle.pages.length} / {bundle.blocks.length} / {bundle.chunks.length}
            </dd>
          </div>
        </dl>
      </div>

      <div className="document-manifest">
        <div>
          <span>出域清单 SHA-256</span>
          <code>{version.outbound_manifest_sha256 ?? "尚未生成"}</code>
        </div>
        <div>
          <span>Parser / Chunk Profile</span>
          <code>{version.parser_profile_hash}</code>
          <code>{version.chunk_profile_hash}</code>
        </div>
        <div>
          <span>Cloud Policy</span>
          <code>{version.cloud_policy_id}</code>
        </div>
      </div>

      {!expectedChunksMatch && (
        <div className="document-review-warning" role="alert">
          <Icon name="alert" size={18} />
          <span>
            期望 {version.expected_chunk_count} 个 Chunk，但完整复核包返回 {bundle.chunks.length}
            个，已禁止批准。
          </span>
        </div>
      )}

      <div className="document-review-content">
        <section aria-labelledby="review-pages-title">
          <div className="document-subheading">
            <h3 id="review-pages-title">本地解析页</h3>
            <span>{bundle.pages.length}</span>
          </div>
          {bundle.pages.length === 0 ? (
            <p className="document-empty-copy">暂无可复核页面；PDF 可能需要 OCR。</p>
          ) : (
            <div className="document-evidence-list">
              {bundle.pages.map((page) => (
                <details key={page.id}>
                  <summary>
                    逻辑页 {page.page_number ?? page.ordinal + 1} · 行 {page.line_start}-
                    {page.line_end}
                  </summary>
                  <p>{page.text}</p>
                  <code>{page.text_sha256}</code>
                </details>
              ))}
            </div>
          )}
          <div className="document-subheading document-subheading--blocks">
            <h3>结构化块</h3>
            <span>{bundle.blocks.length}</span>
          </div>
          {bundle.blocks.length === 0 ? (
            <p className="document-empty-copy">暂无结构化块。</p>
          ) : (
            <div className="document-evidence-list">
              {bundle.blocks.map((block) => (
                <details key={block.id}>
                  <summary>
                    {block.kind} · {block.section_path.join(" / ") || "未标注章节"} · 行
                    {block.line_start}-{block.line_end}
                  </summary>
                  <p>{block.text}</p>
                  <code>{block.anchor_id}</code>
                </details>
              ))}
            </div>
          )}
        </section>

        <section aria-labelledby="review-chunks-title">
          <div className="document-subheading">
            <h3 id="review-chunks-title">拟出域 Chunk</h3>
            <span>{bundle.chunks.length}</span>
          </div>
          {bundle.chunks.length === 0 ? (
            <p className="document-empty-copy">没有可向量化 Chunk。</p>
          ) : (
            <div className="document-chunk-list">
              {bundle.chunks.map((chunk) => (
                <article key={`${chunk.ordinal}:${chunk.cloud_text_sha256}`}>
                  <header>
                    <strong>Chunk {chunk.ordinal + 1}</strong>
                    <span>{chunk.token_count} tokens</span>
                  </header>
                  <p>{chunk.cloud_text}</p>
                  <footer>
                    <span>
                      {chunk.section_path.length === 0
                        ? "未标注章节"
                        : chunk.section_path.join(" / ")}
                    </span>
                    <code>{chunk.cloud_text_sha256.slice(0, 18)}…</code>
                  </footer>
                </article>
              ))}
            </div>
          )}
        </section>
      </div>

      <div className="document-human-gate">
        <div className="document-human-gate__notice">
          <Icon name="shield" size={20} />
          <div>
            <strong>必须由人工确认此精确清单</strong>
            <span>
              批准会绑定当前 revision 与
              manifest；内容发生变化后旧确认自动失效。请勿上传未获授权资料。
            </span>
          </div>
        </div>
        <label className="document-confirmation">
          <input
            checked={confirmed}
            disabled={!reviewable || isDecisionPending}
            onChange={(event) => setConfirmed(event.target.checked)}
            type="checkbox"
          />
          我已逐项核对内容、授权范围与出域清单，确认允许向量化
        </label>
        <div className="document-decision-actions">
          <button
            className="primary-button"
            disabled={!reviewable || !confirmed || isDecisionPending}
            onClick={onApprove}
            type="button"
          >
            {isDecisionPending && <span className="button-spinner" aria-hidden="true" />}
            批准并开始向量化
          </button>
          <div className="document-reject-control">
            <label htmlFor="rejection-reason">拒绝原因</label>
            <select
              disabled={!reviewable || isDecisionPending}
              id="rejection-reason"
              onChange={(event) => setRejectionReason(event.target.value as RejectionReason)}
              value={rejectionReason}
            >
              {REJECTION_REASONS.map((reason) => (
                <option key={reason.value} value={reason.value}>
                  {reason.label}
                </option>
              ))}
            </select>
            <button
              className="tertiary-button document-reject-button"
              disabled={!reviewable || isDecisionPending}
              onClick={() => onReject(rejectionReason)}
              type="button"
            >
              拒绝出域
            </button>
          </div>
        </div>
        {decisionError !== null && (
          <p className="field-error document-decision-error" role="alert">
            {getApiErrorMessage(decisionError)}
          </p>
        )}
      </div>
    </section>
  );
}
