import {
  useQuery,
  useMutation,
  useQueryClient,
  keepPreviousData,
} from "@tanstack/react-query";
import { useAuthToken } from "~/hooks/use-root-data";
import { getApiBaseUrl } from "~/utils/api-config";

/* ------------------------------------------------------------------ *
 * Admin panel data hooks (superuser only). The admin API is a new,
 * fast-moving surface, so these call it directly with fetch (same
 * pattern as use-seller-hooks' useMyStores) rather than the generated
 * client. Responses are camelCased by the backend renderer.
 * ------------------------------------------------------------------ */

export interface AdminOverview {
  generatedAt: string;
  users: {
    total: number;
    active: number;
    sellers: number;
    new7d: number;
    new30d: number;
  };
  sellers: {
    total: number;
    pending: number;
    approved: number;
    rejected: number;
    verified: number;
  };
  products: { total: number; active: number };
  orders: {
    total: number;
    pending: number;
    confirmed: number;
    shipped: number;
    delivered: number;
    cancelled: number;
    paidCount: number;
    revenueTotal: number;
    ordersToday: number;
    revenueToday: number;
  };
  money: {
    walletHeld: number;
    sellerPayable: number;
    payoutsPendingCount: number;
    payoutsPendingAmount: number;
  };
  ordersSeries: Array<{ date: string; orders: number; revenue: number }>;
}

async function adminGet<T>(path: string, token: string): Promise<T> {
  const res = await fetch(`${getApiBaseUrl()}/api/adminpanel/v1/${path}`, {
    headers: { Authorization: `Bearer ${token}` },
  });
  if (!res.ok) {
    throw new Error(`Admin request failed (${res.status})`);
  }
  return res.json();
}

async function adminPatch<T>(
  path: string,
  body: Record<string, unknown>,
  token: string
): Promise<T> {
  const res = await fetch(`${getApiBaseUrl()}/api/adminpanel/v1/${path}`, {
    method: "PATCH",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) {
    throw new Error(`Admin update failed (${res.status})`);
  }
  return res.json();
}

export function useAdminOverview() {
  const token = useAuthToken();
  return useQuery({
    queryKey: ["admin", "overview"],
    enabled: !!token,
    refetchInterval: 60_000,
    queryFn: () => adminGet<AdminOverview>("overview/", token as string),
  });
}

/* ------------------------------ boards ------------------------------ */

export interface Paginated<T> {
  count: number;
  next: string | null;
  previous: string | null;
  results: T[];
}

export type AdminListParams = Record<
  string,
  string | number | boolean | undefined
>;

function toQuery(params: AdminListParams): string {
  const usp = new URLSearchParams();
  Object.entries(params).forEach(([k, v]) => {
    if (v !== undefined && v !== "" && v !== null) usp.set(k, String(v));
  });
  const s = usp.toString();
  return s ? `?${s}` : "";
}

function useAdminList<T>(key: string, params: AdminListParams) {
  const token = useAuthToken();
  return useQuery({
    queryKey: ["admin", key, params],
    enabled: !!token,
    placeholderData: keepPreviousData,
    queryFn: () =>
      adminGet<Paginated<T>>(`${key}/${toQuery(params)}`, token as string),
  });
}

export interface AdminOrderRow {
  id: string;
  createdAt: string;
  status: string;
  paymentStatus: string;
  totalPrice: number;
  userPhone: string | null;
  userName: string | null;
  sellerName: string | null;
  sellerUsername: string | null;
}

export interface AdminSellerRow {
  id: string;
  username: string;
  storeName: string;
  storeLogo: string | null;
  status: string;
  isVerified: boolean;
  platformFee: number;
  productCount: number;
  followerCount: number;
  reviewAverage: number;
  createdAt: string;
  userPhone: string | null;
}

export interface AdminUserRow {
  id: string;
  phoneNumber: string;
  username: string | null;
  email: string | null;
  isActive: boolean;
  isSeller: boolean;
  isStaff: boolean;
  isSuperuser: boolean;
  otpVerified: boolean;
  createdAt: string;
}

export interface AdminProductRow {
  id: string;
  title: string;
  basePrice: number;
  isActive: boolean;
  createdAt: string;
  sellerName: string | null;
  sellerUsername: string | null;
  categoryName: string | null;
  primaryImage: string | null;
}

export const useAdminOrders = (params: AdminListParams) =>
  useAdminList<AdminOrderRow>("orders", params);
export const useAdminSellers = (params: AdminListParams) =>
  useAdminList<AdminSellerRow>("sellers", params);
export const useAdminUsers = (params: AdminListParams) =>
  useAdminList<AdminUserRow>("users", params);
export const useAdminProducts = (params: AdminListParams) =>
  useAdminList<AdminProductRow>("products", params);

/* ----------------------------- actions ------------------------------ */

function useAdminUpdate(resource: "sellers" | "users" | "products") {
  const token = useAuthToken();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, data }: { id: string; data: Record<string, unknown> }) =>
      adminPatch(`${resource}/${id}/`, data, token as string),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["admin", resource] });
      qc.invalidateQueries({ queryKey: ["admin", "overview"] });
    },
  });
}

export const useAdminSellerUpdate = () => useAdminUpdate("sellers");
export const useAdminUserUpdate = () => useAdminUpdate("users");
export const useAdminProductUpdate = () => useAdminUpdate("products");

/* ------------------------------ ledger ------------------------------ */

export interface LedgerOverview {
  walletHeld: number;
  sellerPayable: number;
  depositsTotal: number;
  purchasesTotal: number;
  payouts: {
    pending: { amount: number; count: number };
    completed: { amount: number; count: number };
    rejected: { amount: number; count: number };
  };
  reconciliation: {
    completedPayoutsNotDebited: number;
    sellerPayableRecorded: number;
    sellerPayableEstimatedTrue: number;
  };
}

export interface LedgerTransactionRow {
  id: string;
  transactionType: string;
  amount: number;
  userPhone: string | null;
  order: string | null;
  authority: string | null;
  createdAt: string;
}

export interface LedgerPayoutRow {
  id: string;
  sellerName: string | null;
  sellerUsername: string | null;
  amount: number;
  status: string;
  requestedAt: string;
  processedAt: string | null;
  iban: string | null;
  bankName: string | null;
  accountHolder: string | null;
  shomareMarja: string | null;
  shomareErja: string | null;
}

export interface LedgerSellerRow {
  sellerId: string;
  storeName: string | null;
  username: string | null;
  availableFunds: number;
  completedPayouts: number;
  pendingPayouts: number;
}

export interface LedgerSellerDetail {
  seller: { id: string; storeName: string; username: string; platformFee: number };
  recordedBalance: number;
  accruedFromOrders: number;
  completedPayouts: number;
  pendingPayouts: number;
  derivedBalance: number;
  discrepancy: number;
  bankAccounts: Array<{
    id: string;
    accountHolder: string;
    iban: string;
    cardNumber: string;
    bankName: string;
    isVerified: boolean;
  }>;
  payouts: LedgerPayoutRow[];
}

export function useLedgerOverview() {
  const token = useAuthToken();
  return useQuery({
    queryKey: ["admin", "ledger", "overview"],
    enabled: !!token,
    queryFn: () => adminGet<LedgerOverview>("ledger/overview/", token as string),
  });
}

export const useLedgerTransactions = (params: AdminListParams) =>
  useAdminList<LedgerTransactionRow>("ledger/transactions", params);
export const useLedgerPayouts = (params: AdminListParams) =>
  useAdminList<LedgerPayoutRow>("ledger/payouts", params);
export const useLedgerSellers = (params: AdminListParams) =>
  useAdminList<LedgerSellerRow>("ledger/sellers", params);

export function useLedgerSellerDetail(id: string | undefined) {
  const token = useAuthToken();
  return useQuery({
    queryKey: ["admin", "ledger", "seller", id],
    enabled: !!token && !!id,
    queryFn: () =>
      adminGet<LedgerSellerDetail>(`ledger/sellers/${id}/`, token as string),
  });
}

async function adminPost<T>(
  path: string,
  body: Record<string, unknown>,
  token: string
): Promise<T> {
  const res = await fetch(`${getApiBaseUrl()}/api/adminpanel/v1/${path}`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) {
    let detail = `Admin action failed (${res.status})`;
    try {
      const j = await res.json();
      if (j?.detail) detail = j.detail;
    } catch {
      /* ignore */
    }
    throw new Error(detail);
  }
  return res.json();
}

/** Approve (complete → debits balance + journals) or reject a pending payout. */
export function useLedgerPayoutAction() {
  const token = useAuthToken();
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, action }: { id: string; action: "complete" | "reject" }) =>
      adminPost(`ledger/payouts/${id}/action/`, { action }, token as string),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["admin", "ledger"] });
      qc.invalidateQueries({ queryKey: ["admin", "overview"] });
    },
  });
}
