import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../../entities/user.entity';
import { PlatformSettings } from '../../entities/platform-settings.entity';

export interface GoogleProfile {
  id: string;
  email: string;
  displayName: string;
  profilePhoto?: string | null;
}

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private readonly userRepo: Repository<User>,
    @InjectRepository(PlatformSettings)
    private readonly settingsRepo: Repository<PlatformSettings>,
  ) { }

  async findOrCreate(
    googleId: string,
    email: string,
    name: string,
    tokens?: { accessToken: string; refreshToken: string; expiry: number },
    profilePhoto?: string | null,
  ): Promise<User> {
    let user = await this.userRepo.findOne({ where: { googleId } });
    if (user) {
      if (tokens) {
        user.accessToken = tokens.accessToken;
        // Keep existing refresh token if Google did not return one (e.g. re-auth)
        if (tokens.refreshToken) {
          user.refreshToken = tokens.refreshToken;
        }
        user.tokenExpiry = tokens.expiry;
      }
      // Update profile photo if provided
      if (profilePhoto !== undefined) {
        user.profilePhoto = profilePhoto;
      }
      // Update last active timestamp
      user.lastActiveAt = new Date();
      await this.userRepo.save(user);
      return user;
    }
    user = this.userRepo.create({
      googleId,
      email,
      name,
      profilePhoto: profilePhoto ?? null,
      accessToken: tokens?.accessToken ?? null,
      refreshToken: tokens?.refreshToken ?? null,
      tokenExpiry: tokens?.expiry ?? null,
      lastActiveAt: new Date(),
    });
    return this.userRepo.save(user);
  }

  async findById(id: string): Promise<User | null> {
    return this.userRepo.findOne({ where: { id } });
  }

  async updateTokens(
    userId: string,
    accessToken: string | null,
    refreshToken: string | null,
    expiry: number | null,
  ): Promise<void> {
    await this.userRepo.update(userId, {
      accessToken: accessToken ?? undefined,
      refreshToken: refreshToken ?? undefined,
      tokenExpiry: expiry ?? undefined,
    });
  }

  async getEffectiveSettings(user: User): Promise<{ 
    maxBuildSizeMb: number; 
    cicdEnabled: boolean;
    slackEnabled: boolean;
  }> {
    const settings = await this.settingsRepo.findOne({ where: { id: 'global' } });
    return {
      maxBuildSizeMb: user.maxBuildSizeMb ?? settings?.maxBuildSizeMb ?? 500,
      cicdEnabled: user.cicdEnabled ?? settings?.cicdEnabled ?? true,
      slackEnabled: user.slackEnabled ?? settings?.slackEnabled ?? false,
    };
  }

  async updateUser(
    userId: string,
    updates: { name?: string; showUploaderInfo?: boolean },
  ): Promise<User> {
    const user = await this.userRepo.findOne({ where: { id: userId } });
    if (!user) throw new Error('User not found');

    if (updates.name !== undefined) {
      user.name = updates.name;
    }
    if (updates.showUploaderInfo !== undefined) {
      user.showUploaderInfo = updates.showUploaderInfo;
    }

    // Update last active timestamp
    user.lastActiveAt = new Date();

    return this.userRepo.save(user);
  }
}
