import { PassportStrategy } from '@nestjs/passport';
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { IGoogleUser } from 'modules/auth/interfaces/google-user.interface';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  private logger = new Logger('GoogleStrategy');

  constructor(private configService: ConfigService) {
    super({
      passReqToCallback: true,
      clientID: configService.get('GOOGLE_CLIENT_ID'),
      clientSecret: configService.get('GOOGLE_CLIENT_SECRET'),
      callbackURL: configService.get('GOOGLE_CALLBACK_URL'),
      scope: ['email', 'profile'],
    });
  }

  async validate(request: any, accessToken: string, refreshToken: string, profile: any, done: VerifyCallback): Promise<IGoogleUser> {
    
    try {
      const { name, emails, photos, id } = profile;
      if (!profile || !profile.emails || !profile.emails[0]) {
        throw new Error('Invalid Google profile');
      }

      const user: IGoogleUser = {
        googleId: id,
        firstName: name?.givenName || '',
        lastName: name?.familyName || '',
        email: emails[0].value,
        picture: photos?.[0]?.value || '',
        accessToken,
      };

      if (request['query'] && request['query'].state) {
        this.logger.debug('State parameter detected:', request['query'].state);
        try {
          const stateBuffer = Buffer.from(request['query'].state, 'base64');
          const stateData = JSON.parse(stateBuffer.toString());
          // Attach origin info to the user object
          user['origin'] = stateData;
        } catch (e) {
          this.logger.error('Failed to parse state parameter:', e);
        }
      }
      

      if (done) {
        done(null, user);
      }
      return user;
    } catch (error) {
      this.logger.error('Error during Google authentication:', error);
      if (done) {
        done(error, null);
      }
      return null;
    }
  }
}
