const db = require('../models');
const { sendSuccess, sendError } = require('../utils/response');
const asyncHandler = require('../middlewares/asyncHandler');
const { Op } = require('sequelize');

// Get all fabricators
exports.getAll = asyncHandler(async (req, res) => {
  const {
    page = 1,
    limit = 25,
    search = '',
    company_id,
    status
  } = req.query;

  const offset = (page - 1) * limit;
  const where = {};

  if (company_id) where.company_id = company_id;
  if (status) where.status = status;

  if (search) {
    where[Op.or] = [
      { fabricator_code: { [Op.like]: `%${search}%` } },
      { fabricator_name: { [Op.like]: `%${search}%` } },
      { contact_number: { [Op.like]: `%${search}%` } },
      { email: { [Op.like]: `%${search}%` } },
      { certification_no: { [Op.like]: `%${search}%` } }
    ];
  }

  const { count, rows } = await db.Fabricator.findAndCountAll({
    where,
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Employee,
        as: 'employee',
        attributes: ['id', 'employee_code', 'first_name', 'last_name']
      },
      {
        model: db.User,
        as: 'user',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username']
      }
    ],
    limit: parseInt(limit),
    offset: parseInt(offset),
    order: [['fabricator_code', 'ASC']],
    distinct: true
  });

  return sendSuccess(
    res,
    'Fabricators fetched successfully',
    {
      items: rows,
      pagination: {
        total: count,
        page: parseInt(page),
        limit: parseInt(limit),
        pages: Math.ceil(count / limit)
      }
    }
  );
});

// Get by ID
exports.getById = asyncHandler(async (req, res) => {
  const { id } = req.params;

  const fabricator = await db.Fabricator.findByPk(id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Employee,
        as: 'employee',
        attributes: ['id', 'employee_code', 'first_name', 'last_name']
      },
      {
        model: db.User,
        as: 'user',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username']
      },
      {
        model: db.User,
        as: 'updater',
        attributes: ['id', 'username']
      }
    ]
  });

  if (!fabricator) {
    return sendError(res, 'Fabricator not found', 404);
  }

  return sendSuccess(res, 'Fabricator fetched successfully', fabricator);
});

// Create
exports.create = asyncHandler(async (req, res) => {
  const userId = req.user?.id;

  // Check for duplicate fabricator code
  const existing = await db.Fabricator.findOne({
    where: {
      company_id: req.body.company_id,
      fabricator_code: req.body.fabricator_code
    }
  });

  if (existing) {
    return sendError(res, 'Fabricator code already exists for this company', 400);
  }

  const fabricator = await db.Fabricator.create({
    ...req.body,
    created_by: userId,
    updated_by: userId
  });

  const createdFabricator = await db.Fabricator.findByPk(fabricator.id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Employee,
        as: 'employee',
        attributes: ['id', 'employee_code', 'first_name', 'last_name']
      },
      {
        model: db.User,
        as: 'user',
        attributes: ['id', 'username', 'email']
      }
    ]
  });

  return sendSuccess(res, 'Fabricator created successfully', createdFabricator, null, 201);
});

// Update
exports.update = asyncHandler(async (req, res) => {
  const { id } = req.params;
  const userId = req.user?.id;

  const fabricator = await db.Fabricator.findByPk(id);

  if (!fabricator) {
    return sendError(res, 'Fabricator not found', 404);
  }

  // Check for duplicate fabricator code if code is being changed
  if (req.body.fabricator_code && req.body.fabricator_code !== fabricator.fabricator_code) {
    const existing = await db.Fabricator.findOne({
      where: {
        company_id: req.body.company_id || fabricator.company_id,
        fabricator_code: req.body.fabricator_code,
        id: { [Op.ne]: id }
      }
    });

    if (existing) {
      return sendError(res, 'Fabricator code already exists for this company', 400);
    }
  }

  await fabricator.update({
    ...req.body,
    updated_by: userId
  });

  const updatedFabricator = await db.Fabricator.findByPk(id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Employee,
        as: 'employee',
        attributes: ['id', 'employee_code', 'first_name', 'last_name']
      },
      {
        model: db.User,
        as: 'user',
        attributes: ['id', 'username', 'email']
      }
    ]
  });

  return sendSuccess(res, 'Fabricator updated successfully', updatedFabricator);
});

// Delete
exports.delete = asyncHandler(async (req, res) => {
  const { id } = req.params;

  const fabricator = await db.Fabricator.findByPk(id);

  if (!fabricator) {
    return sendError(res, 'Fabricator not found', 404);
  }

  await fabricator.destroy();

  return sendSuccess(res, 'Fabricator deleted successfully');
});

module.exports = exports;
