import { useInfiniteQuery } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  ChevronDown,
  ChevronUp,
  Copy,
  Download,
  RefreshCw,
  Search,
} from "lucide-react";
import * as React from "react";
import { ForbiddenMessage } from "../../components/common/ForbiddenMessage";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../components/ui/card";
import { Input } from "../../components/ui/input";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../components/ui/table";
import type { DevAuditLog } from "../../lib/devApi";
import { fetchDevAuditLogs } from "../../lib/devApi";
import { t } from "../../lib/i18n";

type AuditDetails = {
  request_id?: string;
  method?: string;
  path?: string;
  tenant_id?: string;
  action?: string;
  target_id?: string;
  before?: unknown;
  after?: unknown;
  error?: string;
};

function parseDetails(details?: string): AuditDetails {
  if (!details) {
    return {};
  }
  try {
    const parsed = JSON.parse(details);
    if (parsed && typeof parsed === "object") {
      return parsed as AuditDetails;
    }
  } catch {}
  return {};
}

function formatValue(value: unknown): string {
  if (value === null || value === undefined || value === "") {
    return "-";
  }
  if (typeof value === "string") {
    return value;
  }
  try {
    return JSON.stringify(value);
  } catch {
    return String(value);
  }
}

function formatDateTime(value: string): string {
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return value;
  }
  return parsed.toLocaleString("ko-KR");
}

function toCsv(logs: DevAuditLog[]) {
  const header = [
    "timestamp",
    "user_id",
    "status",
    "event_type",
    "action",
    "target_id",
    "tenant_id",
    "request_id",
  ];
  const rows = logs.map((logItem) => {
    const details = parseDetails(logItem.details);
    return [
      logItem.timestamp,
      logItem.user_id || "",
      logItem.status,
      logItem.event_type,
      details.action || "",
      details.target_id || "",
      details.tenant_id || "",
      details.request_id || "",
    ];
  });
  return [header, ...rows]
    .map((line) =>
      line.map((cell) => `"${String(cell).replaceAll('"', '""')}"`).join(","),
    )
    .join("\n");
}

function downloadCsv(content: string, filename: string) {
  const blob = new Blob([content], { type: "text/csv;charset=utf-8;" });
  const url = URL.createObjectURL(blob);
  const anchor = document.createElement("a");
  anchor.href = url;
  anchor.download = filename;
  document.body.appendChild(anchor);
  anchor.click();
  document.body.removeChild(anchor);
  URL.revokeObjectURL(url);
}

function AuditLogsPage() {
  const [searchClientId, setSearchClientId] = React.useState("");
  const [searchAction, setSearchAction] = React.useState("");
  const [statusFilter, setStatusFilter] = React.useState("all");
  const [expandedRows, setExpandedRows] = React.useState<
    Record<string, boolean>
  >({});

  const query = useInfiniteQuery({
    queryKey: ["dev-audit-logs", searchClientId, searchAction, statusFilter],
    queryFn: ({ pageParam }) =>
      fetchDevAuditLogs(50, pageParam, {
        client_id: searchClientId.trim() || undefined,
        action: searchAction.trim() || undefined,
        status: statusFilter !== "all" ? statusFilter : undefined,
      }),
    initialPageParam: undefined as string | undefined,
    getNextPageParam: (lastPage) => lastPage.next_cursor || undefined,
  });

  const logs =
    query.data?.pages.flatMap((page) =>
      page.items.filter((item): item is DevAuditLog => Boolean(item)),
    ) ?? [];

  const handleCopy = (value: string) => {
    if (!value) {
      return;
    }
    navigator.clipboard.writeText(value);
  };

  const handleExportCsv = () => {
    const csv = toCsv(logs);
    const stamp = new Date().toISOString().replaceAll(":", "-");
    downloadCsv(csv, `dev-audit-logs-${stamp}.csv`);
  };

  if (query.isLoading) {
    return (
      <div className="p-8 text-center">
        {t("msg.dev.audit.loading", "Loading audit logs...")}
      </div>
    );
  }

  if (query.error) {
    const axiosError = query.error as AxiosError<{ error?: string }>;
    if (axiosError.response?.status === 403) {
      return <ForbiddenMessage resourceToken="audit" />;
    }

    const errMsg =
      axiosError.response?.data?.error ?? (query.error as Error).message;
    return (
      <div className="p-8 text-center text-red-500">
        {t("msg.dev.audit.load_error", "Error loading logs: {{error}}", {
          error: errMsg,
        })}
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <Card className="glass-panel">
        <CardHeader className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
          <div>
            <p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
              {t("ui.dev.audit.registry.title", "Audit registry")}
            </p>
            <CardTitle className="text-3xl font-black tracking-tight">
              {t("ui.dev.audit.title", "Audit Logs")}
            </CardTitle>
            <CardDescription>
              {t(
                "msg.dev.audit.subtitle",
                "Shows DevFront activity history within current tenant/app scope.",
              )}
            </CardDescription>
          </div>
          <div className="flex items-center gap-2">
            <Badge variant="muted">
              {t("msg.dev.audit.loaded_count", "Loaded {{count}} rows", {
                count: logs.length,
              })}
            </Badge>
            <Button
              variant="outline"
              onClick={() => query.refetch()}
              disabled={query.isFetching}
            >
              <RefreshCw size={16} />
              {t("ui.common.refresh", "새로고침")}
            </Button>
            <Button
              className="shadow-sm shadow-primary/30"
              onClick={handleExportCsv}
            >
              <Download size={16} />
              {t("ui.dev.clients.consents.export_csv", "Export CSV")}
            </Button>
          </div>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid gap-2 md:grid-cols-[1fr,1fr,180px]">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <Input
                className="pl-10"
                value={searchClientId}
                onChange={(e) => setSearchClientId(e.target.value)}
                placeholder={t(
                  "ui.dev.audit.filter.client_id",
                  "Filter by Client ID",
                )}
              />
            </div>
            <Input
              value={searchAction}
              onChange={(e) => setSearchAction(e.target.value.toUpperCase())}
              placeholder={t(
                "ui.dev.audit.filter.action",
                "Filter by Action (e.g. ROTATE_SECRET)",
              )}
            />
            <select
              className="h-10 rounded-md border border-input bg-background px-3 text-sm"
              value={statusFilter}
              onChange={(e) => setStatusFilter(e.target.value)}
            >
              <option value="all">
                {t("ui.dev.audit.filter.status_all", "All Status")}
              </option>
              <option value="success">
                {t("ui.common.status.success", "Success")}
              </option>
              <option value="failure">
                {t("ui.common.status.failure", "Failure")}
              </option>
            </select>
          </div>

          <Table className="table-fixed">
            <TableHeader>
              <TableRow>
                <TableHead className="w-[190px]">
                  {t("ui.dev.audit.table.time", "Time")}
                </TableHead>
                <TableHead className="w-[180px]">
                  {t("ui.dev.audit.table.actor", "Actor")}
                </TableHead>
                <TableHead className="w-[180px]">
                  {t("ui.dev.audit.table.action", "Action")}
                </TableHead>
                <TableHead className="w-[260px]">
                  {t("ui.dev.audit.table.target", "Target")}
                </TableHead>
                <TableHead className="w-[120px]">
                  {t("ui.dev.audit.table.status", "Status")}
                </TableHead>
                <TableHead className="w-[80px]" />
              </TableRow>
            </TableHeader>
            <TableBody>
              {logs.length === 0 && (
                <TableRow>
                  <TableCell
                    colSpan={6}
                    className="text-center text-muted-foreground"
                  >
                    {t("msg.dev.audit.empty", "No audit logs found.")}
                  </TableCell>
                </TableRow>
              )}
              {logs.map((row, index) => {
                const details = parseDetails(row.details);
                const actionLabel = details.action || row.event_type;
                const targetValue = details.target_id || "-";
                const rowKey = `${row.event_id}-${row.timestamp}-${index}`;
                const expanded = Boolean(expandedRows[rowKey]);
                return (
                  <React.Fragment key={rowKey}>
                    <TableRow>
                      <TableCell className="text-xs text-muted-foreground">
                        {formatDateTime(row.timestamp)}
                      </TableCell>
                      <TableCell className="font-mono text-xs">
                        <div className="flex items-center gap-2">
                          <span>{row.user_id || "-"}</span>
                          {row.user_id ? (
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-7 w-7 text-muted-foreground"
                              onClick={() => handleCopy(row.user_id)}
                            >
                              <Copy className="h-3 w-3" />
                            </Button>
                          ) : null}
                        </div>
                      </TableCell>
                      <TableCell className="text-xs">{actionLabel}</TableCell>
                      <TableCell className="font-mono text-xs">
                        <div className="flex items-center gap-2">
                          <span className="break-all">{targetValue}</span>
                          {targetValue !== "-" ? (
                            <Button
                              variant="ghost"
                              size="icon"
                              className="h-7 w-7 text-muted-foreground"
                              onClick={() => handleCopy(targetValue)}
                            >
                              <Copy className="h-3 w-3" />
                            </Button>
                          ) : null}
                        </div>
                      </TableCell>
                      <TableCell>
                        <Badge
                          variant={
                            row.status === "success" ? "success" : "warning"
                          }
                        >
                          {row.status}
                        </Badge>
                      </TableCell>
                      <TableCell className="text-right">
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() =>
                            setExpandedRows((prev) => ({
                              ...prev,
                              [rowKey]: !expanded,
                            }))
                          }
                        >
                          {expanded ? (
                            <ChevronUp className="h-4 w-4" />
                          ) : (
                            <ChevronDown className="h-4 w-4" />
                          )}
                        </Button>
                      </TableCell>
                    </TableRow>
                    {expanded ? (
                      <TableRow className="bg-card/20">
                        <TableCell
                          colSpan={6}
                          className="text-xs text-muted-foreground"
                        >
                          <div className="grid gap-3 md:grid-cols-2">
                            <div className="space-y-1">
                              <div>
                                Request ID: {formatValue(details.request_id)}
                              </div>
                              <div>Method: {formatValue(details.method)}</div>
                              <div>Path: {formatValue(details.path)}</div>
                              <div>
                                Tenant: {formatValue(details.tenant_id)}
                              </div>
                            </div>
                            <div className="space-y-1 break-all">
                              <div>Before: {formatValue(details.before)}</div>
                              <div>After: {formatValue(details.after)}</div>
                              <div>Error: {formatValue(details.error)}</div>
                            </div>
                          </div>
                        </TableCell>
                      </TableRow>
                    ) : null}
                  </React.Fragment>
                );
              })}
            </TableBody>
          </Table>

          {query.hasNextPage ? (
            <div className="flex justify-center">
              <Button
                variant="outline"
                onClick={() => query.fetchNextPage()}
                disabled={query.isFetchingNextPage}
              >
                {query.isFetchingNextPage
                  ? t("msg.common.loading", "Loading...")
                  : t("ui.dev.audit.load_more", "Load more")}
              </Button>
            </div>
          ) : null}
        </CardContent>
      </Card>
    </div>
  );
}

export default AuditLogsPage;
