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

// Generate IIR Number
const generateIIRNumber = async (companyId, fiscalYearId = null) => {
  try {
    const generatedNumber = await generateNextNumber(companyId, 'INCOMING_INSPECTION_REPORT', null, fiscalYearId);
    return generatedNumber;
  } catch (error) {
    console.warn('Number format not found, using fallback method:', error.message);
    const today = new Date();
    const year = today.getFullYear();
    const prefix = `IIR${year}`;
    
    const lastIIR = await db.IncomingInspectionReport.findOne({
      where: {
        company_id: companyId,
        iir_no: { [Op.like]: `${prefix}%` }
      },
      order: [['iir_no', 'DESC']]
    });

    let sequence = 1;
    if (lastIIR) {
      const lastSequence = parseInt(lastIIR.iir_no.slice(-4)) || 0;
      sequence = lastSequence + 1;
    }

    return `${prefix}${sequence.toString().padStart(4, '0')}`;
  }
};

// Get all Incoming Inspection Reports
exports.getAll = asyncHandler(async (req, res) => {
  const {
    page = 1,
    limit = 25,
    search = '',
    company_id,
    plant_id,
    fiscal_year_id,
    supplier_id,
    status,
    inspection_status,
    date_from,
    date_to
  } = req.query;

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

  if (company_id) where.company_id = company_id;
  if (plant_id) where.plant_id = plant_id;
  if (fiscal_year_id) where.fiscal_year_id = fiscal_year_id;
  if (supplier_id) where.supplier_id = supplier_id;
  if (status) where.status = status;
  if (inspection_status) where.inspection_status = inspection_status;

  if (date_from && date_to) {
    where.iir_date = { [Op.between]: [date_from, date_to] };
  } else if (date_from) {
    where.iir_date = { [Op.gte]: date_from };
  } else if (date_to) {
    where.iir_date = { [Op.lte]: date_to };
  }

  if (search) {
    where[Op.or] = [
      { iir_no: { [Op.like]: `%${search}%` } },
      { supplier_name: { [Op.like]: `%${search}%` } },
      { part_name: { [Op.like]: `%${search}%` } },
      { part_no: { [Op.like]: `%${search}%` } },
      { dc_no: { [Op.like]: `%${search}%` } }
    ];
  }

  const { count, rows } = await db.IncomingInspectionReport.findAndCountAll({
    where,
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.FiscalYear,
        as: 'fiscalYear',
        attributes: ['id', 'fiscal_year', 'start_date', 'end_date']
      },
      {
        model: db.BusinessPartner,
        as: 'supplier',
        attributes: ['id', 'bp_number', 'name', 'legal_name']
      },
      {
        model: db.Material,
        as: 'material',
        attributes: ['id', 'material_code', 'material_description']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username', 'email']
      }
    ],
    limit: parseInt(limit),
    offset: parseInt(offset),
    order: [['iir_date', 'DESC'], ['id', 'DESC']],
    distinct: true
  });

  return sendSuccess(
    res,
    'Incoming Inspection Reports 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 report = await db.IncomingInspectionReport.findByPk(id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.FiscalYear,
        as: 'fiscalYear',
        attributes: ['id', 'fiscal_year', 'start_date', 'end_date']
      },
      {
        model: db.BusinessPartner,
        as: 'supplier',
        attributes: ['id', 'bp_number', 'name', 'legal_name']
      },
      {
        model: db.Material,
        as: 'material',
        attributes: ['id', 'material_code', 'material_description']
      },
      {
        model: db.PurchaseOrder,
        as: 'purchaseOrder',
        attributes: ['id', 'po_number', 'po_date']
      },
      {
        model: db.User,
        as: 'inspector',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.User,
        as: 'approver',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.User,
        as: 'updater',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.IncomingInspectionReportDetail,
        as: 'details',
        include: [
          {
            model: db.MeasuringInstrument,
            as: 'measuringInstrument',
            attributes: ['id', 'instrument_id', 'description']
          }
        ],
        order: [['line_no', 'ASC']]
      }
    ]
  });

  if (!report) {
    return sendError(res, 'Incoming Inspection Report not found', 404);
  }

  return sendSuccess(res, 'Incoming Inspection Report fetched successfully', report);
});

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

  try {
    const { details, ...headerData } = req.body;

    // Generate IIR Number if not provided
    if (!headerData.iir_no) {
      headerData.iir_no = await generateIIRNumber(
        headerData.company_id,
        headerData.fiscal_year_id
      );
    }

    // Create header
    const report = await db.IncomingInspectionReport.create({
      ...headerData,
      created_by: userId,
      updated_by: userId
    }, { transaction });

    // Create detail lines if provided
    if (details && Array.isArray(details) && details.length > 0) {
      const detailsWithIIRId = details.map((detail, index) => ({
        ...detail,
        iir_id: report.id,
        line_no: detail.line_no || (index + 1)
      }));

      await db.IncomingInspectionReportDetail.bulkCreate(detailsWithIIRId, { transaction });
    }

    await transaction.commit();

    // Fetch the created report with all associations
    const createdReport = await db.IncomingInspectionReport.findByPk(report.id, {
      include: [
        {
          model: db.Company,
          as: 'company',
          attributes: ['id', 'code', 'name']
        },
        {
          model: db.Plant,
          as: 'plant',
          attributes: ['id', 'code', 'name']
        },
        {
          model: db.FiscalYear,
          as: 'fiscalYear',
          attributes: ['id', 'fiscal_year']
        },
        {
          model: db.BusinessPartner,
          as: 'supplier',
          attributes: ['id', 'bp_number', 'name']
        },
        {
          model: db.Material,
          as: 'material',
          attributes: ['id', 'material_code', 'material_description']
        },
        {
          model: db.IncomingInspectionReportDetail,
          as: 'details',
          include: [
            {
              model: db.MeasuringInstrument,
              as: 'measuringInstrument',
              attributes: ['id', 'instrument_id', 'description']
            }
          ],
          order: [['line_no', 'ASC']]
        }
      ]
    });

    return sendSuccess(res, 'Incoming Inspection Report created successfully', createdReport, null, 201);
  } catch (error) {
    await transaction.rollback();
    throw error;
  }
});

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

  try {
    const report = await db.IncomingInspectionReport.findByPk(id);

    if (!report) {
      await transaction.rollback();
      return sendError(res, 'Incoming Inspection Report not found', 404);
    }

    const { details, ...headerData } = req.body;

    // Update header
    await report.update({
      ...headerData,
      updated_by: userId
    }, { transaction });

    // Update detail lines if provided
    if (details && Array.isArray(details)) {
      // Delete existing details
      await db.IncomingInspectionReportDetail.destroy({
        where: { iir_id: id },
        transaction
      });

      // Create new details
      if (details.length > 0) {
        const detailsWithIIRId = details.map((detail, index) => ({
          ...detail,
          iir_id: id,
          line_no: detail.line_no || (index + 1)
        }));

        await db.IncomingInspectionReportDetail.bulkCreate(detailsWithIIRId, { transaction });
      }
    }

    await transaction.commit();

    // Fetch updated report
    const updatedReport = await db.IncomingInspectionReport.findByPk(id, {
      include: [
        {
          model: db.Company,
          as: 'company',
          attributes: ['id', 'code', 'name']
        },
        {
          model: db.Plant,
          as: 'plant',
          attributes: ['id', 'code', 'name']
        },
        {
          model: db.FiscalYear,
          as: 'fiscalYear',
          attributes: ['id', 'fiscal_year']
        },
        {
          model: db.BusinessPartner,
          as: 'supplier',
          attributes: ['id', 'bp_number', 'name']
        },
        {
          model: db.Material,
          as: 'material',
          attributes: ['id', 'material_code', 'material_description']
        },
        {
          model: db.IncomingInspectionReportDetail,
          as: 'details',
          include: [
            {
              model: db.MeasuringInstrument,
              as: 'measuringInstrument',
              attributes: ['id', 'instrument_id', 'description']
            }
          ],
          order: [['line_no', 'ASC']]
        }
      ]
    });

    return sendSuccess(res, 'Incoming Inspection Report updated successfully', updatedReport);
  } catch (error) {
    await transaction.rollback();
    throw error;
  }
});

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

  try {
    const report = await db.IncomingInspectionReport.findByPk(id);

    if (!report) {
      await transaction.rollback();
      return sendError(res, 'Incoming Inspection Report not found', 404);
    }

    // Delete details (will cascade, but explicit for clarity)
    await db.IncomingInspectionReportDetail.destroy({
      where: { iir_id: id },
      transaction
    });

    // Delete header
    await report.destroy({ transaction });

    await transaction.commit();

    return sendSuccess(res, 'Incoming Inspection Report deleted successfully', null);
  } catch (error) {
    await transaction.rollback();
    throw error;
  }
});

// Get reports by supplier
exports.getBySupplier = asyncHandler(async (req, res) => {
  const { supplierId } = req.params;
  const { page = 1, limit = 25 } = req.query;

  const offset = (page - 1) * limit;

  const { count, rows } = await db.IncomingInspectionReport.findAndCountAll({
    where: { supplier_id: supplierId },
    include: [
      {
        model: db.Material,
        as: 'material',
        attributes: ['id', 'material_code', 'material_description']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username', 'email']
      }
    ],
    limit: parseInt(limit),
    offset: parseInt(offset),
    order: [['iir_date', 'DESC']],
    distinct: true
  });

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