"use client";

import type { AuditLogEntry, AuditSource } from "@domainops/shared-types";
import { App, Button, Input, Segmented, Select, Space, Table, Tag, Typography } from "antd";
import { CopyOutlined, DownloadOutlined } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table";
import { useCallback, useEffect, useState } from "react";
import { exportAuditLog, listAuditLog } from "@/lib/api/audit";
import { useAuth } from "@/lib/auth/AuthProvider";
import { ApiError } from "@/lib/api/client";
import { auditDetails } from "@/lib/utils/auditDetails";
import { ActorLabel } from "@/components/features/ActorLabel";
import { PageGuide } from "@/components/features/PageGuide";
import { ACTIVITY_LOG_GUIDES } from "@/lib/guides/activity-log";
import { serverPaginationConfig, useServerPagination } from "@/lib/hooks/useServerPagination";

const SOURCE_COLORS: Record<AuditSource, string> = {
  ui: "blue",
  api: "green",
  mcp: "purple",
  system: "default",
};

export default function AuditLogPage() {
  const { message } = App.useApp();
  const { user } = useAuth();
  const canExport = !!user?.is_admin;
  const [selectedIds, setSelectedIds] = useState<number[]>([]);
  const [exportScope, setExportScope] = useState<"selected" | "page" | "filtered">("page");
  const [isExporting, setIsExporting] = useState(false);
  const [entries, setEntries] = useState<AuditLogEntry[]>([]);
  const [total, setTotal] = useState(0);
  const { page, pageSize, resetToFirstPage, onChange } = useServerPagination();
  const [source, setSource] = useState<AuditSource | undefined>();
  const [action, setAction] = useState("");
  const [isLoading, setIsLoading] = useState(true);

  const load = useCallback(async () => {
    setIsLoading(true);
    try {
      const result = await listAuditLog({ source, action, page, per_page: pageSize });
      setEntries(result.data);
      setTotal(result.meta.total);
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load the audit log.");
    } finally {
      setIsLoading(false);
    }
  }, [source, action, page, pageSize, message]);

  useEffect(() => {
    // Audit log lives on the Laravel API - a client fetch on mount/filter
    // change, not a state-sync bug.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void load();
  }, [load]);

  const effectiveScope = exportScope === "selected" && selectedIds.length === 0 ? "page" : exportScope;

  async function runExport(mode: "download" | "copy") {
    setIsExporting(true);
    try {
      const data = await exportAuditLog(
        effectiveScope === "selected"
          ? { ids: selectedIds }
          : effectiveScope === "page"
            ? { ids: entries.map((entry) => entry.id) }
            : { source, action: action || undefined },
      );
      const text = JSON.stringify(data, null, 2);

      if (mode === "copy") {
        await navigator.clipboard.writeText(text);
        message.success(`Copied ${data.count} entr${data.count === 1 ? "y" : "ies"} - paste them to the dev team.`);
      } else {
        const stamp = new Date().toISOString().replace(/[-:T]/g, "").slice(0, 12);
        const link = document.createElement("a");
        link.href = URL.createObjectURL(new Blob([text], { type: "application/json" }));
        link.download = `activity-log-${stamp}.json`;
        document.body.appendChild(link);
        link.click();
        link.remove();
        URL.revokeObjectURL(link.href);
        message.success(`Exported ${data.count} entr${data.count === 1 ? "y" : "ies"}.`);
      }
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't export the activity log.");
    } finally {
      setIsExporting(false);
    }
  }

  const columns: ColumnsType<AuditLogEntry> = [
    {
      title: "When",
      dataIndex: "created_at",
      render: (v: string) => new Date(v).toLocaleString(),
    },
    {
      title: "Source",
      dataIndex: "source",
      render: (v: AuditSource) => <Tag color={SOURCE_COLORS[v]}>{v}</Tag>,
    },
    { title: "Action", dataIndex: "action", render: (v: string) => <span className="font-mono">{v}</span> },
    {
      title: "Target",
      render: (_, entry) =>
        entry.target_type ? `${entry.target_type.split("\\").pop()} #${entry.target_id}` : "—",
    },
    { title: "Details", render: (_, entry) => auditDetails(entry) || "—" },
    { title: "Actor", render: (_, entry) => <ActorLabel actor={entry.actor} /> },
    {
      title: "Result",
      dataIndex: "result",
      render: (v: string) => <Tag color={v === "success" ? "green" : "red"}>{v}</Tag>,
    },
  ];

  return (
    <div className="flex flex-col gap-4 page page-logs">
      <div className="flex items-center gap-2">
        <Typography.Title level={4} style={{ margin: 0 }}>
          Activity log
        </Typography.Title>
        <PageGuide guides={ACTIVITY_LOG_GUIDES} label="Activity log guide" />
      </div>

      <Space wrap>
        <Select
          allowClear
          placeholder="Source"
          style={{ width: 140 }}
          options={[
            { value: "ui", label: "UI" },
            { value: "api", label: "API" },
            { value: "mcp", label: "MCP" },
            { value: "system", label: "System" },
          ]}
          onChange={(value) => {
            resetToFirstPage();
            setSource(value);
          }}
          className="dms_logs_source_select"
        />
        <Input.Search
          placeholder="Search action…"
          allowClear
          style={{ width: 220 }}
          onSearch={(value) => {
            resetToFirstPage();
            setAction(value);
          }}
          className="dms_logs_action_search_input"
        />
      </Space>

      {canExport && (
        <div className="flex items-center gap-3 flex-wrap dms_logs_export_bar">
          <Typography.Text strong>Export for the dev team</Typography.Text>
          <Segmented
            value={exportScope}
            onChange={(value) => setExportScope(value as "selected" | "page" | "filtered")}
            options={[
              { value: "selected", label: `Selected (${selectedIds.length})` },
              { value: "page", label: "This page" },
              { value: "filtered", label: "All matching the filters (latest 500)" },
            ]}
            className="dms_logs_export_scope"
          />
          <Button icon={<DownloadOutlined />} loading={isExporting} onClick={() => void runExport("download")} className="dms_logs_export_download_btn">
            Download file
          </Button>
          <Button icon={<CopyOutlined />} loading={isExporting} onClick={() => void runExport("copy")} className="dms_logs_export_copy_btn">
            Copy
          </Button>
          <Typography.Text type="secondary">Passwords, keys and tokens are replaced with [redacted].</Typography.Text>
        </div>
      )}

      <Table<AuditLogEntry>
        rowKey="id"
        columns={columns}
        rowSelection={canExport ? { selectedRowKeys: selectedIds, onChange: (keys) => { setSelectedIds(keys as number[]); if (keys.length > 0) setExportScope("selected"); } } : undefined}
        dataSource={entries}
        loading={isLoading}
        className="dms_logs_table"
        pagination={serverPaginationConfig(total, page, pageSize, onChange, "entries")}
      />
    </div>
  );
}
