const { validationResult } = require("express-validator");
const prisma = require("../models/prisma");
const logger = require("../utils/logger");

const generateProjectCode = async () => {
  const year = new Date().getFullYear();
  const count = await prisma.project.count();
  return "PRY-" + year + "-" + String(count + 1).padStart(3, "0");
};

const getAll = async (req, res) => {
  try {
    const { status, category, search, page = 1, limit = 20 } = req.query;
    const where = {};
    if (status) where.status = status;
    if (category) where.category = category;
    if (search) where.OR = [{ name: { contains: search, mode: "insensitive" } }, { code: { contains: search, mode: "insensitive" } }];

    // COLABORADOR solo ve proyectos donde es miembro
    if (req.user.role === "COLABORADOR" || req.user.role === "JEFE_AREA") {
      where.members = { some: { userId: req.user.id } };
    }

    const [projects, total] = await Promise.all([
      prisma.project.findMany({
        where,
        skip: (parseInt(page) - 1) * parseInt(limit),
        take: parseInt(limit),
        orderBy: { createdAt: "desc" },
        include: {
          members: { include: { user: { select: { id: true, firstName: true, lastName: true, avatarUrl: true } } } },
          _count: { select: { tasks: true } },
        },
      }),
      prisma.project.count({ where }),
    ]);

    res.json({ data: projects, total, page: parseInt(page), limit: parseInt(limit), totalPages: Math.ceil(total / parseInt(limit)) });
  } catch (error) {
    logger.error("Error obteniendo proyectos:", error);
    res.status(500).json({ error: "Error obteniendo proyectos" });
  }
};

const getById = async (req, res) => {
  try {
    const project = await prisma.project.findUnique({
      where: { id: req.params.id },
      include: {
        members: { include: { user: { select: { id: true, firstName: true, lastName: true, role: true, avatarUrl: true } } } },
        tasks: { where: { parentId: null }, include: { children: true, assignee: { select: { id: true, firstName: true, lastName: true } } } },
      },
    });
    if (!project) return res.status(404).json({ error: "Proyecto no encontrado" });
    res.json(project);
  } catch (error) {
    res.status(500).json({ error: "Error obteniendo proyecto" });
  }
};

const ALLOWED_PROJECT_CREATE_FIELDS = [
  'name', 'description', 'type', 'category', 'client',
  'startDate', 'plannedEndDate', 'budget', 'priority',
  'status', 'currentPhase', 'methodology', 'tags',
];

const ALLOWED_PROJECT_UPDATE_FIELDS = [
  'name', 'description', 'type', 'category', 'client',
  'startDate', 'plannedEndDate', 'budget', 'priority',
  'status', 'currentPhase', 'methodology', 'ragStatus',
  'progressPct', 'tags',
];

const pickFields = (obj, allowed) =>
  Object.fromEntries(Object.entries(obj).filter(([k]) => allowed.includes(k)));

const create = async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });

  try {
    const code = await generateProjectCode();
    const safeData = pickFields(req.body, ALLOWED_PROJECT_CREATE_FIELDS);
    const project = await prisma.project.create({
      data: { ...safeData, code, createdBy: req.user.id },
    });

    // Agregar al creador como miembro GERENTE por defecto
    await prisma.projectMember.create({
      data: { projectId: project.id, userId: req.user.id, role: "GERENTE" },
    });

    res.status(201).json(project);
  } catch (error) {
    logger.error("Error creando proyecto:", error);
    res.status(500).json({ error: "Error creando proyecto" });
  }
};

const update = async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });

  try {
    const safeData = pickFields(req.body, ALLOWED_PROJECT_UPDATE_FIELDS);
    const project = await prisma.project.update({ where: { id: req.params.id }, data: safeData });
    res.json(project);
  } catch (error) {
    if (error.code === "P2025") return res.status(404).json({ error: "Proyecto no encontrado" });
    res.status(500).json({ error: "Error actualizando proyecto" });
  }
};

module.exports = { getAll, getById, create, update };
