// ============================================================
// GoogleService — Google 登录 / 注册业务逻辑
//
// Google sub 字段 = 用户全局唯一 ID，直接作为 openid 存储
// 每次登录同步 email、nickname（name）、avatarUrl（picture）
// ============================================================

import { Injectable, Logger, Inject } from '@nestjs/common';
import { GoogleProvider } from '../../infrastructure/google/google.provider';
import { SOCIAL_ACCOUNT_REPOSITORY, ISocialAccountRepository } from '../../domain/repositories/social-account.repository.interface';
import { SocialProvider } from '../../domain/entities/social-account.entity';
import { USER_REPOSITORY, IUserRepository } from '../../domain/repositories/user.repository.interface';
import { TokenService } from './token.service';
import { EventPublisherService } from './event-publisher.service';
import { UserRole, UserStatus } from '../../domain/entities/user.entity';
import { AuthResult } from './auth.service';
import { Password } from '../../domain/value-objects/password.vo';
import * as crypto from 'crypto';

@Injectable()
export class GoogleService {
  private readonly logger = new Logger('GoogleService');

  constructor(
    private readonly googleProvider: GoogleProvider,
    @Inject(SOCIAL_ACCOUNT_REPOSITORY)
    private readonly socialAccountRepo: ISocialAccountRepository,
    @Inject(USER_REPOSITORY)
    private readonly userRepo: IUserRepository,
    private readonly tokenService: TokenService,
    private readonly eventPublisher: EventPublisherService,
  ) {}

  async loginOrRegister(
    idToken: string,
    referralCode?: string,
    deviceInfo?: string,
    ipAddress?: string,
  ): Promise<AuthResult> {
    // Step 1: 验证 Google ID Token
    const googleUser = await this.googleProvider.verifyIdToken(idToken);
    const { sub, email, name, picture } = googleUser;

    const nickname = name?.trim() || `google_${sub.slice(-6)}`;
    const avatarUrl = picture || null;
    const rawData = googleUser as unknown as Record<string, unknown>;

    // Step 2: 查找已有绑定（Google sub 全局唯一）
    let socialAccount = await this.socialAccountRepo.findByProviderAndOpenid(
      SocialProvider.GOOGLE,
      sub,
    );

    if (socialAccount) {
      // ── 老用户 ──
      socialAccount.nickname = nickname;
      socialAccount.avatarUrl = avatarUrl;
      await this.socialAccountRepo.save(socialAccount);

      const user = await this.userRepo.findById(socialAccount.userId);
      if (!user || user.status !== UserStatus.ACTIVE) {
        throw new Error('账号已禁用，请联系客服');
      }

      user.recordLoginSuccess(ipAddress);
      await this.userRepo.save(user);

      const tokens = await this.tokenService.generateTokenPair(user.id, user.role, user.kycLevel);
      await this.tokenService.storeRefreshToken(user.id, tokens.refreshToken, deviceInfo, ipAddress);

      await this.eventPublisher.publishUserLoggedIn({
        userId: user.id,
        ipAddress: ipAddress || null,
        deviceInfo: deviceInfo || null,
        timestamp: new Date().toISOString(),
      });

      this.logger.log(`Google login: userId=${user.id} sub=${sub.slice(0, 6)}...`);
      return { user: this.toUserDto(user), tokens };
    }

    // ── 新用户 ──
    const randomPw = await Password.create(crypto.randomBytes(32).toString('hex'));
    const randomPasswordHash = randomPw.value;

    const user = await this.userRepo.create({
      phone: null,
      email: email || null,
      passwordHash: randomPasswordHash,
      nickname,
      role: UserRole.USER,
      status: UserStatus.ACTIVE,
      kycLevel: 0,
      walletMode: 'standard',
    });

    await this.socialAccountRepo.create({
      userId: user.id,
      provider: SocialProvider.GOOGLE,
      openid: sub,
      nickname,
      avatarUrl: avatarUrl || undefined,
      rawData,
    });

    const tokens = await this.tokenService.generateTokenPair(user.id, user.role, user.kycLevel);
    await this.tokenService.storeRefreshToken(user.id, tokens.refreshToken, deviceInfo, ipAddress);

    await this.eventPublisher.publishUserRegistered({
      userId: user.id,
      phone: null,
      email: email || null,
      role: user.role,
      referralCode: referralCode?.toUpperCase() ?? null,
      timestamp: new Date().toISOString(),
    });

    this.logger.log(`Google new user registered: userId=${user.id} sub=${sub.slice(0, 6)}...`);
    return { user: this.toUserDto(user), tokens };
  }

  private toUserDto(user: any) {
    return {
      id: user.id,
      phone: user.phone ?? null,
      email: user.email ?? null,
      nickname: user.nickname ?? null,
      avatarUrl: user.avatarUrl ?? null,
      role: user.role,
      kycLevel: user.kycLevel,
      walletMode: user.walletMode,
    };
  }
}
