import { Request, Response } from "express";
import { sendError, sendSuccess } from "../../common/utils/api-response";
import * as authService from "./auth.service";

const cookieOptions = {
  httpOnly: true,
  secure: process.env.NODE_ENV === "production",
  sameSite: "lax" as const,
};

export const setAuthCookies = (
  res: Response,
  accessToken?: string,
  refreshToken?: string,
) => {
  if (accessToken) {
    res.cookie("accessToken", accessToken, {
      ...cookieOptions,
      maxAge: 15 * 60 * 1000, // 15 minutes
    });
  }
  if (refreshToken) {
    res.cookie("refreshToken", refreshToken, {
      ...cookieOptions,
      maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
    });
  }
};

const clearAuthCookies = (res: Response) => {
  res.clearCookie("accessToken", cookieOptions);
  res.clearCookie("refreshToken", cookieOptions);
};

export async function register(req: Request, res: Response) {
  const result = await authService.register(req.body);
  sendSuccess(res, result, 201);
}

export async function login(req: Request, res: Response) {
  const userAgent = req.headers["user-agent"];
  const ipAddress = req.ip;
  const result = await authService.login(req.body, userAgent, ipAddress);
  if (result.accessToken && result.refreshToken) {
    setAuthCookies(res, result.accessToken, result.refreshToken);
  }
  sendSuccess(res, result);
}

export async function refresh(req: Request, res: Response) {
  const userAgent = req.headers["user-agent"];
  const ipAddress = req.ip;
  const refreshToken = req.body.refreshToken || req.cookies?.refreshToken;
  const tokens = await authService.refresh(refreshToken, userAgent, ipAddress);
  if (tokens.accessToken && tokens.refreshToken) {
    setAuthCookies(res, tokens.accessToken, tokens.refreshToken);
  }
  sendSuccess(res, tokens);
}

export async function logout(req: Request, res: Response) {
  const refreshToken = req.body.refreshToken || req.cookies?.refreshToken;
  if (refreshToken) {
    await authService.logout(refreshToken);
  }
  clearAuthCookies(res);
  sendSuccess(res, { message: "Logged out successfully" });
}

export async function me(req: Request, res: Response) {
  if (req?.user && req.user.id) {
    const data = await authService.userDetails(req?.user.id);
    return sendSuccess(res, data);
  }
  return sendError(res, "User not found", 404);
}

export async function forgotPassword(req: Request, res: Response) {
  const result = await authService.forgotPassword(req.body.email);
  sendSuccess(res, result);
}

export async function verifyOtp(req: Request, res: Response) {
  const userAgent = req.headers["user-agent"];
  const ipAddress = req.ip;
  const result = await authService.verifyOtp(
    req.body.email,
    req.body.otp,
    req.body.purpose,
    userAgent,
    ipAddress,
  );
  if ("accessToken" in result && result.accessToken && result.refreshToken) {
    setAuthCookies(res, result.accessToken, result.refreshToken);
  }
  sendSuccess(res, result);
}

export async function resetPassword(req: Request, res: Response) {
  const result = await authService.resetPassword({
    email: req.body.email,
    otp: req.body.otp,
    newPassword: req.body.newPassword,
  });
  sendSuccess(res, result);
}

export async function changePassword(req: Request, res: Response) {
  // req.user is populated by authMiddleware
  const userId = req.user!.id;
  const result = await authService.changePassword(
    userId,
    req.body.currentPassword,
    req.body.newPassword,
  );
  sendSuccess(res, result);
}

export async function getSessions(req: Request, res: Response) {
  const userId = req.user!.id;
  const result = await authService.getSessions(userId);
  sendSuccess(res, result);
}

export async function revokeSession(req: Request, res: Response) {
  const userId = req.user!.id;
  const sessionId = req.params.id as string;
  const result = await authService.revokeSession(userId, sessionId);
  sendSuccess(res, result);
}

export async function revokeAllSessions(req: Request, res: Response) {
  const userId = req.user!.id;
  const result = await authService.revokeAllSessions(userId);
  sendSuccess(res, result);
}

export async function updateProfile(req: Request, res: Response) {
  const userId = req.user!.id;
  const result = await authService.updateProfile(userId, req.body);
  sendSuccess(res, result);
}

export async function uploadAvatar(req: Request, res: Response) {
  const userId = req.user!.id;
  if (!req.file) return sendError(res, "No file uploaded", 400);
  const result = await authService.uploadAvatar(userId, req.file);
  sendSuccess(res, result);
}

export async function removeAvatar(req: Request, res: Response) {
  const userId = req.user!.id;
  const result = await authService.removeAvatar(userId);
  sendSuccess(res, result);
}
