import type { Request, Response } from "express";
import { z } from "zod";
import { ForgotPasswordService } from "../services/ForgotPasswordService.js";

const sendOtpSchema = z.object({
    email: z.string().email("Invalid email format"),
})

const verifyOtpSchema = z.object({
    email: z.string().email("Invalid email format"),
    otp: z.string().length(6, "OTP must be 6 digits"),
})

const resetPasswordSchema = z.object({
    email: z.string().email("Invalid email format"),
    otp: z.string().length(6, "OTP must be 6 digits"),
    password: z.string().min(6, "Password must be at least 6 characters"),
})

export class ForgotPasswordController {
    constructor(private readonly forgotPasswordService = new ForgotPasswordService()) { }

    maxAttempt: number = 5;

    async sendOtp(req: Request, res: Response): Promise<void> {
        try {
            const parsedData = sendOtpSchema.safeParse(req.body);

            if (!parsedData.success) {
                const formattedErrors: Record<string, string> = {};
                parsedData.error.issues.forEach((issue) => {
                    if (issue?.path && issue.path.length > 0 && issue.path[0] !== undefined) {
                        formattedErrors[issue.path[0].toString()] = issue.message;
                    }
                });

                res.status(422).json({
                    message: "Validation failed",
                    errors: Object.keys(formattedErrors).length > 0 ? formattedErrors : parsedData.error.issues,
                });
                return;
            }

            await this.forgotPasswordService.sendOtp(parsedData.data.email);
            res.status(200).json({ message: "OTP sent successfully" })
        } catch (error) {
            const message = error instanceof Error ? error.message : "Failed to send OTP"
            res.status(400).json({ message })
        }
    }

    async verifyOtp(req: Request, res: Response): Promise<void> {
        try {
            const parsedData = verifyOtpSchema.safeParse(req.body);

            if (!parsedData.success) {
                const formattedErrors: Record<string, string> = {};
                parsedData.error.issues.forEach((issue) => {
                    if (issue?.path && issue.path.length > 0 && issue.path[0] !== undefined) {
                        formattedErrors[issue.path[0].toString()] = issue.message;
                    }
                });

                res.status(422).json({
                    message: "Validation failed",
                    errors: Object.keys(formattedErrors).length > 0 ? formattedErrors : parsedData.error.issues,
                });
                return;
            }

            await this.forgotPasswordService.verifyOtp(parsedData.data.email, parsedData.data.otp);
            res.status(200).json({ message: "OTP verified successfully" })

        } catch (error) {
            const message = error instanceof Error ? error.message : "Failed to verify OTP"
            res.status(400).json({ message })
        }
    }

    async resetPassword(req: Request, res: Response): Promise<void> {
        try {
            const parsedData = resetPasswordSchema.safeParse(req.body);

            if (!parsedData.success) {
                const formattedErrors: Record<string, string> = {};
                parsedData.error.issues.forEach((issue) => {
                    if (issue?.path && issue.path.length > 0 && issue.path[0] !== undefined) {
                        formattedErrors[issue.path[0].toString()] = issue.message;
                    }
                });

                res.status(422).json({
                    message: "Validation failed",
                    errors: Object.keys(formattedErrors).length > 0 ? formattedErrors : parsedData.error.issues,
                });
                return;
            }

            const { email, otp, password } = parsedData.data;
            const result = await this.forgotPasswordService.resetPassword(email, otp, password);
            res.status(200).json(result);
        } catch (error) {
            const message = error instanceof Error ? error.message : "Failed to reset password";
            res.status(400).json({ message });
        }
    }
}