import type { Request, Response, NextFunction } from "express";
import type { RowDataPacket } from "mysql2";
import db from "../db.js";
import { verifyToken, COOKIE_NAME } from "./jwt.js";
import type { JWTPayload } from "./jwt.js";

declare global {
  namespace Express {
    interface Request {
      user?: JWTPayload;
    }
  }
}

export function requireAuth(req: Request, res: Response, next: NextFunction): void {
  const token = req.cookies?.[COOKIE_NAME];
  if (!token) {
    res.status(401).json({ error: "Unauthorized" });
    return;
  }
  try {
    req.user = verifyToken(token);
    next();
  } catch {
    res.status(401).json({ error: "Unauthorized" });
  }
}

export function requireCampaignRole(role: "dm" | "player") {
  return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
    if (!req.user) {
      res.status(401).json({ error: "Unauthorized" });
      return;
    }
    const campaignId = req.params.campaignId ?? req.params.id;
    const userId = req.user.userId;
    try {
      const [rows] = await db.execute<RowDataPacket[]>(
        "SELECT role FROM campaign_members WHERE campaign_id = ? AND user_id = ?",
        [campaignId, userId]
      );
      if (rows.length === 0) {
        res.status(403).json({ error: "Not a campaign member" });
        return;
      }
      if (role === "dm" && rows[0].role !== "dm") {
        res.status(403).json({ error: "DM access required" });
        return;
      }
      next();
    } catch (err) {
      next(err);
    }
  };
}
