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

// Get all measuring instruments
exports.getAll = asyncHandler(async (req, res) => {
  const {
    page = 1,
    limit = 25,
    search = '',
    company_id,
    plant_id,
    status,
    location,
    calibration_status // 'due', 'upcoming', 'current'
  } = 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 (status) where.status = status;
  if (location) where.location = { [Op.like]: `%${location}%` };

  // Handle calibration status filter
  if (calibration_status) {
    const today = new Date();
    const next30Days = new Date();
    next30Days.setDate(today.getDate() + 30);

    if (calibration_status === 'due') {
      where.due_date = { [Op.lt]: today };
    } else if (calibration_status === 'upcoming') {
      where.due_date = { [Op.between]: [today, next30Days] };
    } else if (calibration_status === 'current') {
      where.due_date = { [Op.gte]: next30Days };
    }
  }

  if (search) {
    where[Op.or] = [
      { description: { [Op.like]: `%${search}%` } },
      { instrument_id: { [Op.like]: `%${search}%` } },
      { make: { [Op.like]: `%${search}%` } },
      { serial_no: { [Op.like]: `%${search}%` } },
      { location: { [Op.like]: `%${search}%` } }
    ];
  }

  const { count, rows } = await db.MeasuringInstrument.findAndCountAll({
    where,
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username', 'email']
      }
    ],
    limit: parseInt(limit),
    offset: parseInt(offset),
    order: [['instrument_id', 'ASC']],
    distinct: true
  });

  return sendSuccess(
    res,
    'Measuring Instruments 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 instrument = await db.MeasuringInstrument.findByPk(id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.User,
        as: 'creator',
        attributes: ['id', 'username', 'email']
      },
      {
        model: db.User,
        as: 'updater',
        attributes: ['id', 'username', 'email']
      }
    ]
  });

  if (!instrument) {
    return sendError(res, 'Measuring Instrument not found', 404);
  }

  return sendSuccess(res, 'Measuring Instrument fetched successfully', instrument);
});

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

  // Check if instrument_id already exists
  const existing = await db.MeasuringInstrument.findOne({
    where: { instrument_id: req.body.instrument_id }
  });

  if (existing) {
    return sendError(res, 'Instrument ID already exists', 400);
  }

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

  const createdInstrument = await db.MeasuringInstrument.findByPk(instrument.id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      }
    ]
  });

  return sendSuccess(res, 'Measuring Instrument created successfully', createdInstrument, null, 201);
});

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

  const instrument = await db.MeasuringInstrument.findByPk(id);

  if (!instrument) {
    return sendError(res, 'Measuring Instrument not found', 404);
  }

  // Check if instrument_id is being changed and if it already exists
  if (req.body.instrument_id && req.body.instrument_id !== instrument.instrument_id) {
    const existing = await db.MeasuringInstrument.findOne({
      where: { 
        instrument_id: req.body.instrument_id,
        id: { [Op.ne]: id }
      }
    });

    if (existing) {
      return sendError(res, 'Instrument ID already exists', 400);
    }
  }

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

  const updatedInstrument = await db.MeasuringInstrument.findByPk(id, {
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      }
    ]
  });

  return sendSuccess(res, 'Measuring Instrument updated successfully', updatedInstrument);
});

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

  const instrument = await db.MeasuringInstrument.findByPk(id);

  if (!instrument) {
    return sendError(res, 'Measuring Instrument not found', 404);
  }

  await instrument.destroy();

  return sendSuccess(res, 'Measuring Instrument deleted successfully', null);
});

// Get instruments by location
exports.getByLocation = asyncHandler(async (req, res) => {
  const { location } = req.params;

  const instruments = await db.MeasuringInstrument.findAll({
    where: { 
      location: { [Op.like]: `%${location}%` },
      status: 'GOOD'
    },
    order: [['instrument_id', 'ASC']]
  });

  return sendSuccess(res, 'Measuring Instruments fetched successfully', instruments);
});

// Get calibration due report
exports.getCalibrationDueReport = asyncHandler(async (req, res) => {
  const { company_id, plant_id, days = 30 } = req.query;

  const today = new Date();
  const futureDate = new Date();
  futureDate.setDate(today.getDate() + parseInt(days));

  const where = {
    due_date: { [Op.between]: [today, futureDate] }
  };

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

  const instruments = await db.MeasuringInstrument.findAll({
    where,
    include: [
      {
        model: db.Company,
        as: 'company',
        attributes: ['id', 'code', 'name']
      },
      {
        model: db.Plant,
        as: 'plant',
        attributes: ['id', 'code', 'name']
      }
    ],
    order: [['due_date', 'ASC']]
  });

  return sendSuccess(res, 'Calibration due report fetched successfully', instruments);
});
