"use client";

import type { ReactNode } from "react";
import { ChevronRight } from "lucide-react";
import { useEffect, useMemo, useState } from "react";

import { useLocale } from "@/components/providers/locale-provider";
import type { ApiErrorResponse } from "@/types/api";
import type { AuditTrailRecord } from "@/types/audit-trail";
import type { UserManagementRecord } from "@/types/user-management";

type AuditTrailResponse = {
  data: AuditTrailRecord[];
  meta: {
    page: number;
    per_page: number;
    total: number;
    total_pages: number;
  };
  filters: {
    actions: string[];
  };
};

type FilterState = {
  action: string;
  user_id: string;
  date_from: string;
  date_to: string;
  search: string;
};

const defaultFilters = (): FilterState => ({
  action: "",
  user_id: "",
  date_from: "",
  date_to: "",
  search: ""
});

export function AuditTrailClient() {
  const { dict } = useLocale();
  const [items, setItems] = useState<AuditTrailRecord[]>([]);
  const [users, setUsers] = useState<UserManagementRecord[]>([]);
  const [actions, setActions] = useState<string[]>([]);
  const [meta, setMeta] = useState({ page: 1, per_page: 25, total: 0, total_pages: 1 });
  const [filters, setFilters] = useState<FilterState>(defaultFilters);
  const [loading, setLoading] = useState(true);
  const [exporting, setExporting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const queryString = useMemo(() => {
    const params = new URLSearchParams();
    params.set("page", String(meta.page));
    params.set("per_page", String(meta.per_page));
    if (filters.action) params.set("action", filters.action);
    if (filters.user_id) params.set("user_id", filters.user_id);
    if (filters.date_from) params.set("date_from", filters.date_from);
    if (filters.date_to) params.set("date_to", filters.date_to);
    if (filters.search) params.set("search", filters.search);
    return params.toString();
  }, [filters, meta.page, meta.per_page]);

  async function loadUsers() {
    try {
      const response = await fetch("/api/v1/users", { cache: "no-store" });
      const payload = (await response.json()) as { data: UserManagementRecord[] } | ApiErrorResponse;
      if (!response.ok || !("data" in payload)) {
        throw new Error(dict.master.loadError);
      }
      setUsers(payload.data);
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.loadError);
    }
  }

  async function loadAuditTrail() {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch(`/api/v1/audit-trail?${queryString}`, {
        cache: "no-store"
      });
      const payload = (await response.json()) as AuditTrailResponse | ApiErrorResponse;
      if (!response.ok || !("data" in payload)) {
        throw new Error("message" in payload ? payload.message : dict.master.loadError);
      }
      setItems(payload.data);
      setMeta(payload.meta);
      setActions(payload.filters.actions);
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.loadError);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void loadUsers();
  }, []);

  useEffect(() => {
    void loadAuditTrail();
  }, [queryString]);

  async function exportExcel() {
    setExporting(true);
    setError(null);
    try {
      const params = new URLSearchParams();
      if (filters.action) params.set("action", filters.action);
      if (filters.user_id) params.set("user_id", filters.user_id);
      if (filters.date_from) params.set("date_from", filters.date_from);
      if (filters.date_to) params.set("date_to", filters.date_to);
      if (filters.search) params.set("search", filters.search);

      const response = await fetch(`/api/v1/audit-trail/export?${params.toString()}`);
      if (!response.ok) {
        const payload = (await response.json()) as ApiErrorResponse;
        throw new Error(payload.message ?? dict.common.requestFailed);
      }

      const blob = await response.blob();
      const url = window.URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      anchor.href = url;
      anchor.download = `audit-trail-${new Date().toISOString().slice(0, 10)}.xlsx`;
      document.body.appendChild(anchor);
      anchor.click();
      anchor.remove();
      window.URL.revokeObjectURL(url);
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.common.requestFailed);
    } finally {
      setExporting(false);
    }
  }

  return (
    <section className="space-y-6">
      <div className="ops-card p-6">
        <div className="flex flex-wrap items-end gap-4">
          <FilterField label={dict.audit.search}>
            <input
              value={filters.search}
              onChange={(event) => {
                setFilters((current) => ({ ...current, search: event.target.value }));
                setMeta((current) => ({ ...current, page: 1 }));
              }}
              placeholder="action, summary, path, email..."
              className="ops-input"
            />
          </FilterField>

          <FilterField label={dict.audit.action}>
            <select
              value={filters.action}
              onChange={(event) => {
                setFilters((current) => ({ ...current, action: event.target.value }));
                setMeta((current) => ({ ...current, page: 1 }));
              }}
              className="ops-select"
            >
              <option value="">{dict.audit.allActions}</option>
              {actions.map((action) => (
                <option key={action} value={action}>
                  {action}
                </option>
              ))}
            </select>
          </FilterField>

          <FilterField label={dict.audit.user}>
            <select
              value={filters.user_id}
              onChange={(event) => {
                setFilters((current) => ({ ...current, user_id: event.target.value }));
                setMeta((current) => ({ ...current, page: 1 }));
              }}
              className="ops-select"
            >
              <option value="">{dict.audit.allUsers}</option>
              {users.map((user) => (
                <option key={user.id} value={user.id}>
                  {user.name} · {user.role.code}
                </option>
              ))}
            </select>
          </FilterField>

          <FilterField label={dict.audit.fromDate}>
            <input
              type="date"
              value={filters.date_from}
              onChange={(event) => {
                setFilters((current) => ({ ...current, date_from: event.target.value }));
                setMeta((current) => ({ ...current, page: 1 }));
              }}
              className="ops-input"
            />
          </FilterField>

          <FilterField label={dict.audit.toDate}>
            <input
              type="date"
              value={filters.date_to}
              onChange={(event) => {
                setFilters((current) => ({ ...current, date_to: event.target.value }));
                setMeta((current) => ({ ...current, page: 1 }));
              }}
              className="ops-input"
            />
          </FilterField>

          <div className="flex gap-3">
            <button
              type="button"
              onClick={() => {
                setFilters(defaultFilters());
                setMeta((current) => ({ ...current, page: 1 }));
              }}
              className="ops-btn-secondary"
            >
              {dict.common.reset}
            </button>
            <button
              type="button"
              onClick={() => void exportExcel()}
              disabled={exporting}
              className="ops-btn-primary"
            >
              {exporting ? dict.common.processing : dict.common.exportExcel}
            </button>
          </div>
        </div>

        {error ? (
          <div className="mt-4 rounded border border-ember/30 bg-ember/10 px-4 py-3 text-sm text-ember">
            {error}
          </div>
        ) : null}
      </div>

      <div className="ops-table-shell">
        <div className="ops-section-head">
          <div>
            <p className="ops-title">{dict.audit.logTitle}</p>
            <p className="ops-copy">{dict.audit.logCopy}</p>
          </div>
          <div className="ops-chip-muted">{meta.total} {dict.audit.record}</div>
        </div>

        {loading ? (
          <div className="px-6 py-8 text-sm text-ink/60">{dict.common.loading}</div>
        ) : items.length === 0 ? (
          <div className="px-6 py-8 text-sm text-ink/60">{dict.audit.noData}</div>
        ) : (
          <div className="overflow-x-auto">
            <table className="ops-table">
              <thead>
                <tr>
                  <th>{dict.audit.time}</th>
                  <th>{dict.audit.action}</th>
                  <th>{dict.audit.user}</th>
                  <th>{dict.audit.entity}</th>
                  <th>{dict.audit.changes}</th>
                  <th>{dict.audit.path}</th>
                  <th>{dict.common.status}</th>
                  <th>{dict.audit.summary}</th>
                </tr>
              </thead>
              <tbody>
                {items.map((item) => (
                  <tr key={item.id}>
                    <td className="whitespace-nowrap text-slate-600">
                      {formatDateTime(item.occurred_at)}
                    </td>
                    <td>
                      <span className="ops-chip-active">{item.action}</span>
                    </td>
                    <td className="text-slate-600">
                      {item.user ? (
                        <>
                          <div className="font-medium text-ink">{item.user.name}</div>
                          <div className="mt-1 text-xs text-slate-500">
                            {item.user.role} · {item.user.email ?? item.user.username ?? "-"}
                          </div>
                        </>
                      ) : (
                        "-"
                      )}
                    </td>
                    <td className="text-slate-600">
                      <div className="font-medium text-ink">{item.entity_type}</div>
                      <div className="mt-1 text-xs text-slate-500">{item.entity_id ?? "-"}</div>
                    </td>
                    <td className="text-slate-600">
                      <ChangeSummary metadata={item.metadata} />
                    </td>
                    <td className="text-slate-600">{item.pathname}</td>
                    <td className="text-slate-600">{item.status_code}</td>
                    <td className="text-slate-600">{item.summary ?? "-"}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}

        <div className="flex items-center justify-between border-t border-line/60 px-6 py-4">
          <p className="text-sm text-slate-500">
            {dict.audit.pageOf} {meta.page} {dict.audit.of} {meta.total_pages}
          </p>
          <div className="flex gap-2">
            <button
              type="button"
              disabled={meta.page <= 1}
              onClick={() => setMeta((current) => ({ ...current, page: current.page - 1 }))}
              className="ops-btn-secondary disabled:cursor-not-allowed disabled:opacity-50"
            >
              {dict.audit.prev}
            </button>
            <button
              type="button"
              disabled={meta.page >= meta.total_pages}
              onClick={() => setMeta((current) => ({ ...current, page: current.page + 1 }))}
              className="ops-btn-secondary disabled:cursor-not-allowed disabled:opacity-50"
            >
              {dict.audit.next}
            </button>
          </div>
        </div>
      </div>
    </section>
  );
}

function FilterField({
  label,
  children
}: {
  label: string;
  children: ReactNode;
}) {
  return (
    <label className="block min-w-[180px] flex-1">
      <span className="ops-label">{label}</span>
      {children}
    </label>
  );
}

function formatDateTime(value: string) {
  return new Intl.DateTimeFormat("id-ID", {
    dateStyle: "medium",
    timeStyle: "short"
  }).format(new Date(value));
}

function ChangeSummary({
  metadata
}: {
  metadata: Record<string, unknown> | null;
}) {
  if (!metadata) return "-";

  const changedFields = Array.isArray(metadata.changed_fields)
    ? metadata.changed_fields.filter((item): item is string => typeof item === "string")
    : [];

  if (changedFields.length === 0) {
    return (
      <details className="group max-w-[360px] text-xs">
        <summary className="flex cursor-pointer list-none items-center gap-2 font-medium text-ink [&::-webkit-details-marker]:hidden">
          <ChevronRight className="h-4 w-4 transition-transform group-open:rotate-90" />
          Lihat metadata
        </summary>
        <pre className="mt-2 max-h-56 overflow-auto whitespace-pre-wrap break-words rounded border border-line/70 bg-slate-50 p-3 text-xs text-slate-500">
          {JSON.stringify(metadata, null, 2)}
        </pre>
      </details>
    );
  }

  const before = metadata.before && typeof metadata.before === "object" ? metadata.before : null;
  const after = metadata.after && typeof metadata.after === "object" ? metadata.after : null;
  const previewFields = changedFields.slice(0, 3);
  const remainingCount = changedFields.length - previewFields.length;

  return (
    <details className="group max-w-[360px] text-xs">
      <summary className="flex cursor-pointer list-none items-start gap-2 text-left [&::-webkit-details-marker]:hidden">
        <ChevronRight className="mt-0.5 h-4 w-4 shrink-0 text-slate-500 transition-transform group-open:rotate-90" />
        <div className="min-w-0">
          <div className="space-y-1">
            {previewFields.map((field) => (
              <div key={field} className="truncate font-medium text-ink">
                {field}
              </div>
            ))}
          </div>
          {remainingCount > 0 ? (
            <div className="mt-1 text-slate-500">+{remainingCount} perubahan lainnya</div>
          ) : null}
        </div>
      </summary>
      <div className="mt-2 space-y-2 rounded border border-line/70 bg-slate-50 p-3">
        {changedFields.map((field) => (
          <div key={field}>
            <div className="font-semibold text-ink">{field}</div>
            <div className="mt-1 text-slate-500">
              <span className="font-medium text-slate-700">Before:</span>{" "}
              {formatMetadataValue(before?.[field as keyof typeof before])}
            </div>
            <div className="text-slate-500">
              <span className="font-medium text-slate-700">After:</span>{" "}
              {formatMetadataValue(after?.[field as keyof typeof after])}
            </div>
          </div>
        ))}
      </div>
    </details>
  );
}

function formatMetadataValue(value: unknown) {
  if (value === null || value === undefined || value === "") return "-";
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
    return String(value);
  }
  return JSON.stringify(value);
}
