import { Request, Response } from "express";
import { RefreshToken } from "../../database/auth/refreshToken";
import { TokenBlacklist } from "../../database/auth/tokenBlacklist";
import { sendErrorResponse, sendSuccessResponse } from "../../utills/response";
import jwt from "jsonwebtoken";
import yenv from "yenv";
import { invalidateToken } from "../../utils/csrfTokenManager";

const env = yenv("env.yaml", { env: "development" });

/**
 * Logout user - blacklist access token and revoke refresh token
 */
export const logout = async (req: Request, res: Response) => {
    try {
        const { refreshToken } = req.body;
        const authHeader = req.headers.authorization;

        // Extract access token from Authorization header
        let accessToken: string | null = null;
        if (authHeader?.startsWith('Bearer ')) {
            accessToken = authHeader.substring(7);
        }

        // Revoke refresh token if provided
        if (refreshToken) {
            const tokenRecord = await RefreshToken.findOne({
                where: { token: refreshToken }
            });

            if (tokenRecord && !tokenRecord.isRevoked) {
                tokenRecord.isRevoked = true;
                await tokenRecord.save();
            }
        }

        // Blacklist access token if provided
        if (accessToken) {
            try {
                const decoded: any = jwt.verify(accessToken, env.JWT_SECRET);

                const blacklistedToken = TokenBlacklist.create({
                    token: accessToken,
                    userId: decoded.userId,
                    expiresAt: new Date(decoded.exp * 1000), // JWT exp is in seconds
                    reason: "logout",
                });
                await blacklistedToken.save();

                // Invalidate CSRF token for this user
                invalidateToken(decoded.userId.toString());
            } catch (err: any) {
                // Token might be invalid or expired, but we can still logout
                // Intentionally catching and continuing - logout should succeed regardless
                console.warn("Token verification failed during logout:", err.message);
            }
        }

        return sendSuccessResponse(res, 200, "Logged out successfully", {});
    } catch (err) {
        console.error("Logout error:", err);
        return sendErrorResponse(res, 500, "Error during logout");
    }
};

/**
 * Revoke all refresh tokens for a user (e.g., password change, security breach)
 */
export const revokeAllUserTokens = async (req: Request, res: Response) => {
    try {
        const { userId } = req.body;

        if (!userId) {
            return sendErrorResponse(res, 400, "User ID is required");
        }

        // Revoke all refresh tokens for this user
        await RefreshToken.createQueryBuilder()
            .update()
            .set({ isRevoked: true })
            .where({ userId, isRevoked: false })
            .execute();

        // Invalidate CSRF token for this user
        invalidateToken(userId.toString());

        return sendSuccessResponse(res, 200, "All user tokens revoked successfully", {});
    } catch (err) {
        console.error("Token revocation error:", err);
        return sendErrorResponse(res, 500, "Error revoking tokens");
    }
};
