"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoogleAuthProvider = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const base_auth_provider_1 = require("./base-auth.provider");
const auth_constants_1 = require("../../auth.constants");
const user_entity_1 = require("../../user/entities/user.entity");
const identity_entity_1 = require("../../user/entities/identity.entity");
let GoogleAuthProvider = class GoogleAuthProvider extends base_auth_provider_1.BaseAuthProvider {
    userRepository;
    authIdentityRepository;
    providerName = auth_constants_1.GOOGLE_AUTH_PROVIDER;
    skipMfa = true;
    googleConfig;
    constructor(userRepository, authIdentityRepository) {
        super(userRepository, authIdentityRepository);
        this.userRepository = userRepository;
        this.authIdentityRepository = authIdentityRepository;
        this.googleConfig = this.options.google;
        this.enabled = Boolean(this.googleConfig);
    }
    getClient(clientId, clientSecret) {
        try {
            const { OAuth2Client } = require('google-auth-library');
            return new OAuth2Client(clientId, clientSecret);
        }
        catch (error) {
            console.error('Failed to load google-auth-library. Please install it to use Google Auth.', error);
            throw new Error('Google Auth dependency missing: google-auth-library');
        }
    }
    async validate(credentials) {
        const currentConfig = this.googleConfig;
        if (!currentConfig) {
            throw new common_1.UnauthorizedException('Google authentication is not configured');
        }
        const { token } = credentials;
        const type = credentials.type || 'idToken';
        const client = this.getClient(currentConfig.clientId, currentConfig.clientSecret);
        let payload;
        if (type === 'idToken') {
            try {
                const ticket = await client.verifyIdToken({
                    idToken: token,
                    audience: currentConfig.clientId,
                });
                payload = ticket.getPayload();
            }
            catch (error) {
                console.error('Google ID Token validation failed:', error);
                throw new common_1.UnauthorizedException('Invalid Google ID token');
            }
        }
        else if (type === 'accessToken') {
            try {
                const tokenInfo = await client.getTokenInfo(token);
                const res = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
                    headers: {
                        Authorization: `Bearer ${token}`,
                    },
                });
                if (!res.ok) {
                    console.error('userinfo error status:', res.status, await res.text());
                    throw new common_1.UnauthorizedException('Failed to fetch Google user info');
                }
                const userInfo = (await res.json());
                payload = {
                    ...userInfo,
                    sub: tokenInfo.sub ?? userInfo.sub,
                    email: userInfo.email ?? tokenInfo.email,
                    name: userInfo.name,
                    picture: userInfo.picture,
                    locale: userInfo.locale,
                };
            }
            catch (error) {
                console.error('Google Access Token validation failed:', error);
                throw new common_1.UnauthorizedException('Invalid Google Access token');
            }
        }
        else {
            throw new common_1.UnauthorizedException('Missing or invalid Google token type (idToken | accessToken) in credentials');
        }
        if (!payload || !payload.sub) {
            throw new common_1.UnauthorizedException(`Invalid Google ${type} token`);
        }
        return {
            userId: payload.sub,
            email: payload.email || '',
            metadata: {
                name: payload.name,
                picture: payload.picture,
                locale: payload.locale,
            },
        };
    }
    getRequiredFields() {
        return ['token'];
    }
};
exports.GoogleAuthProvider = GoogleAuthProvider;
exports.GoogleAuthProvider = GoogleAuthProvider = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(user_entity_1.NestAuthUser)),
    __param(1, (0, typeorm_1.InjectRepository)(identity_entity_1.NestAuthIdentity)),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository])
], GoogleAuthProvider);
//# sourceMappingURL=google-auth.provider.js.map