import { Request, Response, NextFunction, RequestHandler } from "express";
import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import { User } from "../models/User";

// Extend Request to include user from JWT
declare module "express" {
  interface Request {
    user?: { id: number; email: string };
  }
}

export class AuthController {
  // Middleware to verify JWT
  static verifyJWT: RequestHandler = (
    req: Request,
    res: Response,
    next: NextFunction
  ): void => {
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith("Bearer ")) {
      res.status(401).json({
        isAuthenticated: false,
        message: "Unauthorized: No token provided",
      });
      return;
    }

    const token = authHeader.split(" ")[1];
    try {
      const decoded = jwt.verify(
        token,
        process.env.JWT_SECRET_ADMINPANEL || "jwtsecret"
      ) as { id: number; email: string };
      req.user = { id: decoded.id, email: decoded.email };
      next();
    } catch (error) {
      console.error("JWT verification error:", error);
      res.status(401).json({
        isAuthenticated: false,
        message: "Unauthorized: Invalid token",
      });
    }
  };

  check: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const userId = req.user?.id;
      if (!userId) {
        res
          .status(401)
          .json({ isAuthenticated: false, message: "Not authenticated" });
        return;
      }

      const user = await User.query().findById(userId);

      if (!user) {
        res
          .status(401)
          .json({ isAuthenticated: false, message: "User not found" });
        return;
      }

      if (user.user_details?.role === "admin") {
        res.json({
          isAuthenticated: true,
          user: {
            id: user.id,
            email: user.user_details.email,
            role: user.user_details.role,
            name: user.user_details?.first_name,
          },
        });
        return;
      }

      res.status(403).json({
        isAuthenticated: false,
        message: "Access denied. Only for admin.",
      });
    } catch (error) {
      console.error("Auth check error:", error);
      res.status(500).json({
        isAuthenticated: false,
        message: "Internal server error",
      });
    }
  };

  login: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const { email, password } = req.body;

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

      const user = await User.query()
        .whereRaw(`JSON_UNQUOTE(JSON_EXTRACT(user_details, '$.email')) = ?`, [
          email,
        ])
        .first();

      if (!user) {
        res.status(401).json({ message: "Invalid email or password" });
        return;
      }

      const isValidPassword = await bcrypt.compare(password, user.password);

      if (!isValidPassword) {
        res.status(401).json({ message: "Invalid email or password" });
        return;
      }

      if (user.user_details.role !== "admin") {
        res.status(403).json({ message: "Access denied. Admins only." });
        return;
      }
      if (user.status !== "active") {
        res
          .status(403)
          .json({ message: "Access denied. Admin is inactive or suspended." });
        return;
      }

      // Generate JWT
      const token = jwt.sign(
        { id: user.id, email: user.user_details.email },
        process.env.JWT_SECRET_ADMINPANEL || "jwtsecret",
        { expiresIn: "1d" } // Token expires in 1 day
      );

      console.log("Generated JWT:", token);

      res.json({
        message: "Login successful",
        token,
        user: {
          id: user.id,
          email: user.user_details.email,
          name: user.user_details.first_name,
          role: user.user_details.role,
        },
      });
    } catch (error) {
      console.error("Login error:", error);
      res.status(500).json({ message: "Internal server error" });
    }
  };

  logout: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      // JWT is stateless, so logout is handled client-side by removing the token
      res.json({
        isAuthenticated: false,
        message: "Logged out successfully",
      });
    } catch (error) {
      console.error("Logout error:", error);
      res.status(500).json({
        isAuthenticated: false,
        message: "Internal server error",
      });
    }
  };
}
