
import { Strategy as OIDCStrategy, Profile, VerifyCallback } from 'passport-openidconnect';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { AuthentikAuthService } from '../services/authentik-auth.service';

export interface AuthentikPayload {
    iss: string;                     // Issuer
    sub: string;                     // Subject (user ID)
    aud: string;                     // Audience (client ID)
    exp: number;                     // Expiration time (Unix)
    iat: number;                     // Issued at time (Unix)
    auth_time: number;               // Time of authentication (Unix)
    acr?: string;                    // Auth Context Class Reference
    amr?: string[];                  // Auth Method References (e.g., ['pwd'])
    email: string;
    email_verified: boolean;
    name?: string;
    given_name?: string;
    preferred_username?: string;
    nickname?: string;
    groups?: string[];
}

@Injectable()
export class AuthentikStrategy extends PassportStrategy(OIDCStrategy, 'openidconnect', 8) {
    constructor(private authentikAuthService: AuthentikAuthService) {
        super({
            issuer: process.env.AUTHENTIK_ISSUER || "ISSUER_MISSING",
            clientID: process.env.AUTHENTIK_CLIENT_ID || 'CLIENT_ID_MISSING',
            clientSecret: process.env.AUTHENTIK_CLIENT_SECRET || 'CLIENT_SECRET_MISSING',
            callbackURL: process.env.AUTHENTIK_CALLBACK_URL || 'CALLBACK_URL_MISSING',
            authorizationURL: process.env.AUTHENTIK_AUTH_URL || 'AUTH_URL_MISSING',
            tokenURL: process.env.AUTHENTIK_TOKEN_URL || 'TOKEN_URL_MISSING',
            userInfoURL: process.env.AUTHENTIK_USERINFO_URL || 'USERINFO_URL_MISSING',
            scope: ['openid', 'email', 'profile', 'offline_access'],
        },);
    }

    async validate(
        _issuer: string,
        profile: Profile,
        _context: any,
        _idToken: string,
        _accessToken: string,
        _refreshToken: string,
        _params: any,
        cb: VerifyCallback,
    ): Promise<any> {
        try {


            const components = _idToken.split('.');
            const payload = Buffer.from(components[1], "base64").toString('utf-8');
            const claims = JSON.parse(payload);

            if (!claims.email) return cb(new Error('Missing email in OIDC profile'), false);

            const user = await this.authentikAuthService.validateUser(claims.email);
            if (!user) return cb(new Error('User not found'), false);

            return cb(null, user);
        } catch (err) {
            return cb(err, false);
        }
    }
}
