import type { Request, Response } from 'express';
import prisma from '../config/db';
import { buildDocumentNumberFromSequence, nextDatabaseDocumentSequence } from '../services/document-sequence.service';
import { createFallbackRecipe, listFallbackRecipes } from '../services/recipe.store';
import { resolveOperationalUser } from '../services/system.resolvers';

const serializeRecipe = (recipe: {
  id: string;
  codigo: string | null;
  fecha: Date;
  diagnostico: string;
  indicaciones: string;
  firmada: boolean;
  paciente: { id: string; nombres: string; apellidos: string };
  medico: { id: string; name: string };
}) => ({
  id: recipe.id,
  codigo: recipe.codigo ?? `REC-LEGACY-${recipe.id.slice(0, 6).toUpperCase()}`,
  fecha: recipe.fecha.toISOString(),
  diagnostico: recipe.diagnostico,
  indicaciones: recipe.indicaciones,
  firmada: recipe.firmada,
  paciente: {
    id: recipe.paciente.id,
    nombres: recipe.paciente.nombres,
    apellidos: recipe.paciente.apellidos,
  },
  medico: {
    id: recipe.medico.id,
    nombre: recipe.medico.name,
  },
});

export const listRecipes = async (_req: Request, res: Response) => {
  try {
    const recipes = await prisma.receta.findMany({
      include: {
        paciente: true,
        medico: true,
      },
      orderBy: { fecha: 'desc' },
    });

    res.setHeader('X-Data-Source', 'database');
    return res.json(recipes.map(serializeRecipe));
  } catch (error) {
    console.warn('Database unavailable for recipes, using local fallback store.', error);
    const recipes = await listFallbackRecipes();
    res.setHeader('X-Data-Source', 'local-fallback');
    return res.json(
      recipes.map((recipe) => ({
        id: recipe.id,
        codigo: recipe.codigo,
        fecha: recipe.fecha,
        diagnostico: recipe.diagnostico,
        indicaciones: recipe.indicaciones,
        firmada: recipe.firmada,
        paciente: {
          id: recipe.pacienteId,
          nombres: recipe.pacienteNombres,
          apellidos: recipe.pacienteApellidos,
        },
        medico: {
          id: 'local-doctor',
          nombre: recipe.medicoNombre,
        },
      })),
    );
  }
};

export const createRecipe = async (req: Request, res: Response) => {
  const { pacienteId, diagnostico, indicaciones, firmada } = req.body;

  if (typeof pacienteId !== 'string' || typeof diagnostico !== 'string' || typeof indicaciones !== 'string') {
    return res.status(400).json({ error: 'Paciente, diagnostico e indicaciones son obligatorios' });
  }

  try {
    const patient = await prisma.paciente.findUnique({
      where: { id: pacienteId },
    });

    if (!patient) {
      return res.status(404).json({ error: 'Paciente no encontrado' });
    }

    const doctor = await resolveOperationalUser('DENTIST');
    const recipe = await prisma.$transaction(async (transaction) => {
      const sequence = await nextDatabaseDocumentSequence(transaction, 'RECETA');

      return transaction.receta.create({
        data: {
          codigo: buildDocumentNumberFromSequence(sequence),
          pacienteId,
          medicoId: doctor.id,
          diagnostico: diagnostico.trim(),
          indicaciones: indicaciones.trim(),
          firmada: Boolean(firmada),
        },
        include: {
          paciente: true,
          medico: true,
        },
      });
    });

    res.setHeader('X-Data-Source', 'database');
    return res.status(201).json(serializeRecipe(recipe));
  } catch (error) {
    console.warn('Database unavailable while creating recipe, using local fallback store.', error);

    try {
      const recipe = await createFallbackRecipe({
        pacienteId,
        diagnostico,
        indicaciones,
        firmada: Boolean(firmada),
      });

      res.setHeader('X-Data-Source', 'local-fallback');
      return res.status(201).json({
        id: recipe.id,
        codigo: recipe.codigo,
        fecha: recipe.fecha,
        diagnostico: recipe.diagnostico,
        indicaciones: recipe.indicaciones,
        firmada: recipe.firmada,
        paciente: {
          id: recipe.pacienteId,
          nombres: recipe.pacienteNombres,
          apellidos: recipe.pacienteApellidos,
        },
        medico: {
          id: 'local-doctor',
          nombre: recipe.medicoNombre,
        },
      });
    } catch (fallbackError) {
      console.error('Error creating recipe:', fallbackError);
      return res.status(500).json({ error: 'Error interno del servidor' });
    }
  }
};
