import { EstadoTratamiento, Prisma } from '@prisma/client';
import type { Request, Response } from 'express';
import prisma from '../config/db';

const serializeTreatmentCatalogItem = (treatment: {
  id: string;
  nombre: string;
  descripcion: string | null;
  costoBase: number;
  activo: boolean;
  updatedAt: Date;
}) => ({
  id: treatment.id,
  nombre: treatment.nombre,
  descripcion: treatment.descripcion,
  costoBase: treatment.costoBase,
  activo: treatment.activo,
  updatedAt: treatment.updatedAt.toISOString(),
});

const normalizeText = (value: unknown) => (typeof value === 'string' ? value.trim() : '');
const normalizeOptionalText = (value: unknown) => {
  const normalized = normalizeText(value);
  return normalized || null;
};

const normalizeCost = (value: unknown) => {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return Number(value.toFixed(2));
  }

  if (typeof value === 'string' && value.trim()) {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? Number(parsed.toFixed(2)) : null;
  }

  return null;
};

const normalizeActive = (value: unknown) => (typeof value === 'boolean' ? value : undefined);

export const listTreatmentCatalog = async (_req: Request, res: Response) => {
  try {
    const treatments = await prisma.tratamiento.findMany({
      where: {
        pacienteId: null,
      },
      orderBy: [{ activo: 'desc' }, { nombre: 'asc' }],
    });

    res.setHeader('X-Data-Source', 'database');
    return res.json(treatments.map(serializeTreatmentCatalogItem));
  } catch (error) {
    console.error('Error listing treatment catalog:', error);
    return res.status(500).json({ error: 'No se pudo cargar el tarifario.' });
  }
};

export const createTreatmentCatalogItem = async (req: Request, res: Response) => {
  const nombre = normalizeText(req.body.nombre);
  const descripcion = normalizeOptionalText(req.body.descripcion);
  const costoBase = normalizeCost(req.body.costoBase);
  const activo = normalizeActive(req.body.activo);

  if (!nombre || costoBase === null || costoBase <= 0) {
    return res.status(400).json({ error: 'Nombre y honorario base son obligatorios.' });
  }

  try {
    const treatment = await prisma.tratamiento.create({
      data: {
        nombre,
        descripcion,
        costoBase,
        activo: activo ?? true,
        estado: EstadoTratamiento.PLANIFICADO,
        pacienteId: null,
      },
    });

    res.setHeader('X-Data-Source', 'database');
    return res.status(201).json(serializeTreatmentCatalogItem(treatment));
  } catch (error) {
    if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2002') {
      return res.status(409).json({ error: 'Ya existe un tratamiento con esos datos unicos.' });
    }

    console.error('Error creating treatment catalog item:', error);
    return res.status(500).json({ error: 'No se pudo registrar el tratamiento del tarifario.' });
  }
};

export const updateTreatmentCatalogItem = async (req: Request, res: Response) => {
  const treatmentId = typeof req.params.treatmentId === 'string' ? req.params.treatmentId.trim() : '';
  const nombre = req.body.nombre !== undefined ? normalizeText(req.body.nombre) : undefined;
  const descripcion = req.body.descripcion !== undefined ? normalizeOptionalText(req.body.descripcion) : undefined;
  const costoBase = req.body.costoBase !== undefined ? normalizeCost(req.body.costoBase) : undefined;
  const activo = normalizeActive(req.body.activo);

  if (!treatmentId) {
    return res.status(400).json({ error: 'Tratamiento invalido.' });
  }

  if (nombre !== undefined && !nombre) {
    return res.status(400).json({ error: 'El nombre no puede quedar vacio.' });
  }

  if (costoBase !== undefined && (costoBase === null || costoBase <= 0)) {
    return res.status(400).json({ error: 'El honorario base debe ser mayor a cero.' });
  }

  try {
    const existing = await prisma.tratamiento.findFirst({
      where: {
        id: treatmentId,
        pacienteId: null,
      },
    });

    if (!existing) {
      return res.status(404).json({ error: 'Tratamiento del tarifario no encontrado.' });
    }

    const updated = await prisma.tratamiento.update({
      where: { id: treatmentId },
      data: {
        ...(nombre !== undefined ? { nombre } : {}),
        ...(descripcion !== undefined ? { descripcion } : {}),
        ...(costoBase !== undefined ? { costoBase } : {}),
        ...(activo !== undefined ? { activo } : {}),
      },
    });

    res.setHeader('X-Data-Source', 'database');
    return res.json(serializeTreatmentCatalogItem(updated));
  } catch (error) {
    console.error('Error updating treatment catalog item:', error);
    return res.status(500).json({ error: 'No se pudo actualizar el tratamiento del tarifario.' });
  }
};
