import { Request, Response } from 'express';
import { z } from 'zod';

import { NotFoundError, BadRequestError } from '../../../errors/http-error';
import { getErrorMessage } from '../../../utils/error-utils';
import { CreateAccessRequestDto, ApproveAccessRequestDto, RejectAccessRequestDto } from '../access.dto';

import { accessRequestService } from './request.service';

/**
 * EN: Access Request Controller
 * VI: Controller yêu cầu truy cập
 */
export class AccessRequestController {
  /**
   * EN: List access requests
   * VI: Liệt kê các yêu cầu truy cập
   */
  async list(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.id || req.query.userId as string;
      
      if (!userId) {
        res.status(400).json({
          success: false,
          error: {
            code: 'USER_ID_REQUIRED',
            message: 'User ID is required / User ID là bắt buộc',
          },
        });
        return;
      }

      const requests = await accessRequestService.getUserRequests(userId);

      res.json({
        success: true,
        data: requests,
      });
    } catch (error: unknown) {
      res.status(500).json({
        success: false,
        error: {
          code: 'LIST_REQUESTS_FAILED',
          message: getErrorMessage(error) || 'Failed to list access requests',
        },
      });
    }
  }

  /**
   * EN: Create access request
   * VI: Tạo yêu cầu truy cập
   */
  async create(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.id || req.body.userId;
      if (!userId) {
        res.status(400).json({
          success: false,
          error: {
            code: 'USER_ID_REQUIRED',
            message: 'User ID is required / User ID là bắt buộc',
          },
        });
        return;
      }

      const data = CreateAccessRequestDto.parse(req.body);
      const request = await accessRequestService.createRequest(userId, data, req);

      res.status(201).json({
        success: true,
        data: request,
        message: 'Access request created successfully / Yêu cầu truy cập đã được tạo thành công',
      });
    } catch (error: unknown) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid input',
            details: error.issues,
          },
        });
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'CREATE_REQUEST_FAILED',
          message: getErrorMessage(error) || 'Failed to create access request',
        },
      });
    }
  }

  /**
   * EN: Get access request
   * VI: Lấy yêu cầu truy cập
   */
  async get(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const request = await accessRequestService.getRequest(id);

      res.json({
        success: true,
        data: request,
      });
    } catch (error: unknown) {
      if (error instanceof NotFoundError) {
        res.status(404).json(error.toApiResponse());
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'GET_REQUEST_FAILED',
          message: getErrorMessage(error) || 'Failed to get access request',
        },
      });
    }
  }

  /**
   * EN: Approve access request
   * VI: Phê duyệt yêu cầu truy cập
   */
  async approve(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const approverId = (req as any).user?.id;
      if (!approverId) {
        res.status(401).json({
          success: false,
          error: {
            code: 'UNAUTHORIZED',
            message: 'Authentication required / Yêu cầu xác thực',
          },
        });
        return;
      }

      const data = ApproveAccessRequestDto.parse(req.body);
      const request = await accessRequestService.approveRequest(id, approverId, data.comments, req);

      res.json({
        success: true,
        data: request,
        message: 'Access request approved successfully / Yêu cầu truy cập đã được phê duyệt thành công',
      });
    } catch (error: unknown) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid input',
            details: error.issues,
          },
        });
        return;
      }

      if (error instanceof NotFoundError || error instanceof BadRequestError) {
        res.status(error.statusCode).json(error.toApiResponse());
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'APPROVE_REQUEST_FAILED',
          message: getErrorMessage(error) || 'Failed to approve access request',
        },
      });
    }
  }

  /**
   * EN: Reject access request
   * VI: Từ chối yêu cầu truy cập
   */
  async reject(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const approverId = (req as any).user?.id;
      if (!approverId) {
        res.status(401).json({
          success: false,
          error: {
            code: 'UNAUTHORIZED',
            message: 'Authentication required / Yêu cầu xác thực',
          },
        });
        return;
      }

      const data = RejectAccessRequestDto.parse(req.body);
      const request = await accessRequestService.rejectRequest(id, approverId, data.comments, req);

      res.json({
        success: true,
        data: request,
        message: 'Access request rejected / Yêu cầu truy cập đã bị từ chối',
      });
    } catch (error: unknown) {
      if (error instanceof z.ZodError) {
        res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid input',
            details: error.issues,
          },
        });
        return;
      }

      if (error instanceof NotFoundError || error instanceof BadRequestError) {
        res.status(error.statusCode).json(error.toApiResponse());
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'REJECT_REQUEST_FAILED',
          message: getErrorMessage(error) || 'Failed to reject access request',
        },
      });
    }
  }

  /**
   * EN: Cancel access request
   * VI: Hủy yêu cầu truy cập
   */
  async cancel(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as any).user?.id;
      if (!userId) {
        res.status(401).json({
          success: false,
          error: {
            code: 'UNAUTHORIZED',
            message: 'Authentication required / Yêu cầu xác thực',
          },
        });
        return;
      }

      await accessRequestService.cancelRequest(id, userId, req);

      res.json({
        success: true,
        message: 'Access request cancelled successfully / Yêu cầu truy cập đã được hủy thành công',
      });
    } catch (error: unknown) {
      if (error instanceof NotFoundError || error instanceof BadRequestError) {
        res.status(error.statusCode).json(error.toApiResponse());
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'CANCEL_REQUEST_FAILED',
          message: getErrorMessage(error) || 'Failed to cancel access request',
        },
      });
    }
  }

  /**
   * EN: Get pending approvals
   * VI: Lấy các yêu cầu đang chờ phê duyệt
   */
  async getPendingApprovals(req: Request, res: Response): Promise<void> {
    try {
      const approverId = (req as any).user?.id;
      if (!approverId) {
        res.status(401).json({
          success: false,
          error: {
            code: 'UNAUTHORIZED',
            message: 'Authentication required / Yêu cầu xác thực',
          },
        });
        return;
      }

      const requests = await accessRequestService.getPendingApprovals(approverId);

      res.json({
        success: true,
        data: requests,
      });
    } catch (error: unknown) {
      res.status(500).json({
        success: false,
        error: {
          code: 'GET_PENDING_APPROVALS_FAILED',
          message: getErrorMessage(error) || 'Failed to get pending approvals',
        },
      });
    }
  }
}

export const accessRequestController = new AccessRequestController();
