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

interface TokenOptions {
  expires?: Date;
  maxAge?: number;
  httpOnly?: boolean;
  sameSite?: "lax" | "strict" | "none" | undefined;
  secure?: boolean;
}

// Default token options
const accessTokenOptions: TokenOptions = {
  expires: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
  maxAge: 24 * 60 * 60 * 1000,
  httpOnly: true,
  sameSite: "strict",
  secure: process.env.NODE_ENV === "production",
};

const refreshTokenOptions: TokenOptions = {
  expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
  maxAge: 7 * 24 * 60 * 60 * 1000,
  httpOnly: true,
  sameSite: "strict",
  secure: process.env.NODE_ENV === "production",
};

export const generateToken = (
  user: any,
  statusCode: number,
  message: string,
  res: Response,
  options?: TokenOptions
) => {
  const accessToken = jwt.sign(
    { id: user.id, username: user.username, account_type: user.account_type },
    process.env.JWT_SECRET_KEY!,
    { expiresIn: "24h" }
  );

  const refreshToken = jwt.sign(
    { id: user.id },
    process.env.JWT_REFRESH_SECRET!,
    { expiresIn: "7d" }
  );

  // Merge custom options with defaults
  const mergedAccessOptions = { ...accessTokenOptions, ...options };
  const mergedRefreshOptions = { ...refreshTokenOptions, ...options };

  // Set cookies
  res.cookie("access_token", accessToken, mergedAccessOptions);
  res.cookie("refresh_token", refreshToken, mergedRefreshOptions);

  // Remove sensitive data from response
  const { password_hash, reset_password_token, otp_code, ...userData } = user;

  res.status(statusCode).json({
    success: true,
    message,
    data: {
      user: userData,
      access_token: accessToken,
    },
  });
};

export const verifyToken = (token: string): any => {
  return jwt.verify(token, process.env.JWT_SECRET_KEY!);
};

export const verifyRefreshToken = (token: string): any => {
  return jwt.verify(token, process.env.JWT_REFRESH_SECRET!);
};

export const refreshAccessToken = (req: Request, res: Response) => {
  const refreshToken = req.cookies.refresh_token;

  if (!refreshToken) {
    return res.status(401).json({
      success: false,
      message: "Refresh token not found.",
    });
  }

  try {
    const decoded = verifyRefreshToken(refreshToken);
    
    // Generate new access token
    const newAccessToken = jwt.sign(
      { id: decoded.id },
      process.env.JWT_SECRET_KEY!,
      { expiresIn: "24h" }
    );

    res.cookie("access_token", newAccessToken, accessTokenOptions);

    return res.status(200).json({
      success: true,
      message: "Access token refreshed successfully.",
      access_token: newAccessToken,
    });
  } catch (error) {
    return res.status(401).json({
      success: false,
      message: "Invalid or expired refresh token.",
    });
  }
};