import { Request, Response, NextFunction } from 'express';
import adminService from '../../../application/services/AdminService';
import { authMiddleware, adminOnly } from '../../../middleware/auth';
import { singleUpload, handleUploadError } from '../../middleware/upload';
import { validateStatusUpdate, validateDocumentVerify, validateChatSend, validateSettings } from '../../validators/adminValidator';

export class AdminController {
  static getStats = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.getStats();
      return res.status(200).json({ success: true, data });
    } catch (error) {
      next(error);
    }
  };

  static listStudents = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { search, role, page = 1, limit = 10 } = req.query;
      const result = await adminService.listStudents({ search: search as string, role: role as string, page: Number(page), limit: Number(limit) });
      return res.status(200).json({ success: true, data: result.data, total: result.total });
    } catch (error) {
      next(error);
    }
  };

  static getDetail = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.getDetail(Number(req.params.id));
      return res.status(200).json({ success: true, data });
    } catch (error) {
      next(error);
    }
  };

  static updateStatus = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.updateStatus(Number(req.params.id), req.body.status, req.body.adminComment, req.user.id);
      return res.status(200).json({ success: true, data, message: 'Status diperbarui' });
    } catch (error) {
      next(error);
    }
  };

  static listDocuments = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { type, verified, search, page = 1, limit = 10 } = req.query;
      const result = await adminService.listDocuments({ type: type as string, verified: verified === 'true' ? true : verified === 'false' ? false : undefined, search: search as string, page: Number(page), limit: Number(limit) });
      return res.status(200).json({ success: true, data: result.data, total: result.total });
    } catch (error) {
      next(error);
    }
  };

  static verifyDocument = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.verifyDocument(Number(req.params.id), req.body.isVerified, req.body.adminNote, req.user.id);
      return res.status(200).json({ success: true, data, message: 'Dokumen diperbarui' });
    } catch (error) {
      next(error);
    }
  };

  static listPrograms = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.listPrograms();
      return res.status(200).json({ success: true, data });
    } catch (error) {
      next(error);
    }
  };

  static createProgram = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.createProgram(req.body);
      return res.status(201).json({ success: true, data, message: 'Program dibuat' });
    } catch (error) {
      next(error);
    }
  };

  static updateProgram = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.updateProgram(Number(req.params.id), req.body);
      return res.status(200).json({ success: true, data, message: 'Program diperbarui' });
    } catch (error) {
      next(error);
    }
  };

  static deleteProgram = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.deleteProgram(Number(req.params.id));
      return res.status(200).json({ success: true, data, message: 'Program dihapus' });
    } catch (error) {
      next(error);
    }
  };

  static listAnnouncements = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.listAnnouncements();
      return res.status(200).json({ success: true, data });
    } catch (error) {
      next(error);
    }
  };

  static createAnnouncement = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.createAnnouncement({ ...req.body, author: req.user.email });
      return res.status(201).json({ success: true, data, message: 'Pengumuman dibuat' });
    } catch (error) {
      next(error);
    }
  };

  static updateAnnouncement = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.updateAnnouncement(Number(req.params.id), req.body);
      return res.status(200).json({ success: true, data, message: 'Pengumuman diperbarui' });
    } catch (error) {
      next(error);
    }
  };

  static deleteAnnouncement = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.deleteAnnouncement(Number(req.params.id));
      return res.status(200).json({ success: true, data, message: 'Pengumuman dihapus' });
    } catch (error) {
      next(error);
    }
  };

  static listUsers = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { search, role, page = 1, limit = 10 } = req.query;
      const result = await adminService.listUsers({ search: search as string, role: role as string, page: Number(page), limit: Number(limit) });
      return res.status(200).json({ success: true, data: result.data, total: result.total });
    } catch (error) {
      next(error);
    }
  };

  static createUser = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.createUser(req.body);
      return res.status(201).json({ success: true, data, message: 'Pengguna dibuat' });
    } catch (error) {
      next(error);
    }
  };

  static updateUser = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.updateUser(Number(req.params.id), req.body);
      return res.status(200).json({ success: true, data, message: 'Pengguna diperbarui' });
    } catch (error) {
      next(error);
    }
  };

  static deleteUser = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.deleteUser(Number(req.params.id));
      return res.status(200).json({ success: true, data, message: 'Pengguna dinonaktifkan' });
    } catch (error) {
      next(error);
    }
  };

  static getChat = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.getChatMessages(Number(req.query.page) || 1, Number(req.query.limit) || 50);
      return res.status(200).json({ success: true, data });
    } catch (error) {
      next(error);
    }
  };

  static markChatRead = async (req: Request, res: Response, next: NextFunction) => {
    try {
      await adminService.markChatRead(Number(req.params.id));
      return res.status(200).json({ success: true, message: 'Pesan dibaca' });
    } catch (error) {
      next(error);
    }
  };

  static sendReply = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.sendReply(req.user.id, Number(req.body.receiverId), req.body.message);
      return res.status(201).json({ success: true, data, message: 'Balasan terkirim' });
    } catch (error) {
      next(error);
    }
  };

  static getSettings = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const data = await adminService.getSettings();
      return res.status(200).json({ success: true, data });
    } catch (error) {
      next(error);
    }
  };

  static updateSetting = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { key } = req.params;
      const data = await adminService.updateSetting(key, req.body.value);
      return res.status(200).json({ success: true, data, message: 'Setting diperbarui' });
    } catch (error) {
      next(error);
    }
  };

  static exportStudents = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const format = req.query.format as string;
      const result = await adminService.exportStudentsReport(format, {});
      res.setHeader('Content-Type', result.contentType);
      res.setHeader('Content-Disposition', `attachment; filename=${result.filename}`);
      return res.send(result.buffer);
    } catch (error) {
      next(error);
    }
  };

  static exportDocuments = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const format = req.query.format as string;
      const result = await adminService.exportDocumentsReport(format);
      res.setHeader('Content-Type', result.contentType);
      res.setHeader('Content-Disposition', `attachment; filename=${result.filename}`);
      return res.send(result.buffer);
    } catch (error) {
      next(error);
    }
  };
}

export default AdminController;
