import { useMemo, useState } from "react";
import {
  Activity,
  BarChart2,
  Clipboard,
  Filter,
  RefreshCw,
  Search,
  Users,
} from "lucide-react";
import {
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  Legend,
  Line,
  LineChart,
  Pie,
  PieChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import { AuditOperationResult } from "../../shared/api/enums";
import { useDictionaries } from "../dictionaries/dictionaryContext";
import {
  formatAuditDate,
  toUtcIso,
} from "./auditLabels";
import {
  useAuditBreakdowns,
  useAuditLogs,
  useAuditTrend,
  type RemoteState,
} from "./auditState";
import {
  AuditGranularity,
  type AuditActionStatisticsItem,
  type AuditLogQuery,
  type AuditTrendItem,
  type AuditUserStatisticsItem,
} from "./auditTypes";

const NAVY = "#1A5299";
const BLUE = "#3191eb";
const WHITE = "#fff";
const COLORS = ["#3191eb", "#1A5299", "#6eaee8", "#8bc4f0", "#4d88c7"];
const EMPTY = "—";

function ResourceState<T>({
  state,
  onRetry,
  label,
}: {
  state: RemoteState<T>;
  onRetry: () => void;
  label: string;
}) {
  if (state.loading && !state.data) {
    return (
      <div className="p-4 text-xs font-bold" style={{ color: NAVY }}>
        <RefreshCw size={12} className="inline animate-spin mr-2" />
        正在加载{label}…
      </div>
    );
  }
  if (state.error) {
    return (
      <div className="p-4 text-xs font-bold" style={{ color: NAVY }}>
        <div>
          {state.error.httpStatus === 403
            ? `当前账号无权读取${label}`
            : state.error.message}
        </div>
        {state.error.requestId && (
          <div className="opacity-60 mt-1">
            错误编号：{state.error.requestId}
          </div>
        )}
        <button
          onClick={onRetry}
          className="mt-2 px-3 py-1 text-white"
          style={{ background: BLUE }}
        >
          重试
        </button>
      </div>
    );
  }
  if (Array.isArray(state.data) && state.data.length === 0) {
    return (
      <div className="p-4 text-xs font-bold opacity-60" style={{ color: NAVY }}>
        当前条件下暂无{label}
      </div>
    );
  }
  return null;
}

function StatsPanel({
  title,
  icon,
  children,
}: {
  title: string;
  icon: React.ReactNode;
  children: React.ReactNode;
}) {
  return (
    <section
      className="bg-white p-3 min-h-[170px]"
      style={{ border: "1px solid rgba(40,118,193,.18)" }}
    >
      <div className="flex items-center gap-2 mb-2">
        {icon}
        <h3 className="text-sm font-black" style={{ color: NAVY }}>
          {title}
        </h3>
      </div>
      {children}
    </section>
  );
}

export function AuditDashboard() {
  const dictionaries = useDictionaries();
  const [keyword, setKeyword] = useState("");
  const [actionType, setActionType] = useState("");
  const [operationResult, setOperationResult] = useState("");
  const [targetType, setTargetType] = useState("");
  const [userId, setUserId] = useState("");
  const [organizationId, setOrganizationId] = useState("");
  const [targetId, setTargetId] = useState("");
  const [createdFromLocal, setCreatedFromLocal] = useState("");
  const [createdToLocal, setCreatedToLocal] = useState("");
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(20);
  const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
  const [granularity, setGranularity] =
    useState<AuditGranularity>(AuditGranularity.DAY);
  const [copyNotice, setCopyNotice] = useState("");

  const createdFrom = toUtcIso(createdFromLocal);
  const createdTo = toUtcIso(createdToLocal);
  const query: AuditLogQuery = {
    keyword: keyword.trim() || undefined,
    actionType: actionType
      ? (actionType as AuditLogQuery["actionType"])
      : undefined,
    operationResult: operationResult
      ? (operationResult as AuditLogQuery["operationResult"])
      : undefined,
    targetType: targetType
      ? (targetType as AuditLogQuery["targetType"])
      : undefined,
    userId: userId.trim() || undefined,
    organizationId: organizationId.trim() || undefined,
    targetId: targetId.trim() || undefined,
    createdFrom,
    createdTo,
    page,
    pageSize,
    sortDirection,
  };
  const logs = useAuditLogs(query);
  const trend = useAuditTrend({ createdFrom, createdTo, granularity });
  const breakdowns = useAuditBreakdowns(
    { createdFrom, createdTo },
    { createdFrom, createdTo, limit: 6 },
  );

  const pieData = useMemo(
    () =>
      (breakdowns.actions.data ?? []).map((item) => ({
        name: dictionaries.label("auditActions", item.actionType),
        value: item.count,
        actionType: item.actionType,
      })),
    [breakdowns.actions.data, dictionaries.data],
  );
  const activeUsers = useMemo(
    () =>
      (breakdowns.users.data ?? []).map((item) => ({
        ...item,
        label: item.realName ?? `用户 ${item.userId}`,
      })),
    [breakdowns.users.data],
  );

  const resetPage = () => setPage(1);
  const clearFilters = () => {
    setKeyword("");
    setActionType("");
    setOperationResult("");
    setTargetType("");
    setUserId("");
    setOrganizationId("");
    setTargetId("");
    setCreatedFromLocal("");
    setCreatedToLocal("");
    setSortDirection("desc");
    setPage(1);
  };

  const copyRequestId = async (requestId: string) => {
    try {
      await navigator.clipboard.writeText(requestId);
      setCopyNotice(`已复制 ${requestId}`);
    } catch {
      setCopyNotice("复制失败，请手动选择错误编号");
    }
  };

  return (
    <>
      <aside
        className="w-[286px] flex-shrink-0 m-3 overflow-y-auto bg-white"
        style={{ border: "1px solid rgba(40,118,193,.2)", color: NAVY }}
      >
        <div
          className="px-4 py-3 flex items-center gap-2 border-b"
          style={{ borderColor: "rgba(40,118,193,.14)" }}
        >
          <Filter size={14} style={{ color: BLUE }} />
          <span className="text-sm font-black">日志筛选</span>
        </div>
        <div className="p-3 space-y-2">
          <label className="flex h-9 items-center border px-2">
            <Search size={13} className="mr-2" style={{ color: BLUE }} />
            <input
              value={keyword}
              onChange={(event) => {
                setKeyword(event.target.value);
                resetPage();
              }}
              className="min-w-0 flex-1 outline-none text-sm font-bold"
              placeholder="名称、用户、requestId"
            />
          </label>
          <select
            value={actionType}
            onChange={(event) => {
              setActionType(event.target.value);
              resetPage();
            }}
            className="w-full h-9 border px-2 text-sm font-bold"
          >
            <option value="">全部动作</option>
            {dictionaries.options("auditActions").map((option) => (
              <option key={option.code} value={option.code}>
                {option.label}
              </option>
            ))}
          </select>
          <select
            value={operationResult}
            onChange={(event) => {
              setOperationResult(event.target.value);
              resetPage();
            }}
            className="w-full h-9 border px-2 text-sm font-bold"
          >
            <option value="">全部结果</option>
            {dictionaries.options("auditResults").map((option) => (
              <option key={option.code} value={option.code}>
                {option.label}
              </option>
            ))}
          </select>
          <select
            value={targetType}
            onChange={(event) => {
              setTargetType(event.target.value);
              resetPage();
            }}
            className="w-full h-9 border px-2 text-sm font-bold"
          >
            <option value="">全部对象类型</option>
            {dictionaries.options("auditTargets").map((option) => (
              <option key={option.code} value={option.code}>
                {option.label}
              </option>
            ))}
          </select>
          {[
            ["用户ID", userId, setUserId],
            ["组织ID", organizationId, setOrganizationId],
            ["目标ID", targetId, setTargetId],
          ].map(([label, value, setter]) => (
            <input
              key={label as string}
              value={value as string}
              inputMode="numeric"
              onChange={(event) => {
                (setter as (value: string) => void)(
                  event.target.value.replace(/\D/g, ""),
                );
                resetPage();
              }}
              placeholder={label as string}
              className="w-full h-9 border px-2 text-sm font-bold"
            />
          ))}
          <label className="block text-xs font-black">
            起始时间（含）
            <input
              type="datetime-local"
              value={createdFromLocal}
              onChange={(event) => {
                setCreatedFromLocal(event.target.value);
                resetPage();
              }}
              className="mt-1 w-full h-9 border px-2 text-xs font-bold"
            />
          </label>
          <label className="block text-xs font-black">
            结束时间（不含）
            <input
              type="datetime-local"
              value={createdToLocal}
              onChange={(event) => {
                setCreatedToLocal(event.target.value);
                resetPage();
              }}
              className="mt-1 w-full h-9 border px-2 text-xs font-bold"
            />
          </label>
          <div className="flex gap-2">
            <button
              onClick={clearFilters}
              className="flex-1 h-9 border text-xs font-black"
              style={{ borderColor: BLUE }}
            >
              清空
            </button>
            <button
              onClick={() => {
                logs.refresh();
                trend.refresh();
                breakdowns.refresh();
              }}
              className="flex-1 h-9 text-white text-xs font-black"
              style={{ background: BLUE }}
            >
              重新加载
            </button>
          </div>
          <div className="text-[11px] leading-5 opacity-60">
            时间按本地输入并转换为 UTC Z；查询区间为 [起始, 结束)。
          </div>
        </div>
      </aside>

      <main className="flex-1 flex gap-3 m-3 ml-0 min-w-0 min-h-0">
        <section
          className="flex-1 min-w-0 flex flex-col bg-white"
          style={{ border: "1px solid rgba(40,118,193,.18)" }}
        >
          <div
            className="px-4 py-2.5 flex items-center gap-3 border-b"
            style={{ color: NAVY, borderColor: "rgba(40,118,193,.14)" }}
          >
          <span className="font-black">操作日志</span>
            <span className="text-xs font-black" style={{ color: BLUE }}>
              {logs.data?.total ?? 0} 条
            </span>
            <select
              value={sortDirection}
              onChange={(event) => {
                setSortDirection(event.target.value as "asc" | "desc");
                setPage(1);
              }}
              className="ml-auto h-8 border px-2 text-xs font-bold"
            >
              <option value="desc">时间降序</option>
              <option value="asc">时间升序</option>
            </select>
            <select
              value={pageSize}
              onChange={(event) => {
                setPageSize(Number(event.target.value));
                setPage(1);
              }}
              className="h-8 border px-2 text-xs font-bold"
            >
              {[20, 50, 100].map((size) => (
                <option key={size} value={size}>
                  每页 {size}
                </option>
              ))}
            </select>
          </div>
          {logs.loading && !logs.data && (
            <div className="p-8 text-sm font-bold" style={{ color: NAVY }}>
              <RefreshCw size={14} className="inline animate-spin mr-2" />
              正在读取审计日志…
            </div>
          )}
          {logs.error && (
            <div className="p-6 text-sm font-bold" style={{ color: NAVY }}>
              <div>
                {logs.error.httpStatus === 403
                  ? "当前账号无权读取审计日志"
                  : logs.error.message}
              </div>
              {logs.error.requestId && (
                <div className="text-xs opacity-60 mt-1">
                  错误编号：{logs.error.requestId}
                </div>
              )}
              <button
                onClick={logs.refresh}
                className="mt-3 px-3 py-1.5 text-xs text-white"
                style={{ background: BLUE }}
              >
                重试
              </button>
            </div>
          )}
          {logs.data && logs.data.items.length === 0 && (
            <div className="p-8 text-sm font-bold opacity-60" style={{ color: NAVY }}>
              当前筛选条件下暂无日志
            </div>
          )}
          {logs.data && logs.data.items.length > 0 && (
            <div className="flex-1 overflow-auto">
              <table className="min-w-[1500px] w-full border-collapse">
                <thead className="sticky top-0 z-10 text-white" style={{ background: NAVY }}>
                  <tr>
                    {[
                      "时间",
                      "用户名 / 姓名",
                      "组织",
                      "动作",
                      "对象类型 / 名称",
                      "结果 / 失败原因",
                      "客户端IP",
                      "requestId",
                    ].map((heading) => (
                      <th key={heading} className="px-3 py-2 text-left text-xs font-black">
                        {heading}
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {logs.data.items.map((log, index) => (
                    <tr
                      key={log.id}
                      className="border-b"
                      style={{
                        color: NAVY,
                        borderColor: "rgba(40,118,193,.1)",
                        background: index % 2 ? "rgba(40,118,193,.04)" : WHITE,
                      }}
                    >
                      <td className="px-3 py-2 text-xs font-bold whitespace-nowrap">
                        {formatAuditDate(log.createdAt)}
                      </td>
                      <td className="px-3 py-2 text-xs font-bold">
                        <div>{log.username ?? EMPTY}</div>
                        <div className="opacity-60">{log.realName ?? EMPTY}</div>
                      </td>
                      <td className="px-3 py-2 text-xs font-bold">
                        {log.organizationName ?? EMPTY}
                      </td>
                      <td className="px-3 py-2 text-xs font-black">
                        {dictionaries.label("auditActions", log.actionType)}
                      </td>
                      <td className="px-3 py-2 text-xs font-bold">
                        <div>
                          {log.targetType
                            ? dictionaries.label("auditTargets", log.targetType)
                            : EMPTY}
                        </div>
                        <div className="opacity-60">
                          {log.targetName ?? EMPTY}
                          {log.targetId ? `（${log.targetId}）` : ""}
                        </div>
                      </td>
                      <td className="px-3 py-2 text-xs font-bold max-w-[240px]">
                        <span
                          className="inline-block px-2 py-0.5 text-white"
                          style={{
                            background:
                              log.operationResult === AuditOperationResult.SUCCESS
                                ? BLUE
                                : NAVY,
                          }}
                        >
                          {dictionaries.label("auditResults", log.operationResult)}
                        </span>
                        <div className="mt-1 opacity-60 break-words">
                          {log.failureReason ?? EMPTY}
                        </div>
                      </td>
                      <td className="px-3 py-2 text-xs font-bold">
                        {log.clientIp ?? EMPTY}
                      </td>
                      <td className="px-3 py-2 text-xs font-mono max-w-[250px] break-all">
                        {log.requestId ?? EMPTY}
                        {log.requestId && (
                          <button
                            title="复制requestId"
                            onClick={() => void copyRequestId(log.requestId!)}
                            className="ml-2"
                            style={{ color: BLUE }}
                          >
                            <Clipboard size={12} />
                          </button>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
          <div
            className="p-2 border-t flex items-center justify-center gap-3 text-xs font-bold"
            style={{ color: NAVY, borderColor: "rgba(40,118,193,.14)" }}
          >
            <button
              disabled={page <= 1}
              onClick={() => setPage((value) => Math.max(1, value - 1))}
              className="px-3 py-1 border disabled:opacity-30"
            >
              上一页
            </button>
            <span>
              第 {logs.data?.page ?? page} / {logs.data?.totalPages ?? 0} 页
            </span>
            <button
              disabled={!logs.data || page >= logs.data.totalPages}
              onClick={() => setPage((value) => value + 1)}
              className="px-3 py-1 border disabled:opacity-30"
            >
              下一页
            </button>
          </div>
        </section>

        <aside className="w-[330px] flex-shrink-0 overflow-y-auto space-y-3">
          <StatsPanel
            title="操作趋势"
            icon={<BarChart2 size={14} style={{ color: BLUE }} />}
          >
            <div className="flex gap-1 mb-2">
              {Object.values(AuditGranularity).map((value) => (
                <button
                  key={value}
                  onClick={() => setGranularity(value)}
                  className="flex-1 py-1 text-xs font-black"
                  style={{
                    color: granularity === value ? WHITE : NAVY,
                    background: granularity === value ? NAVY : "#EBF4FD",
                  }}
                >
                  {value}
                </button>
              ))}
            </div>
            <ResourceState<AuditTrendItem[]>
              state={trend}
              onRetry={trend.refresh}
              label="趋势数据"
            />
            {trend.data && trend.data.length > 0 && (
              <>
                <ResponsiveContainer width="100%" height={115}>
                  <LineChart data={trend.data}>
                    <CartesianGrid strokeDasharray="3 3" stroke="rgba(40,118,193,.12)" />
                    <XAxis dataKey="period" tick={{ fontSize: 9, fill: NAVY }} />
                    <YAxis tick={{ fontSize: 9, fill: NAVY }} />
                    <Tooltip />
                    <Line
                      dataKey="operationCount"
                      name="操作次数"
                      stroke={BLUE}
                      strokeWidth={2}
                    />
                  </LineChart>
                </ResponsiveContainer>
                <div className="text-[10px] font-bold opacity-60" style={{ color: NAVY }}>
                  {trend.data.map((item) => `${item.period}: ${item.operationCount}`).join(" · ")}
                </div>
              </>
            )}
          </StatsPanel>

          <StatsPanel
            title="动作分布"
            icon={<Activity size={14} style={{ color: BLUE }} />}
          >
            <ResourceState<AuditActionStatisticsItem[]>
              state={breakdowns.actions}
              onRetry={breakdowns.refresh}
              label="动作分布"
            />
            {pieData.length > 0 && (
              <>
                <ResponsiveContainer width="100%" height={120}>
                  <PieChart>
                    <Pie
                      data={pieData}
                      dataKey="value"
                      nameKey="name"
                      innerRadius={25}
                      outerRadius={45}
                    >
                      {pieData.map((item, index) => (
                        <Cell
                          key={item.actionType}
                          fill={COLORS[index % COLORS.length]}
                        />
                      ))}
                    </Pie>
                    <Tooltip />
                    <Legend iconSize={7} wrapperStyle={{ fontSize: 9 }} />
                  </PieChart>
                </ResponsiveContainer>
                <div className="text-[10px] font-bold" style={{ color: NAVY }}>
                  {pieData.map((item) => `${item.name} ${item.value}`).join(" · ")}
                </div>
              </>
            )}
          </StatsPanel>

          <StatsPanel
            title="活跃用户 TOP 6"
            icon={<Users size={14} style={{ color: BLUE }} />}
          >
            <ResourceState<AuditUserStatisticsItem[]>
              state={breakdowns.users}
              onRetry={breakdowns.refresh}
              label="活跃用户"
            />
            {activeUsers.length > 0 && (
              <>
                <ResponsiveContainer width="100%" height={115}>
                  <BarChart data={activeUsers} layout="vertical">
                    <CartesianGrid strokeDasharray="3 3" horizontal={false} />
                    <XAxis type="number" tick={{ fontSize: 9 }} />
                    <YAxis
                      type="category"
                      dataKey="label"
                      width={62}
                      tick={{ fontSize: 9, fill: NAVY }}
                    />
                    <Tooltip />
                    <Bar
                      dataKey="operationCount"
                      name="操作次数"
                      fill={BLUE}
                    />
                  </BarChart>
                </ResponsiveContainer>
                <div className="space-y-1 text-[10px] font-bold" style={{ color: NAVY }}>
                  {activeUsers.map((item) => (
                    <div key={item.userId}>
                      {item.label} · {item.organizationName ?? EMPTY} ·{" "}
                      {item.operationCount} 次
                    </div>
                  ))}
                </div>
              </>
            )}
          </StatsPanel>
        </aside>
      </main>
      {copyNotice && (
        <button
          onClick={() => setCopyNotice("")}
          className="fixed right-6 bottom-6 px-4 py-3 text-xs font-bold text-white shadow-xl"
          style={{ background: NAVY }}
        >
          {copyNotice}
        </button>
      )}
    </>
  );
}
