import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import { Download, NotebookTabs, RefreshCw, Search } from "lucide-react";
import * as React from "react";
import { useAuth } from "react-oidc-context";
import { useNavigate } from "react-router-dom";
import { parseAuditDetails } from "../../../../common/core/audit";
import { AuditLogTable } from "../../../../common/core/components/audit";
import { PageHeader } from "../../../../common/core/components/page";
import { SearchFilterBar } from "../../../../common/ui/search-filter-bar";
import { DeveloperAccessRequestCard } from "../../components/common/DeveloperAccessRequestCard";
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 type { DevAuditLog } from "../../lib/devApi";
import { fetchDevAuditLogs } from "../../lib/devApi";
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import { fetchMe } from "../auth/authApi";
import { useDeveloperAccessGate } from "../developer-access/developerAccessGate";

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 = parseAuditDetails(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 navigate = useNavigate();
  const auth = useAuth();
  const hasAccessToken = Boolean(auth.user?.access_token);
  const userProfile = auth.user?.profile as Record<string, unknown> | undefined;
  const role = resolveProfileRole(userProfile);
  const tenantId = userProfile?.tenant_id as string | undefined;

  const [searchClientId, setSearchClientId] = React.useState("");
  const [searchAction, setSearchAction] = React.useState("");
  const [statusFilter, setStatusFilter] = React.useState("all");

  // Use deferred values to avoid UI lag during rapid typing
  const deferredSearchClientId = React.useDeferredValue(searchClientId.trim());
  const deferredSearchAction = React.useDeferredValue(searchAction.trim());

  const { data: me, isLoading: isLoadingMe } = useQuery({
    queryKey: ["userMe"],
    queryFn: fetchMe,
    enabled: hasAccessToken,
  });
  const profileRole = me?.role?.trim() || role;
  const {
    hasDeveloperAccess,
    isDeveloperRequestPending,
    canRequestDeveloperAccess,
    isLoadingDeveloperAccessGate,
  } = useDeveloperAccessGate({
    hasAccessToken,
    profileRole,
    tenantId,
    isLoadingIdentity: isLoadingMe,
  });

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

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

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

  if (isLoadingDeveloperAccessGate) {
    return (
      <div className="p-8 text-center">
        {t("ui.common.loading", "Loading...")}
      </div>
    );
  }

  if (!hasDeveloperAccess) {
    return (
      <DeveloperAccessRequestCard
        title={t("ui.common.audit.title", "Audit Logs")}
        isPending={isDeveloperRequestPending}
        canRequest={canRequestDeveloperAccess}
        pendingMessage={t(
          "msg.dev.dashboard.access_pending",
          "개발자 권한 신청을 검토 중입니다.",
        )}
        deniedMessage={t(
          "msg.dev.audit.access_denied",
          "감사 로그는 개발자 권한이 있어야 볼 수 있습니다.",
        )}
        pendingDetailMessage={t(
          "msg.dev.dashboard.access_pending_detail",
          "super admin이 승인하면 개요와 개발자 기능을 사용할 수 있습니다.",
        )}
        deniedDetailMessage={t(
          "msg.dev.audit.access_denied_detail",
          "개발자 권한 신청 페이지에서 신청을 등록한 뒤 승인을 받아주세요.",
        )}
        actionLabel={t("ui.dev.nav.developer_request", "개발자 권한 신청")}
        onAction={() => navigate("/developer-requests")}
      />
    );
  }

  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.common.audit.load_error", "Error loading logs: {{error}}", {
          error: errMsg,
        })}
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <PageHeader
        icon={<NotebookTabs size={20} />}
        title={t("ui.common.audit.title", "Audit Logs")}
        description={t(
          "msg.dev.audit.subtitle",
          "현재 앱 범위의 개발자 작업 이력을 조회합니다.",
        )}
        actions={
          <>
            <Badge variant="muted">
              {t("msg.common.audit.registry.count", "총 {{count}}개 로그", {
                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.common.export_csv", "CSV 내보내기")}
            </Button>
          </>
        }
      />

      <Card className="glass-panel">
        <CardHeader className="flex flex-row items-center justify-between">
          <div>
            <CardTitle>
              {t("ui.common.audit.registry.title", "Audit registry")}
            </CardTitle>
            <CardDescription>
              {t(
                "msg.dev.audit.registry_description",
                "최근 감사 로그를 검색 조건에 맞춰 필터링하고, 작업 이력을 빠르게 확인합니다.",
              )}
            </CardDescription>
          </div>
        </CardHeader>
        <CardContent className="space-y-4 pt-0">
          <SearchFilterBar
            primary={
              <form
                onSubmit={(e) => {
                  e.preventDefault();
                  query.refetch();
                }}
                className="grid flex-1 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.common.audit.filters.client_id",
                      "Filter by Client ID",
                    )}
                  />
                </div>
                <Input
                  value={searchAction}
                  onChange={(e) =>
                    setSearchAction(e.target.value.toUpperCase())
                  }
                  placeholder={t(
                    "ui.common.audit.filters.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.common.audit.filters.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>
              </form>
            }
          />

          <div
            className={
              query.isFetching && !query.isFetchingNextPage
                ? "opacity-50 transition-opacity"
                : ""
            }
          >
            <AuditLogTable
              logs={logs}
              t={t}
              loading={query.isLoading}
              hasNextPage={Boolean(query.hasNextPage)}
              isFetchingNextPage={query.isFetchingNextPage}
              onLoadMore={() => query.fetchNextPage()}
            />
          </div>
        </CardContent>
      </Card>
    </div>
  );
}

export default AuditLogsPage;
