import { Request, Response } from 'express';
import Employee from '../schema/employee.schema';
import { logActivity } from '../../../helpers/activityLog.helper';
import { buildTextSearch, parsePagination, paginationMeta } from '../../../helpers/query.helper';

function employeeLabel(employee: { firstname?: string; lastname?: string }) {
  return `${employee.firstname || ''} ${employee.lastname || ''}`.trim();
}

export class EmployeesController {
  static async list(req: Request, res: Response) {
    try {
      const { page, limit, skip } = parsePagination(req, 10);
      const filter: Record<string, unknown> = {};

      const status = String(req.query.status || '').trim();
      if (status) filter.status = status;

      const search = buildTextSearch(
        ['firstname', 'lastname', 'email', 'phone', 'specialty', 'notes'],
        String(req.query.q || '')
      );
      if (search.$or) Object.assign(filter, search);

      const [response, total] = await Promise.all([
        Employee.find(filter).sort({ firstname: 1, lastname: 1 }).skip(skip).limit(limit),
        Employee.countDocuments(filter),
      ]);

      return res.status(200).json({
        success: true,
        response,
        pagination: paginationMeta(page, limit, total),
      });
    } catch {
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }

  static async create(req: Request, res: Response) {
    try {
      const firstname = String(req.body?.firstname || '').trim();
      const lastname = String(req.body?.lastname || '').trim();

      if (!firstname || !lastname) {
        return res.status(400).json({ success: false, message: 'First and last name are required' });
      }

      const employee = await Employee.create({
        firstname,
        lastname,
        phone: String(req.body?.phone || '').trim(),
        email: String(req.body?.email || '').trim().toLowerCase(),
        specialty: String(req.body?.specialty || '').trim(),
        notes: String(req.body?.notes || '').trim(),
        status: req.body?.status === 'INACTIVE' ? 'INACTIVE' : 'ACTIVE',
      });

      await logActivity(req, 'CREATE', 'EMPLOYEE', employee._id.toString(), employeeLabel(employee));

      return res.status(201).json({ success: true, response: employee });
    } catch {
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }

  static async update(req: Request, res: Response) {
    try {
      const updates: Record<string, unknown> = {};

      if (req.body?.firstname !== undefined) updates.firstname = String(req.body.firstname).trim();
      if (req.body?.lastname !== undefined) updates.lastname = String(req.body.lastname).trim();
      if (req.body?.phone !== undefined) updates.phone = String(req.body.phone).trim();
      if (req.body?.email !== undefined) updates.email = String(req.body.email).trim().toLowerCase();
      if (req.body?.specialty !== undefined) updates.specialty = String(req.body.specialty).trim();
      if (req.body?.notes !== undefined) updates.notes = String(req.body.notes).trim();
      if (req.body?.status !== undefined) {
        updates.status = req.body.status === 'INACTIVE' ? 'INACTIVE' : 'ACTIVE';
      }

      const employee = await Employee.findByIdAndUpdate(req.params.id, updates, {
        new: true,
        runValidators: true,
      });

      if (!employee) {
        return res.status(404).json({ success: false, message: 'Employee not found' });
      }

      await logActivity(req, 'UPDATE', 'EMPLOYEE', employee._id.toString(), employeeLabel(employee));

      return res.status(200).json({ success: true, response: employee });
    } catch {
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }

  static async deactivate(req: Request, res: Response) {
    try {
      const employee = await Employee.findByIdAndUpdate(
        req.params.id,
        { status: 'INACTIVE' },
        { new: true }
      );

      if (!employee) {
        return res.status(404).json({ success: false, message: 'Employee not found' });
      }

      await logActivity(req, 'DEACTIVATE', 'EMPLOYEE', employee._id.toString(), employeeLabel(employee));

      return res.status(200).json({ success: true, response: employee });
    } catch {
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }

  static async activate(req: Request, res: Response) {
    try {
      const employee = await Employee.findByIdAndUpdate(
        req.params.id,
        { status: 'ACTIVE' },
        { new: true }
      );

      if (!employee) {
        return res.status(404).json({ success: false, message: 'Employee not found' });
      }

      await logActivity(req, 'ACTIVATE', 'EMPLOYEE', employee._id.toString(), employeeLabel(employee));

      return res.status(200).json({ success: true, response: employee });
    } catch {
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }

  static async remove(req: Request, res: Response) {
    try {
      const employee = await Employee.findById(req.params.id);
      if (!employee) {
        return res.status(404).json({ success: false, message: 'Employee not found' });
      }

      await Employee.findByIdAndDelete(req.params.id);
      await logActivity(req, 'DELETE', 'EMPLOYEE', req.params.id, employeeLabel(employee));

      return res.status(200).json({ success: true, message: 'Employee removed' });
    } catch {
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }
}
