import { NextFunction, Response } from "express";
import jwt from "jsonwebtoken";

import { prisma } from "@/config/database.js";
import { env } from "@/config/env.js";
import { AuthenticatedRequest, AuthenticatedSocket, JWTPayload } from "@/types/index.js";
import { Socket } from "socket.io";

export const authenticateToken = (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
  try {
    const authHeader = req.headers.authorization;
    const token = authHeader?.split(" ")[1];

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

    const decoded = jwt.verify(token, env.JWT_SECRET) as JWTPayload;
    req.user = decoded;
    next();
  } catch (error) {
    console.error("Authentication error:", error);
    res.status(403).json({ success: false, error: "Invalid or expired token" });
  }
};

export const authenticateSocket = async (socket: Socket, next: (err?: Error) => void) => {
  try {
    const token = socket.handshake.auth.token as string | undefined;

    if (!token) {
      return next(new Error("Authentication token required"));
    }

    const decoded = jwt.verify(token, env.JWT_SECRET) as JWTPayload;

    const user = await prisma.user.findUnique({
      where: {
        id: decoded.userId,
      },
    });

    if (!user) return next(new Error("User not found"));

    const authenticateSocket = socket as AuthenticatedSocket;
    authenticateSocket.userId = user.id;
    authenticateSocket.user = user;

    next();
  } catch (error) {
    console.error("Socket authentication error:", error);
  }
};
