import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ConfigService } from '@nestjs/config';
import {
  Strategy,
  type Profile,
  type StrategyOptions,
} from 'passport-google-oauth20';
import { AuthService } from '../auth.service';
import { CookieStateStore } from './cookie-state.store';
import type { PublicUser } from '../../user/user.service';

// 구글 OAuth 전략 — 콜백에서 프로필을 정규화해 AuthService 로 위임.
// 키 미설정 환경에서는 모듈이 이 전략을 등록하지 않는다(AuthModule 팩토리 가드).
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor(
    config: ConfigService,
    private readonly authService: AuthService,
  ) {
    // store: 쿠키 기반 state 저장소(OAuth CSRF 방지)
    const options: StrategyOptions & { store: CookieStateStore } = {
      clientID: config.getOrThrow<string>('GOOGLE_CLIENT_ID'),
      clientSecret: config.getOrThrow<string>('GOOGLE_CLIENT_SECRET'),
      callbackURL: config.getOrThrow<string>('GOOGLE_CALLBACK_URL'),
      scope: ['email', 'profile'],
      store: new CookieStateStore(),
    };
    super(options);
  }

  // 성공 시 PublicUser 반환 → @nestjs/passport 가 req.user 에 주입
  async validate(
    _accessToken: string,
    _refreshToken: string,
    profile: Profile,
  ): Promise<PublicUser> {
    const email = profile.emails?.[0]?.value ?? null;
    const name = profile.displayName || email?.split('@')[0] || '구글 사용자';
    const avatarUrl = profile.photos?.[0]?.value ?? null;
    // 구글이 이메일 소유를 검증했는지(email_verified)
    const json = profile._json as { email_verified?: boolean } | undefined;
    const emailVerified = json?.email_verified === true;
    return this.authService.validateOrCreateOAuthUser({
      provider: 'google',
      email,
      emailVerified,
      name,
      avatarUrl,
    });
  }
}
