import type { Request, Response } from "express";
import { MobileAuthService } from "../../services/mobile/MobileAuthService.js";
import { createUploadMiddleware } from "../../middleware/upload.middleware.js";
import path from "path";
import fs from "fs";
import { z } from "zod";

const baseUrl = process.env.BASE_URL || "baseurl not loaded check env";
const FILE_LOCATION = "uploads/profiles";
const uploadDir = path.join(process.cwd(), FILE_LOCATION);

const loginSchema = z.object({
    contact: z.string({ message: "Contact (email or mobile number) is required" }).min(1, "Contact (email or mobile number) is required"),
    password: z.string({ message: "Password is required" }).min(6, "Password must be at least 6 characters"),
});

const profileUpdateSchema = z.object({
    name: z.string().optional(),
    mobileNo: z.string().optional(),
    password: z.string().min(6, "Password must be at least 6 characters").optional(),
});

export class MobileAuthController {
    constructor(private readonly mobileAuthService = new MobileAuthService()) {}

    handleImageUpload = createUploadMiddleware(FILE_LOCATION, "profile", "profile");

    login = async (req: Request, res: Response): Promise<void> => {
        try {
            const parsedData = loginSchema.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 { contact, password } = parsedData.data;

            const result = await this.mobileAuthService.login(contact, password);

            if (!result.user.status) {
                res.status(400).json({ message: "Your account is inactive. Please contact the administrator." });
                return;
            }

            res.status(200).json(result);
        } catch (error) {
            const message = error instanceof Error ? error.message : "Login failed";
            res.status(412).json({ message });
        }
    };

    logout = async (_req: Request, res: Response): Promise<void> => {
        try {
            const result = await this.mobileAuthService.logout();
            res.status(200).json(result);
        } catch (error) {
            const message = error instanceof Error ? error.message : "Logout failed";
            res.status(500).json({ message });
        }
    };

    getProfile = async (req: Request, res: Response): Promise<void> => {
        try {
            const userId = BigInt(req.user?.id || 0);
            const user = await this.mobileAuthService.getProfile(userId);
            const { password: _pw, ...userWithoutPassword } = user as any;
            res.status(200).json({
                ...userWithoutPassword,
                profileUrl: user.profile ? `${baseUrl}/${FILE_LOCATION}/${user.profile}` : null,
            });
        } catch (error) {
            const message = error instanceof Error ? error.message : "Failed to get profile";
            res.status(500).json({ message });
        }
    };

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

            if (!parsedData.success) {
                if (req.file && fs.existsSync(req.file.path)) fs.unlinkSync(req.file.path);

                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 { name, mobileNo, password } = parsedData.data;
            const userId = BigInt(req.user?.id || 0);
            const existingUser = await this.mobileAuthService.getProfile(userId);

            let profileImage = existingUser?.profile ?? "default-profile.png";

            if (req.file) {
                if (existingUser?.profile && existingUser.profile !== "default-profile.png") {
                    const oldProfile = path.join(uploadDir, existingUser.profile);
                    if (fs.existsSync(oldProfile)) fs.unlinkSync(oldProfile);
                }
                profileImage = req.file.filename;
            }

            const updateData: any = { profile: profileImage };
            if (name && name.trim() !== "") updateData.name = name;
            if (mobileNo && mobileNo.trim() !== "") updateData.mobileNo = mobileNo;
            if (password && password.trim() !== "") updateData.password = password;

            const updatedUser = await this.mobileAuthService.updateProfile(userId, updateData);
            const { password: _pw, ...userWithoutPassword } = updatedUser as any;

            res.status(200).json({
                ...userWithoutPassword,
                profileUrl: updatedUser.profile ? `${baseUrl}/${FILE_LOCATION}/${updatedUser.profile}` : null,
            });
        } catch (error: any) {
            if (req.file && fs.existsSync(req.file.path)) fs.unlinkSync(req.file.path);
            const message = error instanceof Error ? error.message : "Failed to update profile";
            res.status(500).json({ message });
        }
    };
}