import { clientesApi } from './api';
import { db } from './db';

export type PaginatedCacheResult<T> = {
  data: T[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
};

export function mapRemoteClienteToDb(cliente: any) {
  return {
    tarjeta: cliente.tarjeta,
    nombre: cliente.nombre || cliente.comercial || cliente.razonsocial || cliente.tarjeta,
    nit: cliente.nit,
    direccion: cliente.direccion,
    telefono: cliente.telefono,
    celular: cliente.celular,
    email: cliente.email,
    syncStatus: 'synced' as const,
    lastModified: Date.now(),
  };
}

export async function cacheRemoteClientes(list: any[]): Promise<void> {
  if (!Array.isArray(list) || list.length === 0) {
    return;
  }

  await db.clientes.bulkPut(list.map(mapRemoteClienteToDb));
}

export async function syncRemoteClientesCache(limit = 200): Promise<void> {
  let page = 1;
  let totalPages = 1;

  do {
    const response = await clientesApi.list({ page, limit });
    const rows = response?.data || [];

    if (Array.isArray(rows) && rows.length > 0) {
      await cacheRemoteClientes(rows);
    }

    totalPages = Math.max(1, Number(response?.totalPages || 1));
    page += 1;
  } while (page <= totalPages);
}

export async function refreshClienteSearchCache(search: string): Promise<void> {
  if (search.trim().length < 2) {
    return;
  }

  const rows = await clientesApi.search(search.trim());
  await cacheRemoteClientes(rows);
}

function mapLocalClient(cliente: any) {
  return {
    tarjeta: cliente.tarjeta,
    nombre: cliente.nombre,
    nit: cliente.nit,
    direccion: cliente.direccion,
    telefono: cliente.telefono,
    celular: cliente.celular,
    email: cliente.email,
    origen: cliente.syncStatus === 'pending' ? 'local' : 'erp',
  };
}

export async function getLocalClientes({
  search = '',
  page = 1,
  limit = 20,
}: {
  search?: string;
  page?: number;
  limit?: number;
}): Promise<PaginatedCacheResult<any>> {
  const all = await db.clientes.toArray();
  const normalizedSearch = search.trim().toLowerCase();
  const filtered = normalizedSearch.length >= 2
    ? all.filter((cliente) => {
        const composite = [
          cliente.nombre,
          cliente.tarjeta,
          cliente.nit,
          cliente.telefono,
          cliente.celular,
          cliente.email,
        ]
          .filter(Boolean)
          .join(' ')
          .toLowerCase();

        return composite.includes(normalizedSearch);
      })
    : all;

  const sorted = filtered.sort((a, b) => (a.nombre || '').localeCompare(b.nombre || ''));
  const total = sorted.length;
  const safeLimit = Math.max(1, limit);
  const totalPages = Math.max(1, Math.ceil(total / safeLimit));
  const safePage = Math.min(Math.max(1, page), totalPages);
  const start = (safePage - 1) * safeLimit;

  return {
    data: sorted.slice(start, start + safeLimit).map(mapLocalClient),
    total,
    page: safePage,
    limit: safeLimit,
    totalPages,
  };
}
