import { Request, Response } from 'express';
import { encrypt } from '../../../helpers/tokenizer';
import { logActivity } from '../../../helpers/activityLog.helper';
import { buildTextSearch, parsePagination, paginationMeta } from '../../../helpers/query.helper';
import User from '../schema/user.schema';
import { Roles } from '../enums/roles.enum';

export class UsersAdminController {
  static async list(req: Request, res: Response) {
    try {
      const { page, limit, skip } = parsePagination(req, 10);
      const filter: Record<string, unknown> = { role: { $in: [Roles.ADMIN, Roles.RECEPTIONIST] } };

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

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

      const [response, total] = await Promise.all([
        User.find(filter).select('-password -otp').sort({ createdAt: -1 }).skip(skip).limit(limit),
        User.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 { email, password, firstname, lastname, role } = req.body;
      if (!email || !password) {
        return res.status(400).json({ success: false, message: 'Email and password required' });
      }

      const encryptedPassword = await encrypt.encryptpass(password);
      const user = await User.create({
        email: String(email).trim().toLowerCase(),
        password: encryptedPassword,
        firstname,
        lastname,
        role: role || Roles.RECEPTIONIST,
        status: 'ACTIVE',
      });

      const safe = user.toObject();
      delete safe.password;
      delete safe.otp;

      await logActivity(req, 'CREATE', 'STAFF_USER', user._id.toString(), user.email);

      return res.status(201).json({ success: true, response: safe });
    } catch (e: any) {
      if (e?.code === 11000) {
        return res.status(409).json({ success: false, message: 'Email already exists' });
      }
      return res.status(500).json({ success: false, message: 'System error' });
    }
  }

  static async update(req: Request, res: Response) {
    try {
      const updates = { ...req.body };
      delete updates.password;

      if (updates.email) updates.email = String(updates.email).trim().toLowerCase();
      if (updates.password) {
        updates.password = await encrypt.encryptpass(updates.password);
      }

      const user = await User.findByIdAndUpdate(req.params.id, updates, { new: true }).select(
        '-password -otp'
      );
      if (!user) return res.status(404).json({ success: false, message: 'Not found' });

      await logActivity(req, 'UPDATE', 'STAFF_USER', user._id.toString(), user.email);

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

  static async suspend(req: Request, res: Response) {
    try {
      const user = await User.findByIdAndUpdate(
        req.params.id,
        { status: 'DEACTIVE' },
        { new: true }
      ).select('-password -otp');
      if (!user) return res.status(404).json({ success: false, message: 'Not found' });

      await logActivity(req, 'SUSPEND', 'STAFF_USER', user._id.toString(), user.email);

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

  static async activate(req: Request, res: Response) {
    try {
      const user = await User.findByIdAndUpdate(
        req.params.id,
        { status: 'ACTIVE' },
        { new: true }
      ).select('-password -otp');
      if (!user) return res.status(404).json({ success: false, message: 'Not found' });

      await logActivity(req, 'ACTIVATE', 'STAFF_USER', user._id.toString(), user.email);

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

  static async remove(req: Request, res: Response) {
    try {
      const currentId = req['staffUser']?._id?.toString();
      if (currentId === req.params.id) {
        return res.status(400).json({ success: false, message: 'Cannot delete your own account' });
      }

      const user = await User.findById(req.params.id);
      if (!user) return res.status(404).json({ success: false, message: 'Not found' });

      await User.findByIdAndDelete(req.params.id);
      await logActivity(req, 'DELETE', 'STAFF_USER', req.params.id, user.email);

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