﻿import { db, type DbOrdenTrabajo } from './db';

type LocalOtFilters = {
  search?: string;
  estado?: string;
  page?: number;
  limit?: number;
};

export function buildLocalOtRouteId(localId: string): string {
  return `local-${localId}`;
}

function parseRouteId(routeId: string): { serverId?: number; localId?: string } {
  if (routeId.startsWith('local-')) {
    return { localId: routeId.slice('local-'.length) };
  }

  const asNumber = Number(routeId);
  if (Number.isFinite(asNumber) && asNumber > 0) {
    return { serverId: asNumber };
  }

  return { localId: routeId };
}

function normalizeDate(value: any): Date {
  if (value instanceof Date) return value;
  if (typeof value === 'string' || typeof value === 'number') {
    const parsed = new Date(value);
    if (!Number.isNaN(parsed.getTime())) {
      return parsed;
    }
  }
  return new Date();
}

export function mapRemoteOtToDb(ot: any): DbOrdenTrabajo {
  const localId = String(ot.localId || `srv-${ot.id}`);
  return {
    localId,
    serverId: Number(ot.id),
    numeroOt: ot.numeroOt,
    clienteTarjeta: String(ot.clienteTarjeta || ''),
    vehiculo: ot.vehiculo || {},
    fechaEntrada: normalizeDate(ot.fechaEntrada),
    fechaSalida: ot.fechaSalida ? normalizeDate(ot.fechaSalida) : undefined,
    km: Number(ot.km || 0),
    nivelGasolina: Number(ot.nivelGasolina || 0),
    requerimientoCliente: ot.requerimientoCliente || '',
    observaciones: ot.observaciones || '',
    estado: String(ot.estado || 'borrador'),
    cosasTrae: Array.isArray(ot.cosasTrae)
      ? ot.cosasTrae.map((item: any) => Number(item?.cosaTraeId || item?.id || item)).filter((x: number) => Number.isFinite(x))
      : [],
    danos: Array.isArray(ot.danos) ? ot.danos : [],
    fotos: Array.isArray(ot.fotos) ? ot.fotos : [],
    firma: ot.firma || undefined,
    cotizacion: Array.isArray(ot.cotizaciones) ? ot.cotizaciones[0] : ot.cotizacion,
    syncStatus: 'synced',
    lastModified: Date.now(),
    version: Number(ot.version || 1),
  };
}

export async function cacheRemoteOtList(ots: any[]): Promise<void> {
  const mapped = ots
    .filter((ot) => Number.isFinite(Number(ot?.id)))
    .map((ot) => mapRemoteOtToDb(ot));

  if (mapped.length === 0) {
    return;
  }

  await db.transaction('rw', db.ordenesTrabajo, async () => {
    for (const ot of mapped) {
      const existing = await db.ordenesTrabajo.where('serverId').equals(ot.serverId!).first();
      if (existing && existing.syncStatus === 'pending') {
        continue;
      }
      await db.ordenesTrabajo.put(ot);
    }
  });
}

export async function setLocalOtCotizacion(serverId: number, cotizacion: any): Promise<void> {
  const existing = await db.ordenesTrabajo.where('serverId').equals(serverId).first();
  if (!existing) return;

  await db.ordenesTrabajo.update(existing.localId, {
    cotizacion: cotizacion || undefined,
    lastModified: Date.now(),
  });
}

function toUiOt(ot: DbOrdenTrabajo): any {
  const routeId = ot.serverId ? String(ot.serverId) : buildLocalOtRouteId(ot.localId);
  const numeroOt = ot.numeroOt || `OT-LOCAL-${ot.localId.slice(0, 8).toUpperCase()}`;

  return {
    id: routeId,
    serverId: ot.serverId,
    localId: ot.localId,
    numeroOt,
    clienteTarjeta: ot.clienteTarjeta,
    vehiculo: ot.vehiculo || {},
    fechaEntrada: ot.fechaEntrada,
    fechaSalida: ot.fechaSalida,
    km: ot.km,
    nivelGasolina: ot.nivelGasolina,
    requerimientoCliente: ot.requerimientoCliente,
    observaciones: ot.observaciones,
    estado: ot.estado,
    cosasTrae: ot.cosasTrae || [],
    danos: ot.danos || [],
    fotos: ot.fotos || [],
    firma: ot.firma,
    cotizaciones: ot.cotizacion ? [ot.cotizacion] : [],
    syncStatus: ot.syncStatus,
  };
}

export async function getLocalOtList(filters: LocalOtFilters = {}) {
  const { search = '', estado = '', page = 1, limit = 20 } = filters;
  const normalizedSearch = search.trim().toLowerCase();

  const all = await db.ordenesTrabajo.toArray();
  const filtered = all.filter((ot) => {
    if (estado && ot.estado !== estado) {
      return false;
    }

    if (!normalizedSearch) {
      return true;
    }

    const numeroOt = String(ot.numeroOt || '').toLowerCase();
    const placa = String(ot.vehiculo?.placa || '').toLowerCase();
    const cliente = String(ot.clienteTarjeta || '').toLowerCase();

    return numeroOt.includes(normalizedSearch) || placa.includes(normalizedSearch) || cliente.includes(normalizedSearch);
  });

  filtered.sort((a, b) => normalizeDate(b.fechaEntrada).getTime() - normalizeDate(a.fechaEntrada).getTime());

  const total = filtered.length;
  const start = (page - 1) * limit;
  const data = filtered.slice(start, start + limit).map(toUiOt);

  const byEstado = {
    borrador: 0,
    en_proceso: 0,
    cotizada: 0,
    aprobada: 0,
    terminada: 0,
    entregada: 0,
  };

  for (const ot of all) {
    if (Object.prototype.hasOwnProperty.call(byEstado, ot.estado)) {
      (byEstado as any)[ot.estado] += 1;
    }
  }

  return {
    data,
    total,
    page,
    totalPages: Math.max(1, Math.ceil(total / limit)),
    byEstado,
  };
}

export async function getLocalOtByRouteId(routeId: string): Promise<any | null> {
  const parsed = parseRouteId(routeId);
  let ot: DbOrdenTrabajo | undefined;

  if (parsed.serverId) {
    ot = await db.ordenesTrabajo.where('serverId').equals(parsed.serverId).first();
  } else if (parsed.localId) {
    ot = await db.ordenesTrabajo.where('localId').equals(parsed.localId).first();
  }

  if (!ot) {
    return null;
  }

  return toUiOt(ot);
}
