import { useVirtualizer } from "@tanstack/react-virtual";
import { ChevronDown, ChevronUp, Copy } from "lucide-react";
import * as React from "react";
import {
  formatAuditDateParts,
  formatAuditValue,
  parseAuditDetails,
  resolveAuditAction,
  resolveAuditActor,
  resolveAuditTarget,
} from "../../../../common/core/audit";
import {
  type CommonBadgeVariant,
  getCommonBadgeClasses,
} from "../../../../common/ui/badge";
import { getCommonButtonClasses } from "../../../../common/ui/button";
import {
  commonStickyTableHeaderClass,
  commonTableBodyClass,
  commonTableCellClass,
  commonTableClass,
  commonTableHeadClass,
  commonTableHeaderClass,
  commonTableRowClass,
  commonTableShellClass,
  commonTableViewportClass,
  commonTableWrapperClass,
} from "../../../../common/ui/table";
import { Button } from "../../components/ui/button";
import type { AuditLog } from "../../lib/adminApi";

type AuditTranslate = (
  key: string,
  fallback: string,
  vars?: Record<string, string | number>,
) => string;

type VirtualizedAuditLogTableProps = {
  logs: AuditLog[];
  t: AuditTranslate;
  loading: boolean;
  hasNextPage: boolean;
  isFetchingNextPage: boolean;
  onLoadMore: () => void;
  className?: string;
};

function cx(...classNames: Array<string | false | null | undefined>) {
  return classNames.filter(Boolean).join(" ");
}

function statusVariant(status: string): CommonBadgeVariant {
  return status === "success" || status === "ok" ? "success" : "warning";
}

export function VirtualizedAuditLogTable({
  logs,
  t,
  loading,
  hasNextPage,
  isFetchingNextPage,
  onLoadMore,
  className,
}: VirtualizedAuditLogTableProps) {
  const [expandedRows, setExpandedRows] = React.useState<
    Record<string, boolean>
  >({});
  const viewportRef = React.useRef<HTMLDivElement>(null);
  const isTest =
    (typeof process !== "undefined" && process.env.NODE_ENV === "test") ||
    (typeof window !== "undefined" &&
      (window as Window & { _IS_TEST_MODE?: boolean })._IS_TEST_MODE);

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

  const rowVirtualizer = useVirtualizer({
    count: logs.length,
    getScrollElement: () => viewportRef.current,
    estimateSize: () => 80,
    measureElement: (el) => el.getBoundingClientRect().height,
    overscan: isTest ? logs.length : 10,
    initialRect: isTest ? { width: 1010, height: 1000 } : undefined,
  });

  const virtualRows = rowVirtualizer.getVirtualItems();

  React.useEffect(() => {
    if (isTest) {
      return;
    }
    const lastItem = virtualRows[virtualRows.length - 1];
    if (!lastItem) return;

    if (
      lastItem.index >= logs.length - 1 &&
      hasNextPage &&
      !isFetchingNextPage
    ) {
      onLoadMore();
    }
  }, [
    virtualRows,
    logs.length,
    hasNextPage,
    isFetchingNextPage,
    onLoadMore,
    isTest,
  ]);

  const tableMinWidth = 1010;

  const renderRow = (
    row: AuditLog,
    index: number,
    virtualRow?: { start: number; end: number },
  ) => {
    if (!row) return null;

    const details = parseAuditDetails(row.details);
    const actorLabel = resolveAuditActor(row, details);
    const actionLabel = resolveAuditAction(row, details);
    const targetLabel = resolveAuditTarget(details);
    const rowKey = `${row.event_id}-${row.timestamp}-${index}`;
    const expanded = Boolean(expandedRows[rowKey]);
    const { date, time } = formatAuditDateParts(row.timestamp);

    return (
      <tr
        key={rowKey}
        data-index={index}
        ref={virtualRow ? rowVirtualizer.measureElement : undefined}
        className={cx(
          commonTableRowClass,
          "bg-card/40",
          virtualRow ? "absolute left-0 w-full" : "",
        )}
        style={
          virtualRow
            ? {
                transform: `translateY(${virtualRow.start}px)`,
              }
            : undefined
        }
      >
        <td colSpan={6} className="p-0">
          <div className={cx("flex items-center", expanded && "border-b")}>
            <div
              className={cx(
                commonTableCellClass,
                "w-[190px] shrink-0 text-xs text-muted-foreground",
              )}
            >
              <div className="space-y-1">
                <div>{date}</div>
                <div>{time}</div>
              </div>
            </div>
            <div className={cx(commonTableCellClass, "w-[180px] shrink-0")}>
              <div className="flex items-center gap-2">
                <code className="rounded-md bg-secondary/60 px-2 py-1 text-xs text-muted-foreground">
                  {actorLabel}
                </code>
                {actorLabel !== "-" ? (
                  <button
                    type="button"
                    className={cx(
                      getCommonButtonClasses({
                        variant: "ghost",
                        size: "icon",
                      }),
                      "h-7 w-7 text-muted-foreground hover:text-primary",
                    )}
                    aria-label={t(
                      "ui.common.audit.copy.actor_id",
                      "Copy User ID",
                    )}
                    onClick={() => handleCopy(actorLabel)}
                  >
                    <Copy className="h-3 w-3" />
                  </button>
                ) : null}
              </div>
            </div>
            <div
              className={cx(
                commonTableCellClass,
                "w-[180px] shrink-0 text-xs text-muted-foreground",
              )}
            >
              <div className="font-semibold text-foreground">{actionLabel}</div>
            </div>
            <div
              className={cx(
                commonTableCellClass,
                "w-[260px] shrink-0 text-xs text-muted-foreground",
              )}
            >
              <div className="flex items-center gap-2">
                <span className="break-all">{targetLabel}</span>
                {targetLabel !== "-" ? (
                  <button
                    type="button"
                    className={cx(
                      getCommonButtonClasses({
                        variant: "ghost",
                        size: "icon",
                      }),
                      "h-7 w-7 text-muted-foreground hover:text-primary",
                    )}
                    aria-label={t(
                      "ui.common.audit.copy.target",
                      "Copy Client ID",
                    )}
                    onClick={() => handleCopy(targetLabel)}
                  >
                    <Copy className="h-3 w-3" />
                  </button>
                ) : null}
              </div>
            </div>
            <div className={cx(commonTableCellClass, "w-[120px] shrink-0")}>
              <span
                className={getCommonBadgeClasses({
                  variant: statusVariant(row.status),
                })}
              >
                {row.status}
              </span>
            </div>
            <div
              className={cx(
                commonTableCellClass,
                "w-[80px] shrink-0 text-right",
              )}
            >
              <button
                type="button"
                className={getCommonButtonClasses({
                  variant: "ghost",
                  size: "sm",
                })}
                onClick={() => {
                  setExpandedRows((prev) => ({
                    ...prev,
                    [rowKey]: !expanded,
                  }));
                  // Re-measure after state change
                  setTimeout(() => rowVirtualizer.measure(), 0);
                }}
              >
                {expanded ? (
                  <ChevronUp className="h-4 w-4" />
                ) : (
                  <ChevronDown className="h-4 w-4" />
                )}
              </button>
            </div>
          </div>
          {expanded && (
            <div className={cx(commonTableCellClass, "bg-card/20 text-xs")}>
              <div className="grid gap-4 text-muted-foreground md:grid-cols-3">
                <div className="space-y-1">
                  <div className="uppercase tracking-[0.16em]">
                    {t("ui.common.audit.details.request", "Request")}
                  </div>
                  <div className="break-all">
                    {t(
                      "ui.common.audit.details.request_id",
                      "Request ID · {{value}}",
                      { value: formatAuditValue(details.request_id) },
                    )}
                  </div>
                  <div className="break-all">
                    {t(
                      "ui.common.audit.details.event_id",
                      "Event ID · {{value}}",
                      { value: formatAuditValue(row.event_id) },
                    )}
                  </div>
                  <div>
                    {t("ui.common.audit.details.ip", "IP · {{value}}", {
                      value: formatAuditValue(row.ip_address),
                    })}
                  </div>
                  <div className="break-all">
                    {t("ui.common.audit.details.method", "Method · {{value}}", {
                      value: formatAuditValue(details.method),
                    })}
                  </div>
                  <div className="break-all">
                    {t("ui.common.audit.details.path", "Path · {{value}}", {
                      value: formatAuditValue(details.path),
                    })}
                  </div>
                  <div>
                    {t(
                      "ui.common.audit.details.latency",
                      "Latency · {{value}}",
                      {
                        value:
                          details.latency_ms !== undefined
                            ? `${details.latency_ms}ms`
                            : "-",
                      },
                    )}
                  </div>
                </div>
                <div className="space-y-1">
                  <div className="uppercase tracking-[0.16em]">
                    {t("ui.common.audit.details.actor", "Actor")}
                  </div>
                  <div>
                    {t(
                      "ui.common.audit.details.actor_id",
                      "User ID · {{value}}",
                      { value: actorLabel },
                    )}
                  </div>
                  <div>
                    {t("ui.common.audit.details.tenant", "Tenant · {{value}}", {
                      value: formatAuditValue(details.tenant_id),
                    })}
                  </div>
                  <div>
                    {t("ui.common.audit.details.device", "Device · {{value}}", {
                      value: formatAuditValue(row.device_id),
                    })}
                  </div>
                  <div className="break-all">
                    {t(
                      "ui.common.audit.details.target",
                      "Client ID · {{value}}",
                      { value: targetLabel },
                    )}
                  </div>
                </div>
                <div className="space-y-1">
                  <div className="uppercase tracking-[0.16em]">
                    {t("ui.common.audit.details.result", "Result")}
                  </div>
                  <div className="break-all">
                    {t("ui.common.audit.details.error", "Error · {{value}}", {
                      value: formatAuditValue(details.error),
                    })}
                  </div>
                  <div className="break-all">
                    {t("ui.common.audit.details.before", "Before · {{value}}", {
                      value: formatAuditValue(details.before),
                    })}
                  </div>
                  <div className="break-all">
                    {t("ui.common.audit.details.after", "After · {{value}}", {
                      value: formatAuditValue(details.after),
                    })}
                  </div>
                </div>
              </div>
            </div>
          )}
        </td>
      </tr>
    );
  };

  return (
    <div className={cx(commonTableShellClass, className)}>
      <div
        ref={viewportRef}
        className={cx(commonTableViewportClass, "flex-1")}
        data-testid="audit-table-viewport"
      >
        <div
          className={commonTableWrapperClass}
          style={{ minWidth: tableMinWidth }}
        >
          <table
            className={cx(commonTableClass, "table-fixed w-full")}
            style={{ borderCollapse: "separate", borderSpacing: 0 }}
          >
            <thead
              className={cx(
                commonTableHeaderClass,
                commonStickyTableHeaderClass,
              )}
            >
              <tr className={commonTableRowClass}>
                <th className={cx(commonTableHeadClass, "w-[190px]")}>
                  {t("ui.common.audit.table.time", "Time")}
                </th>
                <th className={cx(commonTableHeadClass, "w-[180px]")}>
                  {t("ui.common.audit.table.user_id", "User ID")}
                </th>
                <th className={cx(commonTableHeadClass, "w-[180px]")}>
                  {t("ui.common.audit.table.action", "Action")}
                </th>
                <th className={cx(commonTableHeadClass, "w-[260px]")}>
                  {t("ui.common.audit.table.client_id", "Client ID")}
                </th>
                <th className={cx(commonTableHeadClass, "w-[120px]")}>
                  {t("ui.common.audit.table.status", "Status")}
                </th>
                <th className={cx(commonTableHeadClass, "w-[80px]")} />
              </tr>
            </thead>
            <tbody
              className={commonTableBodyClass}
              style={
                !isTest
                  ? {
                      height: `${rowVirtualizer.getTotalSize()}px`,
                      position: "relative",
                    }
                  : undefined
              }
            >
              {isTest
                ? logs.map((row, index) => renderRow(row, index))
                : virtualRows.map((virtualRow) =>
                    renderRow(
                      logs[virtualRow.index],
                      virtualRow.index,
                      virtualRow,
                    ),
                  )}
              {logs.length === 0 && !loading && (
                <tr>
                  <td
                    colSpan={6}
                    className={cx(
                      commonTableCellClass,
                      "text-center py-8 text-muted-foreground",
                    )}
                  >
                    {t("ui.common.audit.table.no_logs", "No audit logs found")}
                  </td>
                </tr>
              )}
            </tbody>
          </table>
        </div>
      </div>

      <div className="flex-shrink-0 border-t bg-background/50 p-4 text-center backdrop-blur-sm">
        {hasNextPage ? (
          <div className="flex flex-col items-center gap-2">
            {isFetchingNextPage && (
              <span className="animate-pulse text-xs text-muted-foreground">
                {t("msg.common.loading", "Loading more...")}
              </span>
            )}
            <Button
              variant="outline"
              size="sm"
              onClick={onLoadMore}
              disabled={isFetchingNextPage}
            >
              {isFetchingNextPage
                ? t("msg.common.loading", "Loading...")
                : t("ui.common.audit.load_more", "더 보기")}
            </Button>
          </div>
        ) : logs.length > 0 ? (
          <span className="text-xs text-muted-foreground">
            {t("msg.common.audit.end", "End of audit feed")}
          </span>
        ) : null}
      </div>
    </div>
  );
}
