import { EstadoPresupuesto, TipoDocumento } from '@prisma/client';
import { randomUUID } from 'crypto';
import { nextFallbackDocumentSequence, syncFallbackDocumentSequence } from './document.store';
import { buildDocumentNumberFromSequence } from './document-sequence.service';
import { getBudgetDocumentSequenceType } from './document-sequences';
import { listFallbackPatients } from './patient.store';
import { readDataFile, writeDataFile } from './local-store';

export type StoredBudget = {
  id: string;
  folio: string;
  fecha: string;
  subtotal: number;
  igv: number;
  total: number;
  estado: EstadoPresupuesto;
  tipoDocumento: TipoDocumento | null;
  serieDoc: string | null;
  correlativoDoc: string | null;
  concepto: string;
  pacienteId: string;
  pacienteNombres: string;
  pacienteApellidos: string;
  creadoPorNombre: string;
};

type CreateFallbackBudgetInput = {
  pacienteId: string;
  total: number;
  concepto: string;
  estado?: EstadoPresupuesto;
  tipoDocumento?: TipoDocumento | null;
};

const fileName = 'budgets.json';

const buildSeedBudgets = async () => {
  const patients = await listFallbackPatients();

  if (patients.length === 0) {
    return [] as StoredBudget[];
  }

  const [firstPatient, secondPatient = firstPatient] = patients;
  const now = new Date().toISOString();

  return [
    {
      id: randomUUID(),
      folio: 'PRE001-000001',
      fecha: now,
      subtotal: 508.47,
      igv: 91.53,
      total: 600,
      estado: EstadoPresupuesto.APROBADO,
      tipoDocumento: TipoDocumento.BOLETA,
      serieDoc: 'B001',
      correlativoDoc: '000001',
      concepto: 'Limpieza integral y control',
      pacienteId: firstPatient!.id,
      pacienteNombres: firstPatient!.nombres,
      pacienteApellidos: firstPatient!.apellidos,
      creadoPorNombre: 'Administrador DentaFlow',
    },
    {
      id: randomUUID(),
      folio: 'PRE001-000002',
      fecha: now,
      subtotal: 762.71,
      igv: 137.29,
      total: 900,
      estado: EstadoPresupuesto.PENDIENTE,
      tipoDocumento: TipoDocumento.FACTURA,
      serieDoc: 'F001',
      correlativoDoc: '000001',
      concepto: 'Restauracion estetica',
      pacienteId: secondPatient!.id,
      pacienteNombres: secondPatient!.nombres,
      pacienteApellidos: secondPatient!.apellidos,
      creadoPorNombre: 'Administrador DentaFlow',
    },
  ];
};

export const listFallbackBudgets = async () =>
  readDataFile<StoredBudget[]>(fileName, buildSeedBudgets);

export const createFallbackBudget = async (input: CreateFallbackBudgetInput) => {
  const budgets = await listFallbackBudgets();
  const patients = await listFallbackPatients();
  const patient = patients.find((item) => item.id === input.pacienteId);

  if (!patient) {
    throw new Error('Paciente no encontrado');
  }

  const subtotal = Number((input.total / 1.18).toFixed(2));
  const igv = Number((input.total - subtotal).toFixed(2));
  await syncFallbackDocumentSequence('BUDGET_FOLIO', budgets.length);
  await syncFallbackDocumentSequence(
    getBudgetDocumentSequenceType(input.tipoDocumento),
    budgets.filter((item) => item.tipoDocumento === (input.tipoDocumento ?? TipoDocumento.BOLETA)).length,
  );
  const folioSequence = await nextFallbackDocumentSequence('BUDGET_FOLIO');
  const documentSequence = await nextFallbackDocumentSequence(getBudgetDocumentSequenceType(input.tipoDocumento));
  const [serieDocValue, correlativoDocValue] = buildDocumentNumberFromSequence(documentSequence).split('-');
  const serieDoc = serieDocValue ?? null;
  const correlativoDoc = correlativoDocValue ?? null;

  const budget: StoredBudget = {
    id: randomUUID(),
    folio: buildDocumentNumberFromSequence(folioSequence),
    fecha: new Date().toISOString(),
    subtotal,
    igv,
    total: input.total,
    estado: input.estado ?? EstadoPresupuesto.PENDIENTE,
    tipoDocumento: input.tipoDocumento ?? TipoDocumento.BOLETA,
    serieDoc,
    correlativoDoc,
    concepto: input.concepto.trim(),
    pacienteId: patient.id,
    pacienteNombres: patient.nombres,
    pacienteApellidos: patient.apellidos,
    creadoPorNombre: 'Administrador DentaFlow',
  };

  budgets.unshift(budget);
  await writeDataFile(fileName, budgets);
  return budget;
};
