import { api } from "@/src/lib/api/client";

/**
 * Treasury / Comptabilité minimaliste (Entrées / Sorties)
 *
 * Endpoints (backend):
 * - Comptes:       /treasury-accounts/
 * - Journal:       /treasury-movements/
 *   - Summary:     /treasury-movements/summary/
 *   - Manuel:      /treasury-movements/manual/
 *   - Transfert:   /treasury-movements/transfer/
 *   - Suggestions: /treasury-movements/customer-suggestions/ (+ debtor-suggestions)
 * - Reversements:  /remittances/
 *
 * NOTE:
 * Le backend scope par tenant via request.tenant ou membership.
 */

export type TreasuryAccountType = "bank" | "cash" | "mobile_money" | "other" | string;

export type TreasuryAccount = {
  id: number;
  tenant: number;
  name: string;
  type: TreasuryAccountType;
  currency: string;
  is_default: boolean;
  metadata?: any | null;
  created_by?: number | null;
  created_at?: string;
  updated_at?: string;
};

export type TreasuryMovementDirection = "in" | "out" | string;
export type TreasuryMovementStatus = "pending" | "confirmed" | "cancelled" | string;

export type TreasuryMovement = {
  id: number;
  tenant: number;

  // FK ids
  account: number;
  customer: number | null;
  case: number | null;
  payment: number | null;
  remittance: number | null;

  // denormalized display
  account_name?: string | null;
  account_currency?: string | null;
  customer_name?: string | null;
  debtor_name?: string | null;
  case_reference?: string | null;
  direction_label?: string | null;
  status_label?: string | null;

  direction: TreasuryMovementDirection;
  status: TreasuryMovementStatus;

  amount: string; // Decimal as string
  currency: string;

  value_date: string;

  label: string;
  reference: string;

  source: string;
  source_label?: string;
  source_key: string | null;

  notes: string;

  created_by: number | null;
  created_at: string;
};

export type TreasuryTotalsRow = {
  currency: string;
  total_in: string;
  total_out: string;
  net: string;
  count: number;
};

export type TreasuryAccountBalance = {
  account: number;
  currency: string;
  total_in: string;
  total_out: string;
  balance: string;
  count: number;
  last_value_date?: string | null;
};

export type TreasuryMovementsSummary = {
  totals: TreasuryTotalsRow[];
  account_balances: TreasuryAccountBalance[];
};

export type TreasuryCustomerSuggestion = {
  id: number;
  label: string;
};

export type TreasuryDebtorSuggestion = {
  id: number;
  label: string;
};

export type RemittanceStatus = "draft" | "validated" | "paid" | "cancelled" | string;

export type RemittanceLine = {
  id: number;
  remittance: number;
  payment: number;
  case: number | null;
  amount: string;
  notes: string;
  created_at: string;
};

export type RemittanceBatch = {
  id: number;
  tenant: number;
  customer: number;
  customer_name?: string | null;
  account: number;
  account_name?: string | null;
  currency: string;
  amount_total: string;
  status: RemittanceStatus;
  reference: string;
  notes: string;
  paid_at: string | null;
  created_by: number | null;
  created_at: string;
  updated_at: string;
  lines: RemittanceLine[];
};

export type EligibleRemittancePayment = {
  id: number; // payment id
  amount: string;
  currency: string;
  paid_at: string;
  reference: string;
  case_id: number | null;
  case_reference: string | null;
  debtor_name: string | null;
};

export type PaginatedResponse<T> = {
  count: number;
  next: string | null;
  previous: string | null;
  results: T[];
};

function normalizeListResponse<T>(res: any): T[] {
  if (Array.isArray(res)) return res as T[];
  if (res && Array.isArray(res.results)) return res.results as T[];
  return [];
}

function normalizePaginated<T>(res: any): PaginatedResponse<T> {
  if (res && Array.isArray(res.results)) {
    return {
      count: res.count ?? res.results.length,
      next: res.next ?? null,
      previous: res.previous ?? null,
      results: res.results as T[],
    };
  }
  const arr = Array.isArray(res) ? (res as T[]) : [];
  return { count: arr.length, next: null, previous: null, results: arr };
}

// -------------------- Accounts --------------------

export async function listTreasuryAccounts(): Promise<TreasuryAccount[]> {
  const res = await api.request<any>("/treasury-accounts/", { method: "GET" });
  return normalizeListResponse<TreasuryAccount>(res);
}

export async function createTreasuryAccount(payload: {
  name: string;
  type?: TreasuryAccountType;
  currency?: string;
  is_default?: boolean;
  metadata?: any;
}): Promise<TreasuryAccount> {
  return api.request<TreasuryAccount>("/treasury-accounts/", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

export async function updateTreasuryAccount(id: number, patch: Partial<TreasuryAccount>): Promise<TreasuryAccount> {
  return api.request<TreasuryAccount>(`/treasury-accounts/${id}/`, {
    method: "PATCH",
    body: JSON.stringify(patch),
  });
}

// -------------------- Movements (Journal) --------------------

export async function listTreasuryMovements(params: {
  accountId?: number;
  customerId?: number;
  caseId?: number;
  direction?: "in" | "out";
  status?: string;
  source?: string;
  dateFrom?: string; // YYYY-MM-DD
  dateTo?: string; // YYYY-MM-DD
  creditorQuery?: string;
  customerQuery?: string;
  debtorQuery?: string;
  caseQuery?: string;
  referenceQuery?: string;
  page?: number;
  pageSize?: number;
}): Promise<PaginatedResponse<TreasuryMovement>> {
  const qp: string[] = [];

  if (params.accountId) qp.push(`account=${encodeURIComponent(String(params.accountId))}`);
  if (params.customerId) qp.push(`customer=${encodeURIComponent(String(params.customerId))}`);
  if (params.caseId) qp.push(`case=${encodeURIComponent(String(params.caseId))}`);
  if (params.direction) qp.push(`direction=${encodeURIComponent(params.direction)}`);
  if (params.status) qp.push(`status=${encodeURIComponent(params.status)}`);
  if (params.source) qp.push(`source=${encodeURIComponent(params.source)}`);

  if (params.dateFrom) qp.push(`date_from=${encodeURIComponent(params.dateFrom)}`);
  if (params.dateTo) qp.push(`date_to=${encodeURIComponent(params.dateTo)}`);

  const creditorQ = (params.creditorQuery ?? params.customerQuery ?? "").trim();
  if (creditorQ) qp.push(`customer_q=${encodeURIComponent(creditorQ)}`);

  const debtorQ = (params.debtorQuery ?? "").trim();
  if (debtorQ) qp.push(`debtor_q=${encodeURIComponent(debtorQ)}`);

  const caseQ = (params.caseQuery ?? params.referenceQuery ?? "").trim();
  if (caseQ) qp.push(`case_q=${encodeURIComponent(caseQ)}`);

  if (params.page && params.page > 1) qp.push(`page=${params.page}`);
  if (params.pageSize) qp.push(`page_size=${params.pageSize}`);

  const url = `/treasury-movements/${qp.length ? `?${qp.join("&")}` : ""}`;
  const res = await api.request<any>(url, { method: "GET" });
  return normalizePaginated<TreasuryMovement>(res);
}

export async function getTreasuryMovementsSummary(params: {
  accountId?: number;
  customerId?: number;
  caseId?: number;
  direction?: "in" | "out";
  status?: string;
  source?: string;
  dateFrom?: string;
  dateTo?: string;
  creditorQuery?: string;
  customerQuery?: string;
  debtorQuery?: string;
  caseQuery?: string;
  referenceQuery?: string;
  /** When true, passes confirmed_only=1 to the backend (default: backend defaults to confirmed) */
  confirmedOnly?: boolean;
}): Promise<TreasuryMovementsSummary> {
  const qp: string[] = [];

  if (params.accountId) qp.push(`account=${encodeURIComponent(String(params.accountId))}`);
  if (params.customerId) qp.push(`customer=${encodeURIComponent(String(params.customerId))}`);
  if (params.caseId) qp.push(`case=${encodeURIComponent(String(params.caseId))}`);
  if (params.direction) qp.push(`direction=${encodeURIComponent(params.direction)}`);
  if (params.status) qp.push(`status=${encodeURIComponent(params.status)}`);
  if (params.source) qp.push(`source=${encodeURIComponent(params.source)}`);

  if (params.dateFrom) qp.push(`date_from=${encodeURIComponent(params.dateFrom)}`);
  if (params.dateTo) qp.push(`date_to=${encodeURIComponent(params.dateTo)}`);

  const creditorQ = (params.creditorQuery ?? params.customerQuery ?? "").trim();
  if (creditorQ) qp.push(`customer_q=${encodeURIComponent(creditorQ)}`);

  const debtorQ = (params.debtorQuery ?? "").trim();
  if (debtorQ) qp.push(`debtor_q=${encodeURIComponent(debtorQ)}`);

  const caseQ = (params.caseQuery ?? params.referenceQuery ?? "").trim();
  if (caseQ) qp.push(`case_q=${encodeURIComponent(caseQ)}`);

  if (params.confirmedOnly === true) qp.push("confirmed_only=1");
  else if (params.confirmedOnly === false) qp.push("confirmed_only=0");

  const url = `/treasury-movements/summary/${qp.length ? `?${qp.join("&")}` : ""}`;
  return api.request<TreasuryMovementsSummary>(url, { method: "GET" });
}

export async function listTreasuryCustomerSuggestions(params: { q: string; limit?: number }): Promise<TreasuryCustomerSuggestion[]> {
  const qp: string[] = [];
  qp.push(`q=${encodeURIComponent(params.q || "")}`);
  if (params.limit) qp.push(`limit=${encodeURIComponent(String(params.limit))}`);
  const url = `/treasury-movements/customer-suggestions/?${qp.join("&")}`;
  const res = await api.request<any>(url, { method: "GET" });
  return normalizeListResponse<TreasuryCustomerSuggestion>(res);
}

export async function listTreasuryDebtorSuggestions(params: { q: string; limit?: number }): Promise<TreasuryDebtorSuggestion[]> {
  const qp: string[] = [];
  qp.push(`q=${encodeURIComponent(params.q || "")}`);
  if (params.limit) qp.push(`limit=${encodeURIComponent(String(params.limit))}`);
  const url = `/treasury-movements/debtor-suggestions/?${qp.join("&")}`;
  const res = await api.request<any>(url, { method: "GET" });
  return normalizeListResponse<TreasuryDebtorSuggestion>(res);
}

/**
 * Mouvement manuel (entrée/sortie).
 */
export async function createTreasuryManualMovement(payload: {
  account: number;
  direction: "in" | "out";
  amount: string | number;
  currency?: string;
  value_date?: string; // ISO
  label?: string;
  reference?: string;
  notes?: string;
  customer?: number | null;
  case?: number | null;
  status?: "pending" | "confirmed";
}): Promise<TreasuryMovement> {
  return api.request<TreasuryMovement>("/treasury-movements/manual/", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

/**
 * Alias rétro-compat (anciens imports).
 */
export const createManualTreasuryMovement = createTreasuryManualMovement;

/**
 * Transfert interne entre deux comptes.
 * Génère 2 mouvements : OUT (compte source) + IN (compte destination)
 */
export async function createTreasuryTransfer(payload: {
  from_account: number;
  to_account: number;
  amount: string | number;
  currency?: string;
  value_date?: string; // ISO
  reference?: string;
  notes?: string;
  status?: "pending" | "confirmed";
}): Promise<{ out_movement_id: number; in_movement_id: number; transfer_key: string }> {
  return api.request<any>("/treasury-movements/transfer/", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

// -------------------- Remittances --------------------

export async function listRemittances(params?: {
  customerId?: number;
  status?: string;
  q?: string;
  page?: number;
  pageSize?: number;
}): Promise<PaginatedResponse<RemittanceBatch>> {
  const qp: string[] = [];
  if (params?.customerId) qp.push(`customer=${encodeURIComponent(String(params.customerId))}`);
  if (params?.status) qp.push(`status=${encodeURIComponent(String(params.status))}`);
  if (params?.q) qp.push(`q=${encodeURIComponent(params.q)}`);
  if (params?.page && params.page > 1) qp.push(`page=${params.page}`);
  if (params?.pageSize) qp.push(`page_size=${params.pageSize}`);

  const url = `/remittances/${qp.length ? `?${qp.join("&")}` : ""}`;
  const res = await api.request<any>(url, { method: "GET" });
  return normalizePaginated<RemittanceBatch>(res);
}

export async function getRemittance(id: number): Promise<RemittanceBatch> {
  return api.request<RemittanceBatch>(`/remittances/${id}/`, { method: "GET" });
}

export async function createRemittanceDraft(payload: {
  customer: number;
  account: number;
  currency?: string;
  notes?: string;
}): Promise<RemittanceBatch> {
  return api.request<RemittanceBatch>("/remittances/draft/", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

export async function listEligibleRemittancePayments(params?: {
  customerId?: number;
  q?: string;
  limit?: number;
}): Promise<EligibleRemittancePayment[]> {
  const qp: string[] = [];
  if (params?.customerId) qp.push(`customer=${encodeURIComponent(String(params.customerId))}`);
  if (params?.q) qp.push(`q=${encodeURIComponent(params.q)}`);
  if (params?.limit) qp.push(`limit=${encodeURIComponent(String(params.limit))}`);
  const url = `/remittances/eligible-payments/${qp.length ? `?${qp.join("&")}` : ""}`;
  const res = await api.request<any>(url, { method: "GET" });
  return normalizeListResponse<EligibleRemittancePayment>(res);
}

export async function addPaymentToRemittance(
  remittanceId: number,
  payload: { payment: number; amount?: string | number; notes?: string },
): Promise<RemittanceLine> {
  return api.request<RemittanceLine>(`/remittances/${remittanceId}/add-payment/`, {
    method: "POST",
    body: JSON.stringify({
      payment: payload.payment,
      amount: payload.amount,
      notes: payload.notes,
    }),
  });
}

export async function markRemittancePaid(
  remittanceId: number,
  payload?: { reference?: string; paid_at?: string },
): Promise<any> {
  return api.request<any>(`/remittances/${remittanceId}/mark-paid/`, {
    method: "POST",
    body: JSON.stringify({ reference: payload?.reference || "", paid_at: payload?.paid_at || null }),
  });
}

export async function validateRemittance(remittanceId: number): Promise<any> {
  return api.request<any>(`/remittances/${remittanceId}/validate/`, { method: "POST" });
}

export async function cancelRemittance(remittanceId: number): Promise<any> {
  return api.request<any>(`/remittances/${remittanceId}/cancel/`, { method: "POST" });
}
