import adminModel from "../models/adminModel.js";
import jwt from "jsonwebtoken";
import bcrypt from "bcrypt";
import validator from "validator";



/* JWT Token Creator*/
const createToken = (id) => {
    return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: "1h" });
};

/* Admin Signup*/
const adminSign = async (req, res) => {
    try {
        const { adminName, email, password } = req.body;

        if (!adminName || !email || !password) {
            return res
                .status(400)
                .json({ success: false, message: "All fields are required" });
        }

        const adminExists = await adminModel.findOne({ email });
        if (adminExists) {
            return res
                .status(400)
                .json({ success: false, message: "Admin already exists" });
        }

        if (!validator.isEmail(email)) {
            return res
                .status(400)
                .json({ success: false, message: "Invalid email format" });
        }

        if (
            !validator.isStrongPassword(password, {
                minLength: 8,
                minUppercase: 1,
                minLowercase: 1,
                minNumbers: 1,
                minSymbols: 1,
            })
        ) {
            return res.status(400).json({
                success: false,
                message:
                    "Password too weak. Use at least 8 characters, uppercase, lowercase, number, and symbol.",
            });
        }

        const hashedPassword = await bcrypt.hash(password, 10);

        const newAdmin = new adminModel({
            adminName,
            email,
            password: hashedPassword,
        });

        const savedAdmin = await newAdmin.save();

        const adminToken = createToken(savedAdmin._id);

        res.cookie("adminToken", adminToken, {
            httpOnly: true,
            secure: process.env.NODE_ENV === "production",
            sameSite: "Strict",
            maxAge: 7 * 24 * 60 * 60 * 1000,
        });

        return res
            .status(201)
            .json({ success: true, message: "Admin registered successfully" });
    } catch (error) {
        console.error("Signup Error", error);
        return res.status(500).json({ success: false, message: "Server error" });
    }
};

/* Admin Login*/
const adminLogin = async (req, res) => {
    try {
        const { email, password } = req.body;

        if (!email || !password)
            return res
                .status(400)
                .json({ success: false, message: "Email and password required" });

        const admin = await adminModel.findOne({ email });
        if (!admin)
            return res
                .status(401)
                .json({ success: false, message: "Invalid credentials" });

        const isMatch = await bcrypt.compare(password, admin.password);
        if (!isMatch)
            return res
                .status(401)
                .json({ success: false, message: "Invalid credentials" });

        const adminToken = createToken(admin._id);

        res.cookie("adminToken", adminToken, {
            httpOnly: true,
            secure: process.env.NODE_ENV === "production",
            sameSite: "Strict",
            maxAge: 7 * 24 * 60 * 60 * 1000,
        });

        return res.status(200).json({
            success: true,
            adminToken,
            message: "Login successful",
        });
    } catch (error) {
        console.error("Login Error:", error);
        return res.status(500).json({ success: false, message: "Server error" });
    }
};

/* Admin Logout*/
const adminLogout = async (req, res) => {
    try {
        res.clearCookie("adminToken", {
            httpOnly: true,
            secure: process.env.NODE_ENV === "production",
            sameSite: "Strict",
        });

        return res
            .status(200)
            .json({ success: true, message: "Admin logged out successfully" });
    } catch (error) {
        console.error("Logout Error:", error);
        return res.status(500).json({ success: false, message: "Logout failed" });
    }
};

// Forgot Password (email reset link)
const forgotPassword = async (req, res) => {
    try {
        const { email } = req.body;

        const admin = await adminModel.findOne({ email });
        if (!admin) {
            return res
                .status(404)
                .json({ success: false, message: "Admin not found with this email" });
        }

// Generate reset token
        const resetToken = crypto.randomBytes(32).toString("hex");
        const hashedToken = crypto
            .createHash("sha256")
            .update(resetToken)
            .digest("hex");

//Save token and expiry to DB (add these fields in model)
        admin.resetPasswordToken = hashedToken;
        admin.resetPasswordExpires = Date.now() + 10 * 60 * 1000; // 10 minutes
        await admin.save({ validateBeforeSave: false });

//Create reset link
const resetUrl = `${process.env.FRONTEND_URL}/admin/reset-password/${resetToken}`;

//Send email (using nodemailer)
        const transporter = nodemailer.createTransport({
            service: "gmail",
            auth: {
                user: process.env.EMAIL_USER,
                pass: process.env.EMAIL_PASS,
            },
        });

        const message = {
            from: process.env.EMAIL_USER,
            to: email,
            subject: "Admin Password Reset",
            html: `<p>Hello ${admin.adminName},</p>
            <p>Click the link below to reset your password. This link expires in 10 minutes.</p>
            <a href="${resetUrl}" target="_blank">${resetUrl}</a>`,
        };

        await transporter.sendMail(message);

        return res.status(200).json({
            success: true,
            message: "Password reset link sent to your email",
        });
    } catch (error) {
        console.error("Forgot Password Error:", error);
        return res.status(500).json({
            success: false,
            message: "Failed to send password reset link",
        });
    }
};


/*Reset Password (after clicking email link)*/
const resetPassword = async (req, res) => {
    try {
        const { token } = req.params;
        const { newPassword } = req.body;

        const hashedToken = crypto.createHash("sha256").update(token).digest("hex");

        const admin = await adminModel.findOne({
            resetPasswordToken: hashedToken,
            resetPasswordExpires: { $gt: Date.now() },
        });

        if (!admin)
            return res
                .status(400)
                .json({ success: false, message: "Invalid or expired token" });

        admin.password = await bcrypt.hash(newPassword, 10);
        admin.resetPasswordToken = undefined;
        admin.resetPasswordExpires = undefined;
        await admin.save();

        return res
            .status(200)
            .json({ success: true, message: "Password reset successfully" });
    } catch (error) {
        console.error("Reset Password Error:", error);
        return res.status(500).json({ success: false, message: "Server error" });
    }
};

export { adminSign, adminLogin, adminLogout };
