import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";
import { UserModel } from "../models/user";
import { ShopModel } from "../models/shop";

interface AuthRequest extends Request {
  user?: {
    id: number;
    email: string;
    role: string;
    assignedShopIds: number[];
    assignedShopNames: string[];
  };
}

export const authenticateToken = async (
  req: AuthRequest,
  res: Response,
  next: NextFunction
) => {
  try {
    const authHeader = req.headers["authorization"];
    const token = authHeader && authHeader.split(" ")[1]; // Bearer TOKEN

    if (!token) {
      return res.status(401).json({ error: "Access token required" });
    }

    const secret = "TheUniformCenter!@#$%54321"; // Same secret used in generateAuthToken
    const decoded = jwt.verify(token, secret) as any;

    // Get fresh user data from database
    const user = await UserModel.findByPk(decoded.id);
    if (!user || user.isDeleted) {
      return res.status(401).json({ error: "Invalid token or user not found" });
    }

    // Get assigned shops for this user (if shopkeeper)
    let assignedShopIds: number[] = [];
    let assignedShopNames: string[] = [];

    if (user.role === "Shopkeeper") {
      const assignedShops = await ShopModel.findAll({
        where: {
          isDeleted: false
        },
        raw: true
      });

      // Filter shops where this user's ID is in the shopkeeperIds array
      const userShops = assignedShops.filter(shop => {
        const shopkeeperIds = shop.shopkeeperIds || [];
        return shopkeeperIds.includes(user.id);
      });

      assignedShopIds = userShops.map(shop => shop.id);
      assignedShopNames = userShops.map(shop => shop.name);
    }

    // Attach user info to request
    req.user = {
      id: user.id,
      email: user.email,
      role: user.role,
      assignedShopIds,
      assignedShopNames,
    };

    next();
  } catch (error) {
    return res.status(403).json({ error: "Invalid or expired token" });
  }
};

export const requireRole = (roles: string[]) => {
  return (req: AuthRequest, res: Response, next: NextFunction) => {
    if (!req.user) {
      return res.status(401).json({ error: "Authentication required" });
    }

    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ 
        error: `Access denied. Required roles: ${roles.join(", ")}` 
      });
    }

    next();
  };
};