import { reactive, ref, watch } from "vue";
import { useRoute, useRouter, type LocationQueryRaw } from "vue-router";
import { usageAPI } from "@/api";
import type { AdminUsageRow, UsageLedgerRow } from "@/types";

const auditQueryMap = {
  search: "auditSearch",
  userId: "auditUser",
  serviceId: "service",
  resourceType: "resource",
  apiKeyId: "apiKey",
  status: "auditStatus",
  kind: "kind",
  source: "source",
  idempotencyKey: "idempotency",
  from: "from",
  to: "to",
} as const;

export function useUserAuditWorkspace() {
  const route = useRoute();
  const router = useRouter();
  const auditTab = ref<"usage" | "ledger">(route.query.audit === "ledger" ? "ledger" : "usage");
  const auditLoading = ref(false);
  const auditError = ref<string | null>(null);
  const auditUsageRows = ref<AdminUsageRow[]>([]);
  const auditLedgerRows = ref<UsageLedgerRow[]>([]);
  const auditPage = ref(Math.max(1, Number(route.query.auditPage) || 1));
  const auditPageSize = 25;
  const auditTotal = ref(0);
  const auditFilters = reactive({
    search: textQuery("auditSearch"),
    userId: textQuery("auditUser"),
    serviceId: textQuery("service"),
    resourceType: textQuery("resource"),
    apiKeyId: textQuery("apiKey"),
    status: textQuery("auditStatus"),
    kind: textQuery("kind"),
    source: textQuery("source"),
    idempotencyKey: textQuery("idempotency"),
    from: textQuery("from"),
    to: textQuery("to"),
  });
  let auditRequestSequence = 0;

  function textQuery(key: string): string {
    return typeof route.query[key] === "string" ? String(route.query[key]) : "";
  }
  function auditParams(extra: Record<string, unknown> = {}): Record<string, unknown> {
    const params: Record<string, unknown> = { page: auditPage.value, pageSize: auditPageSize, ...extra };
    for (const [key, value] of Object.entries(auditFilters))
      if (String(value).trim()) params[key] = String(value).trim();
    if (auditTab.value === "usage") {
      delete params.kind;
      delete params.source;
    } else {
      delete params.serviceId;
      delete params.resourceType;
      delete params.apiKeyId;
    }
    return params;
  }
  async function loadAudit(updateRoute = true): Promise<void> {
    const requestSequence = ++auditRequestSequence;
    if (updateRoute) await syncAuditQuery();
    if (requestSequence !== auditRequestSequence) return;
    auditLoading.value = true;
    auditError.value = null;
    const response = auditTab.value === "usage"
      ? await usageAPI.adminUsage(auditParams())
      : await usageAPI.adminLedger(auditParams());
    if (requestSequence !== auditRequestSequence) return;
    auditLoading.value = false;
    if (!response.ok) {
      auditError.value = response.error ?? `HTTP ${response.status}`;
      return;
    }
    auditTotal.value = Number(response.data?.total ?? response.data?.count ?? 0);
    if (auditTab.value === "usage") auditUsageRows.value = response.data?.rows ?? [];
    else auditLedgerRows.value = response.data?.rows ?? [];
  }
  async function syncAuditQuery(): Promise<void> {
    const query: LocationQueryRaw = {
      ...route.query,
      audit: auditTab.value === "ledger" ? "ledger" : undefined,
      auditPage: auditPage.value > 1 ? String(auditPage.value) : undefined,
    };
    for (const [key, queryKey] of Object.entries(auditQueryMap))
      query[queryKey] = auditFilters[key as keyof typeof auditFilters].trim() || undefined;
    await router.push({ query });
  }
  async function setAuditTab(value: "usage" | "ledger"): Promise<void> {
    auditTab.value = value;
    auditPage.value = 1;
    await loadAudit();
  }
  async function setAuditPage(value: number): Promise<void> {
    auditPage.value = value;
    await loadAudit();
  }
  function downloadAudit(): void {
    window.location.assign(auditTab.value === "usage"
      ? usageAPI.adminUsageExportUrl(auditParams({ limit: 1000 }))
      : usageAPI.adminLedgerExportUrl(auditParams({ limit: 1000 })));
  }

  watch(
    () => route.query,
    () => {
      const nextPage = Math.max(1, Number(route.query.auditPage) || 1);
      const nextTab = route.query.audit === "ledger" ? "ledger" : "usage";
      const changed = auditPage.value !== nextPage || auditTab.value !== nextTab ||
        Object.entries(auditQueryMap).some(([key, queryKey]) =>
          auditFilters[key as keyof typeof auditFilters] !== textQuery(queryKey));
      if (!changed) return;
      for (const [key, queryKey] of Object.entries(auditQueryMap))
        auditFilters[key as keyof typeof auditFilters] = textQuery(queryKey);
      auditPage.value = nextPage;
      auditTab.value = nextTab;
      void loadAudit(false);
    },
  );

  return {
    auditTab, auditLoading, auditError, auditUsageRows, auditLedgerRows,
    auditPage, auditPageSize, auditTotal, auditFilters, loadAudit,
    setAuditTab, setAuditPage, downloadAudit,
  };
}
