import { Router, Request, Response } from 'express';
import PsWorkflowTareas from '../modelos-web/ps_workflow_tareas.modelo';
import { sequelize } from '../config/database';
import { QueryTypes } from 'sequelize';

const psWorkflowTareasRouter = Router();

// Obtener todas las tareas del workflow
psWorkflowTareasRouter.get('/', async (req: Request, res: Response) => {
  try {
    const tareas = await PsWorkflowTareas.findAll();
    res.json(tareas);
  } catch (error) {
    res.status(500).json({ error: 'Error al obtener las tareas del workflow' });
  }
});

// Endpoint para insertar tareas automáticamente a partir de nuevos pedidos
psWorkflowTareasRouter.post('/insertar_tareas_pedidos', async (req: Request, res: Response) => {
  try {
    const nuevosArticulos: any[] = await sequelize.query(
      `SELECT *
       FROM ps_workflow_data wd
       WHERE current_state IN (3, 33)
         AND NOT EXISTS (
           SELECT 1 FROM ps_workflow_tareas wt
           WHERE wt.id_order = wd.id_order
            AND wt.id_order_detail = wd.id_order_detail
         )`,
      { type: QueryTypes.SELECT }
    );

    for (const articulo of nuevosArticulos) {
      const { id_order, id_order_detail, id_value, product_quantity } = articulo;

      const maquinas: any[] = await sequelize.query(
        `
        WITH MaquinasPrioritarias AS (
          SELECT
            wm.*,
            m.nombre AS maquina_nombre,
            m.id_maquina_relacionada,
            m.param1,
            t.descripcion,
            t.nombre AS tarea_nombre,
            t.orden,
            t.id_tipo_tarea,
            m.id_tarea AS id_tarea_maquina,
            t.id AS id_tarea,
            ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY wm.prioridad ASC) AS rn
          FROM ps_workflow_maquinas wm
          JOIN maquina m ON m.id = wm.id_maquina
          JOIN tarea t ON t.id = m.id_tarea
          WHERE wm.id_value = :id_value
        )
        SELECT * FROM MaquinasPrioritarias
        WHERE rn = 1
        ORDER BY orden ASC;
        `,
        {
          type: QueryTypes.SELECT,
          replacements: { id_value }
        }
      );            

      const tareasInsertadas = new Set();

      for (const maquina of maquinas) {
        const key = `${maquina.id_tarea}-${maquina.id_maquina}`;
        if (tareasInsertadas.has(key)) continue;
        tareasInsertadas.add(key);

        // Insertar tarea
        await sequelize.query(
          `INSERT INTO ps_workflow_tareas 
          (id_order, id_order_detail, id_value, id_tarea, tarea_nombre, descripcion, estado, orden, id_maquina, maquina_nombre, prioridad, id_maquina_relacionada, fecha_realizacion, grupo_trabajo, product_quantity, id_operario, param1) 
          VALUES 
          (:id_order, :id_order_detail, :id_value, :id_tarea, :tarea_nombre, :descripcion, 1, :orden, :id_maquina, :maquina_nombre, :prioridad, :id_maquina_relacionada, NULL, NULL, :product_quantity, NULL, :param1);`,
          {
            replacements: {
              id_order,
              id_order_detail,
              id_value,
              id_tarea: maquina.id_tarea,
              tarea_nombre: maquina.tarea_nombre,
              descripcion: maquina.descripcion,
              orden: maquina.orden,
              id_maquina: maquina.id_maquina,
              maquina_nombre: maquina.maquina_nombre,
              prioridad: maquina.prioridad,
              id_maquina_relacionada: maquina.id_maquina_relacionada,
              product_quantity,
              param1: maquina.param1 ?? null
            },
            type: QueryTypes.INSERT
          }
        );

        // Insertar tarea RIP si la tarea es impresión
        if (maquina.id_tipo_tarea === 1 && maquina.tarea_nombre === 'Imprimir') {
          const maquinaRip: any = await sequelize.query(
            `SELECT * FROM maquina WHERE id = :id_maquina LIMIT 1`,
            {
              type: QueryTypes.SELECT,
              replacements: { id_maquina: maquina.id_maquina_relacionada }
            }
          ).then(r => r[0]);

          if (maquinaRip) {
            const tareaRip: any = await sequelize.query(
              `SELECT * FROM tarea WHERE id = :id_tarea LIMIT 1`,
              {
                type: QueryTypes.SELECT,
                replacements: { id_tarea: maquinaRip.id_tarea }
              }
            ).then(r => r[0]);

            if (tareaRip) {
              await sequelize.query(
                `INSERT INTO ps_workflow_tareas 
                (id_order, id_order_detail, id_value, id_tarea, tarea_nombre, descripcion, estado, orden, id_maquina, maquina_nombre, prioridad, id_maquina_relacionada, fecha_realizacion, grupo_trabajo, product_quantity, id_operario, param1) 
                VALUES 
                (:id_order, :id_order_detail, :id_value, :id_tarea, 'RIP', 'RIP', 1, :orden, :id_maquina, :maquina_nombre, :prioridad, :id_maquina_relacionada, NULL, NULL, :product_quantity, NULL, :param1);`,
                {
                  replacements: {
                    id_order,
                    id_order_detail,
                    id_value,
                    id_tarea: tareaRip.id,
                    orden: tareaRip.orden,
                    id_maquina: maquinaRip.id,
                    maquina_nombre: maquinaRip.nombre,
                    prioridad: maquina.prioridad,
                    id_maquina_relacionada: maquinaRip.id_maquina_relacionada,
                    product_quantity,
                    param1: maquina.param1 ?? null
                  },
                  type: QueryTypes.INSERT
                }
              );
            }
          }
        }
      }
    }

    console.log('Tareas insertadas correctamente');
    res.status(204).end();

  } catch (error) {
    console.error('Error al insertar tareas automáticamente:', error);
    res.status(500).json({ error: 'Error al insertar tareas.' });
  }
});

psWorkflowTareasRouter.get('/resumen_maquina', async (req, res) => {
  try {
    const { id_maquina, fecha_desde, fecha_hasta } = req.query;

    const rows = await sequelize.query(
      `SELECT
          wt.id AS trabajo_id,
          DATE(wt.fecha_realizacion) AS fecha,
          wt.id_tarea,
          wt.id_order_detail,
          wt.id_order,
          wt.id_operario,
          wd.reference AS pedido,
          o.nombre AS operario_nombre,
          mat.nombre AS material,
          wt.fecha_realizacion,
          ROW_NUMBER() OVER (PARTITION BY wd.id_order ORDER BY wd.id_order_detail ASC) AS numero_trabajo
       FROM ps_workflow_tareas wt
       JOIN ps_workflow_data wd ON wd.id_order = wt.id_order AND wd.id_order_detail = wt.id_order_detail AND wd.id_value = wt.id_value
       JOIN operario o ON o.id = wt.id_operario
       JOIN ps_workflow_material wmat ON wmat.id_value = wd.id_value
       JOIN material mat ON wmat.id_material = mat.id
       WHERE wt.estado = 4
       AND wt.id_maquina = :id_maquina
       AND DATE(wt.fecha_realizacion) BETWEEN :fecha_desde AND :fecha_hasta
       ORDER BY wt.fecha_realizacion ASC`,
      {
        type: QueryTypes.SELECT,
        replacements: { id_maquina, fecha_desde, fecha_hasta },
      }
    );

    const resumenPorDia: any[] = [];
    const resumenMap: any = {};

    rows.forEach((row: any) => {
      if (!resumenMap[row.fecha]) {
        resumenMap[row.fecha] = {
          fecha: row.fecha,
          trabajos: [],
          filas: []
        };
        resumenPorDia.push(resumenMap[row.fecha]);
      }

      resumenMap[row.fecha].trabajos.push({
        nombre: `${row.id_order_detail}-${row.numero_trabajo}` // para el timeline
      });

      resumenMap[row.fecha].filas.push({
        pedido: row.pedido,
        articulo: `${row.id_order_detail}-${row.numero_trabajo}`,
        material: row.material,
        operario: row.operario_nombre,
        fechaRealizacion: row.fecha,
        id_order: row.id_order,
        id_tarea: row.id_tarea,
        id_operario: row.id_operario,
        id_order_detail: row.id_order_detail
      });
    });

    res.json(resumenPorDia);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Error al obtener resumen de máquina' });
  }
});

psWorkflowTareasRouter.get('/resumen_operario', async (req, res) => {
  try {
    const { id_operario, fecha_desde, fecha_hasta } = req.query;

    const rows = await sequelize.query(
      `SELECT
          wt.id AS trabajo_id,
          DATE(wt.fecha_realizacion) AS fecha,
          wt.id_tarea,
          wt.id_order_detail,
          wt.id_order,
          wt.id_operario,
          wd.reference AS pedido,
          o.nombre AS operario_nombre,
          mat.nombre AS material,
          maq.nombre AS maquina,
          wt.fecha_realizacion,
          ROW_NUMBER() OVER (PARTITION BY wd.id_order ORDER BY wd.id_order_detail ASC) AS numero_trabajo
        FROM ps_workflow_tareas wt
        JOIN ps_workflow_data wd ON wd.id_order = wt.id_order AND wd.id_order_detail = wt.id_order_detail AND wd.id_value = wt.id_value
        JOIN operario o ON o.id = wt.id_operario
        JOIN ps_workflow_material wmat ON wmat.id_value = wd.id_value
        JOIN material mat ON wmat.id_material = mat.id
        JOIN ps_workflow_maquinas wmaq ON wmaq.id_value = wd.id_value
        JOIN maquina maq ON maq.id = wmaq.id_maquina
        WHERE wt.estado = 4
        AND wt.id_operario = :id_operario
        AND DATE(wt.fecha_realizacion) BETWEEN :fecha_desde AND :fecha_hasta
        ORDER BY wt.fecha_realizacion ASC;`,
      {
        type: QueryTypes.SELECT,
        replacements: { id_operario, fecha_desde, fecha_hasta },
      }
    );

    const resumenPorDia: any[] = [];
    const resumenMap: any = {};

    rows.forEach((row: any) => {
      if (!resumenMap[row.fecha]) {
        resumenMap[row.fecha] = {
          fecha: row.fecha,
          trabajos: [],
          filas: []
        };
        resumenPorDia.push(resumenMap[row.fecha]);
      }

      resumenMap[row.fecha].trabajos.push({
        nombre: `${row.id_order_detail}-${row.numero_trabajo}`
      });

      resumenMap[row.fecha].filas.push({
        pedido: row.pedido,
        articulo: `${row.id_order_detail}-${row.numero_trabajo}`,
        material: row.material,
        operario: row.operario_nombre,
        maquina: row.maquina,
        fechaRealizacion: row.fecha,
        id_order: row.id_order,
        id_tarea: row.id_tarea,
        id_operario: row.id_operario,
        id_order_detail: row.id_order_detail
      });
    });

    res.json(resumenPorDia);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Error al obtener resumen de operario' });
  }
});

// Obtener un registro de tarea del workflow
psWorkflowTareasRouter.get('/:id', async (req: Request, res: Response) => {
  const { id } = req.params;
  try {
    const tarea = await PsWorkflowTareas.findByPk(id);
    if (!tarea) {
      return res.status(404).json({ error: 'Tarea no encontrada' });
    }
    res.json(tarea);
  } catch (error) {
    res.status(500).json({ error: 'Error al obtener la tarea' });
  }
});

// Crear una nueva tarea para el workflow
psWorkflowTareasRouter.post('/', async (req: Request, res: Response) => {
  const {
    idOrder,
    idOrderDetail,
    idValue,
    orden,
    tareaNombre,
    descripcion,
    maquinaNombre,
    prioridad,
    idMaquina,
    idTarea,
    idMaquinaRelacionada,
    param1
  } = req.body;

  try {
    const nuevaTarea = await PsWorkflowTareas.create({
      idOrder,
      idOrderDetail,
      idValue,
      orden,
      tareaNombre,
      descripcion,
      maquinaNombre,
      prioridad,
      idMaquina,
      idTarea,
      idMaquinaRelacionada,
      param1
    });
    res.status(201).json(nuevaTarea);
  } catch (error) {
    res.status(500).json({ error: 'Error al crear la nueva tarea del workflow' });
  }
});

// Actualizar una tarea del workflow existente
psWorkflowTareasRouter.put('/:id', async (req: Request, res: Response) => {
  const { id } = req.params;
  const updateData = req.body;

  try {
    const tarea = await PsWorkflowTareas.findByPk(id);
    if (!tarea) {
      return res.status(404).json({ error: 'Tarea no encontrada' });
    }

    await tarea.update(updateData);
    res.json(tarea);
  } catch (error) {
    res.status(500).json({ error: 'Error al actualizar la tarea' });
  }
});

// Eliminar una tarea por ID
psWorkflowTareasRouter.delete('/:id', async (req: Request, res: Response) => {
  const { id } = req.params;

  try {
    const tarea = await PsWorkflowTareas.findByPk(id);
    if (!tarea) {
      return res.status(404).json({ error: 'Tarea no encontrada' });
    }

    await tarea.destroy();
    res.json({ message: 'Tarea eliminada correctamente' });
  } catch (error) {
    res.status(500).json({ error: 'Error al eliminar la tarea del workflow' });
  }
});

export default psWorkflowTareasRouter;