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

import { BadRequestError, NotFoundError } from '../../../errors/http-error';
import { getErrorMessage } from '../../../utils/error-utils';
import { VerifyEmailDto, VerifyPhoneDto } from '../identity.dto';

import { verificationService } from './verification.service';

/**
 * EN: Identity Verification Controller
 * VI: Controller xác thực danh tính
 */
export class VerificationController {
  /**
   * EN: Request email verification
   * VI: Yêu cầu xác thực email
   */
  async requestEmail(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 result = await verificationService.requestEmailVerification(userId, req);

      res.json({
        success: true,
        data: result,
        message: 'Verification email sent / Email xác thực đã được gửi',
      });
    } 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: 'REQUEST_VERIFICATION_FAILED',
          message: getErrorMessage(error) || 'Failed to request verification',
        },
      });
    }
  }

  /**
   * EN: Verify email
   * VI: Xác thực email
   */
  async verifyEmail(req: Request, res: Response): Promise<void> {
    try {
      const data = VerifyEmailDto.parse(req.body);
      const result = await verificationService.verifyEmail(data.token, req);

      res.json({
        success: true,
        data: result,
        message: 'Email verified successfully / Email đã được xác thực 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 BadRequestError) {
        res.status(400).json(error.toApiResponse());
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'VERIFY_EMAIL_FAILED',
          message: getErrorMessage(error) || 'Failed to verify email',
        },
      });
    }
  }

  /**
   * EN: Request phone verification
   * VI: Yêu cầu xác thực điện thoại
   */
  async requestPhone(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.id || req.body.userId;
      const { phone } = req.body;

      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;
      }

      if (!phone) {
        res.status(400).json({
          success: false,
          error: {
            code: 'PHONE_REQUIRED',
            message: 'Phone number is required / Số điện thoại là bắt buộc',
          },
        });
        return;
      }

      const result = await verificationService.requestPhoneVerification(userId, phone, req);

      res.json({
        success: true,
        data: result,
        message: 'Verification code sent / Mã xác thực đã được gửi',
      });
    } 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: 'REQUEST_PHONE_VERIFICATION_FAILED',
          message: getErrorMessage(error) || 'Failed to request phone verification',
        },
      });
    }
  }

  /**
   * EN: Verify phone
   * VI: Xác thực điện thoại
   */
  async verifyPhone(req: Request, res: Response): Promise<void> {
    try {
      const data = VerifyPhoneDto.parse(req.body);
      const result = await verificationService.verifyPhone(data.token, data.code, req);

      res.json({
        success: true,
        data: result,
        message: 'Phone verified successfully / Điện thoại đã được xác thực 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 BadRequestError) {
        res.status(400).json(error.toApiResponse());
        return;
      }

      res.status(500).json({
        success: false,
        error: {
          code: 'VERIFY_PHONE_FAILED',
          message: getErrorMessage(error) || 'Failed to verify phone',
        },
      });
    }
  }

  /**
   * EN: Get verification status
   * VI: Lấy trạng thái xác thực
   */
  async getStatus(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const { type } = req.query;

      if (!type) {
        res.status(400).json({
          success: false,
          error: {
            code: 'TYPE_REQUIRED',
            message: 'Verification type is required / Loại xác thực là bắt buộc',
          },
        });
        return;
      }

      const status = await verificationService.getVerificationStatus(id, type as any);

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

export const verificationController = new VerificationController();
