import type {
  AdminOperationAuditItem,
  AdminOperationAuditResponse,
  PrivateContentAccessAuditItem,
  PrivateContentAccessAuditResponse,
} from "@dada/shared-contracts";
import { useCallback, useEffect, useState } from "react";

import "./admin-audit.css";

type AuditTab = "operations" | "private-content";

interface AuditPageState<Item> {
  failed: boolean;
  generatedAt: string | null;
  items: Item[];
  loading: boolean;
  nextCursor: string | null;
}

const emptyState = <Item,>(): AuditPageState<Item> => ({
  failed: false,
  generatedAt: null,
  items: [],
  loading: false,
  nextCursor: null,
});

function formatTime(value: string) {
  return new Intl.DateTimeFormat("zh-CN", {
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    month: "2-digit",
    second: "2-digit",
  }).format(new Date(value));
}

function operationSummary(item: AdminOperationAuditItem) {
  if (item.after_summary) return item.after_summary;
  if (item.before_summary) return item.before_summary;
  return "无变更摘要";
}

export function AdminAuditPage() {
  const [tab, setTab] = useState<AuditTab>("operations");
  const [operations, setOperations] = useState<AuditPageState<AdminOperationAuditItem>>(emptyState);
  const [privateAccess, setPrivateAccess] = useState<AuditPageState<PrivateContentAccessAuditItem>>(emptyState);

  const loadOperations = useCallback(async (cursor?: string, append = false) => {
    setOperations((current) => ({ ...current, failed: false, loading: true }));
    try {
      const query = new URLSearchParams({ limit: "50" });
      if (cursor) query.set("cursor", cursor);
      const response = await fetch(`/api/v1/admin/audit/operations?${query}`, { credentials: "same-origin" });
      if (response.status === 401) {
        window.dispatchEvent(new Event("dada:session-invalid"));
        return;
      }
      if (!response.ok) throw new Error("admin_operation_audit_unavailable");
      const body = await response.json() as AdminOperationAuditResponse;
      setOperations((current) => ({
        failed: false,
        generatedAt: body.generated_at,
        items: append ? [...current.items, ...body.items] : body.items,
        loading: false,
        nextCursor: body.next_cursor,
      }));
    } catch {
      setOperations((current) => ({ ...current, failed: true, loading: false }));
    }
  }, []);

  const loadPrivateAccess = useCallback(async (cursor?: string, append = false) => {
    setPrivateAccess((current) => ({ ...current, failed: false, loading: true }));
    try {
      const query = new URLSearchParams({ limit: "50" });
      if (cursor) query.set("cursor", cursor);
      const response = await fetch(`/api/v1/admin/audit/private-content?${query}`, { credentials: "same-origin" });
      if (response.status === 401) {
        window.dispatchEvent(new Event("dada:session-invalid"));
        return;
      }
      if (!response.ok) throw new Error("private_content_audit_unavailable");
      const body = await response.json() as PrivateContentAccessAuditResponse;
      setPrivateAccess((current) => ({
        failed: false,
        generatedAt: body.generated_at,
        items: append ? [...current.items, ...body.items] : body.items,
        loading: false,
        nextCursor: body.next_cursor,
      }));
    } catch {
      setPrivateAccess((current) => ({ ...current, failed: true, loading: false }));
    }
  }, []);

  useEffect(() => { void loadOperations(); }, [loadOperations]);

  function selectTab(next: AuditTab) {
    setTab(next);
    if (next === "private-content" && !privateAccess.generatedAt && !privateAccess.loading) void loadPrivateAccess();
  }

  const state = tab === "operations" ? operations : privateAccess;
  const reload = tab === "operations" ? loadOperations : loadPrivateAccess;

  return (
    <main className="admin-audit-page" id="admin-main">
      <header className="admin-audit-heading">
        <div><p>IMMUTABLE / 180 DAYS</p><h2>审计</h2></div>
        {state.generatedAt ? <time dateTime={state.generatedAt}>读取于 {formatTime(state.generatedAt)}</time> : null}
      </header>

      <div aria-label="审计类型" className="admin-audit-tabs" role="tablist">
        <button aria-controls="operation-audit-panel" aria-selected={tab === "operations"} id="operation-audit-tab" onClick={() => selectTab("operations")} role="tab" type="button">后台操作审计</button>
        <button aria-controls="private-audit-panel" aria-selected={tab === "private-content"} id="private-audit-tab" onClick={() => selectTab("private-content")} role="tab" type="button">私有内容访问审计</button>
      </div>

      {state.failed ? (
        <div className="admin-audit-failure" role="alert">
          <span>审计记录暂时无法读取{state.generatedAt ? "，已保留上次结果" : ""}。</span>
          <button disabled={state.loading} onClick={() => void reload()} type="button">重试</button>
        </div>
      ) : null}

      {tab === "operations" ? (
        <section aria-labelledby="operation-audit-tab" id="operation-audit-panel" role="tabpanel">
          {operations.loading && operations.items.length === 0 ? <p aria-live="polite" className="admin-audit-status">正在读取后台操作审计</p> : null}
          {!operations.loading && !operations.failed && operations.items.length === 0 ? <p className="admin-audit-status">当前没有后台操作审计记录。</p> : null}
          {operations.items.length > 0 ? (
            <div className="admin-audit-table-scroll">
              <table>
                <thead><tr><th>时间</th><th>管理员</th><th>操作类型</th><th>对象安全摘要</th><th>结果</th><th>Operation ID</th></tr></thead>
                <tbody>{operations.items.map((item) => (
                  <tr key={item.log_id}>
                    <td><time dateTime={item.occurred_at}>{formatTime(item.occurred_at)}</time></td>
                    <td><code>{item.actor_ref}</code><small>{item.actor_type}</small></td>
                    <td><code>{item.operation_type}</code></td>
                    <td><code>{item.target_type}:{item.target_ref}</code><small>{operationSummary(item)}</small></td>
                    <td><strong className={`is-${item.result}`}>{item.result}</strong></td>
                    <td><code>{item.log_id}</code></td>
                  </tr>
                ))}</tbody>
              </table>
            </div>
          ) : null}
        </section>
      ) : (
        <section aria-labelledby="private-audit-tab" id="private-audit-panel" role="tabpanel">
          {privateAccess.loading && privateAccess.items.length === 0 ? <p aria-live="polite" className="admin-audit-status">正在读取私有内容访问审计</p> : null}
          {!privateAccess.loading && !privateAccess.failed && privateAccess.items.length === 0 ? <p className="admin-audit-status">当前没有私有内容访问审计记录。</p> : null}
          {privateAccess.items.length > 0 ? (
            <div className="admin-audit-table-scroll">
              <table>
                <thead><tr><th>时间</th><th>管理员</th><th>安全目标标识</th><th>内容类型</th><th>到期时间</th><th>Access ID</th></tr></thead>
                <tbody>{privateAccess.items.map((item) => (
                  <tr key={item.log_id}>
                    <td><time dateTime={item.occurred_at}>{formatTime(item.occurred_at)}</time></td>
                    <td><code>{item.actor_ref}</code></td>
                    <td><code>{item.target_ref}</code></td>
                    <td>{item.content_type}</td>
                    <td><time dateTime={item.expires_at}>{formatTime(item.expires_at)}</time></td>
                    <td><code>{item.log_id}</code></td>
                  </tr>
                ))}</tbody>
              </table>
            </div>
          ) : null}
        </section>
      )}

      {state.nextCursor ? (
        <div className="admin-audit-pagination">
          <button disabled={state.loading} onClick={() => void reload(state.nextCursor!, true)} type="button">{state.loading ? "正在读取" : "下一页"}</button>
        </div>
      ) : null}
      <p className="admin-audit-retention">记录保留 180 天。此页面不提供编辑、删除或清空能力。</p>
    </main>
  );
}
