import axios from '@/network/axios';
import { apis } from '@/utils/apis/apis';
import { SuccessResponse } from '@/utils/types/Responses';
import {
  AdjustBalancePayload,
  AdjustBalanceResponse,
  BrandWalletDetail,
  BrandWalletRow,
  CollaborationTransferRow,
  CrTransferLine,
  CrTransfersResponse,
  CrTransfersSummary,
  MoneyOverview,
  ApproveChargePayload,
  RejectChargePayload,
  RevenueReportData,
  WalletCharge,
  WalletChargePaymentMethod,
  WalletChargeStatus,
  WalletTransaction,
  WalletsListMeta,
  WalletsListResponse,
} from './wallets.types';

const M = apis.DASHBOARD.MARKETPLACE_ADMIN.MONEY;
const WC = apis.DASHBOARD.MARKETPLACE_ADMIN.WALLET_CHARGES;

type LaravelPaginator<T> = {
  current_page: number;
  last_page: number;
  per_page: number;
  total: number;
  data: T[];
};

const emptyMeta: WalletsListMeta = {
  current_page: 1,
  last_page: 1,
  per_page: 25,
  total: 0,
};

function normalizeList<T>(
  raw: unknown,
): WalletsListResponse<T> {
  if (!raw || typeof raw !== 'object') {
    return { items: [], meta: emptyMeta };
  }

  // already { items, meta }
  if ('items' in raw && Array.isArray((raw as { items: T[] }).items)) {
    const r = raw as { items: T[]; meta?: WalletsListMeta };
    return {
      items: r.items,
      meta: r.meta ?? {
        current_page: 1,
        last_page: 1,
        per_page: r.items.length,
        total: r.items.length,
      },
    };
  }

  // bare Laravel paginator — must be checked BEFORE { data, meta }
  // because both have a `data` array, but the bare paginator has top-level
  // pagination keys (`current_page`, `last_page`, …) instead of a nested `meta`.
  if (
    'data' in raw &&
    Array.isArray((raw as LaravelPaginator<T>).data) &&
    'current_page' in raw
  ) {
    const p = raw as LaravelPaginator<T>;
    return {
      items: p.data,
      meta: {
        current_page: p.current_page ?? 1,
        last_page: p.last_page ?? 1,
        per_page: p.per_page ?? p.data.length,
        total: p.total ?? p.data.length,
      },
    };
  }

  // { data: T[], meta: {...} } — Laravel resource-collection shape used in the spec
  if ('data' in raw && Array.isArray((raw as { data: T[] }).data)) {
    const items = (raw as { data: T[] }).data;
    const meta = (raw as { meta?: WalletsListMeta }).meta;
    return {
      items,
      meta: meta ?? {
        current_page: 1,
        last_page: 1,
        per_page: items.length,
        total: items.length,
      },
    };
  }

  return { items: [], meta: emptyMeta };
}

// ─── Money overview ─────────────────────────────────────────────────────────

export type MoneyOverviewParams = {
  from?: string;
  to?: string;
};

export const fetchMoneyOverview = async (
  params?: MoneyOverviewParams,
): Promise<MoneyOverview> => {
  const response = await axios.get<SuccessResponse<MoneyOverview>>(M.OVERVIEW, {
    params,
  });
  return response.data?.data;
};

// ─── Brand wallets ──────────────────────────────────────────────────────────

export type BrandWalletsParams = {
  q?: string;
  min_balance?: number;
  max_balance?: number;
  sort?: string;
  page?: number;
  per_page?: number;
};

export const fetchBrandWallets = async (
  params?: BrandWalletsParams,
): Promise<WalletsListResponse<BrandWalletRow>> => {
  const response = await axios.get<unknown>(M.BRAND_WALLETS_LIST, { params });
  const data = (response.data as { data?: unknown })?.data;
  return normalizeList<BrandWalletRow>(data);
};

export const fetchBrandWallet = async (
  brandId: number,
): Promise<BrandWalletDetail> => {
  const response = await axios.get<SuccessResponse<BrandWalletDetail>>(
    M.BRAND_WALLET_SHOW(brandId),
  );
  return response.data?.data;
};

export type BrandWalletTransactionsParams = {
  type?: 'credit' | 'debit';
  source?: string;
  from?: string;
  to?: string;
  page?: number;
  per_page?: number;
};

export const fetchBrandWalletTransactions = async (
  brandId: number,
  params?: BrandWalletTransactionsParams,
): Promise<WalletsListResponse<WalletTransaction>> => {
  const response = await axios.get<unknown>(
    M.BRAND_WALLET_TRANSACTIONS(brandId),
    { params },
  );
  const data = (response.data as { data?: unknown })?.data;
  return normalizeList<WalletTransaction>(data);
};

export const adjustBrandWallet = async (
  brandId: number,
  payload: AdjustBalancePayload,
): Promise<AdjustBalanceResponse> => {
  const response = await axios.post<SuccessResponse<AdjustBalanceResponse>>(
    M.BRAND_WALLET_ADJUST(brandId),
    payload,
  );
  return response.data?.data;
};

// ─── Collaboration transfers (ledger) ───────────────────────────────────────

export type TransfersParams = {
  account_type?: 'creator' | 'platform' | 'vat';
  creator_id?: number;
  brand_id?: number;
  cr_id?: number;
  from?: string;
  to?: string;
  page?: number;
  per_page?: number;
};

export const fetchTransfers = async (
  params?: TransfersParams,
): Promise<WalletsListResponse<CollaborationTransferRow>> => {
  const response = await axios.get<unknown>(M.TRANSFERS, { params });
  const data = (response.data as { data?: unknown })?.data;
  return normalizeList<CollaborationTransferRow>(data);
};

function computeSummaryFromLines(
  rows: CrTransferLine[],
): CrTransfersSummary {
  const currency = rows[0]?.currency ?? 'SAR';
  let creator_earned = 0;
  let platform_fee = 0;
  let vat_collected = 0;
  for (const r of rows) {
    if (r.type !== 'credit') continue;
    const amt = Number(r.amount) || 0;
    if (r.account_type === 'creator') creator_earned += amt;
    else if (r.account_type === 'platform') platform_fee += amt;
    else if (r.account_type === 'vat') vat_collected += amt;
  }
  return {
    currency,
    brand_paid: creator_earned + platform_fee + vat_collected,
    creator_earned,
    platform_fee,
    vat_collected,
  };
}

export const fetchCrTransfers = async (
  crId: number,
): Promise<CrTransfersResponse> => {
  const response = await axios.get<SuccessResponse<CrTransfersResponse>>(
    M.CR_TRANSFERS(crId),
  );
  const payload = response.data?.data;

  // Defensive fallback: if BE ever changes shape, derive what we can.
  if (!payload || typeof payload !== 'object') {
    return {
      collaboration_request: null,
      brand_paid: null,
      transfers: [],
      summary: {
        currency: 'SAR',
        brand_paid: 0,
        creator_earned: 0,
        platform_fee: 0,
        vat_collected: 0,
      },
    };
  }

  const transfers = Array.isArray(payload.transfers) ? payload.transfers : [];

  return {
    collaboration_request: payload.collaboration_request ?? null,
    brand_paid: payload.brand_paid ?? null,
    transfers,
    summary: payload.summary ?? computeSummaryFromLines(transfers),
  };
};

// ─── Reports ────────────────────────────────────────────────────────────────

export type ReportParams = {
  from: string;
  to: string;
  group_by?: 'day' | 'week' | 'month';
};

export const fetchPlatformRevenueReport = async (
  params: ReportParams,
): Promise<RevenueReportData> => {
  const response = await axios.get<SuccessResponse<RevenueReportData>>(
    M.REPORT_PLATFORM_REVENUE,
    { params },
  );
  return response.data?.data;
};

export const fetchVatReport = async (
  params: ReportParams,
): Promise<RevenueReportData> => {
  const response = await axios.get<SuccessResponse<RevenueReportData>>(
    M.REPORT_VAT_COLLECTED,
    { params },
  );
  return response.data?.data;
};

// ─── Brand top-up requests (wallet charges) ─────────────────────────────────

export type WalletChargesParams = {
  status?: WalletChargeStatus;
  payment_method?: WalletChargePaymentMethod;
  brand_id?: number | string;
  from?: string;
  to?: string;
  page?: number;
  per_page?: number;
};

export const fetchWalletCharges = async (
  params?: WalletChargesParams,
): Promise<WalletsListResponse<WalletCharge>> => {
  const response = await axios.get<unknown>(WC.LIST, { params });
  const data = (response.data as { data?: unknown })?.data;
  return normalizeList<WalletCharge>(data);
};

export const fetchWalletCharge = async (id: number): Promise<WalletCharge> => {
  const response = await axios.get<SuccessResponse<WalletCharge>>(WC.SHOW(id));
  return response.data?.data;
};

export const approveWalletCharge = async (
  id: number,
  payload?: ApproveChargePayload,
): Promise<WalletCharge> => {
  const response = await axios.post<SuccessResponse<WalletCharge>>(
    WC.APPROVE(id),
    payload ?? {},
  );
  return response.data?.data;
};

export const rejectWalletCharge = async (
  id: number,
  payload: RejectChargePayload,
): Promise<WalletCharge> => {
  const response = await axios.post<SuccessResponse<WalletCharge>>(
    WC.REJECT(id),
    payload,
  );
  return response.data?.data;
};
