import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { UserEntity, UserType } from '../domain/entities/user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private userRepo: Repository<UserEntity>,
  ) {}

  async createAnonymousUser(fingerprint: string): Promise<UserEntity> {
    // Check if user with this fingerprint already exists
    const existingUser = await this.userRepo.findOne({
      where: { fingerprint },
    });

    if (existingUser) {
      // Update last active time and return existing user
      existingUser.lastActiveAt = new Date();
      return this.userRepo.save(existingUser);
    }

    // Create new anonymous user
    const user = this.userRepo.create({
      type: UserType.ANONYMOUS,
      fingerprint,
      lastActiveAt: new Date(),
    });

    return this.userRepo.save(user);
  }

  async findById(id: string): Promise<UserEntity> {
    const user = await this.userRepo.findOne({
      where: { id },
    });

    if (!user) {
      throw new NotFoundException('User not found');
    }

    return user;
  }

  async findByFingerprint(fingerprint: string): Promise<UserEntity | null> {
    return this.userRepo.findOne({
      where: { fingerprint },
    });
  }

  async findByPhone(phone: string): Promise<UserEntity | null> {
    return this.userRepo.findOne({
      where: { phone },
    });
  }

  async upgradeToRegistered(
    userId: string,
    phone: string,
  ): Promise<UserEntity> {
    const user = await this.findById(userId);

    // Check if phone is already registered
    const existingPhoneUser = await this.findByPhone(phone);
    if (existingPhoneUser && existingPhoneUser.id !== userId) {
      throw new Error('Phone number already registered');
    }

    user.type = UserType.REGISTERED;
    user.phone = phone;

    return this.userRepo.save(user);
  }

  async updateLastActive(userId: string): Promise<void> {
    await this.userRepo.update(userId, {
      lastActiveAt: new Date(),
    });
  }

  async updateProfile(
    userId: string,
    data: { nickname?: string; avatar?: string },
  ): Promise<UserEntity> {
    const user = await this.findById(userId);

    if (data.nickname !== undefined) {
      user.nickname = data.nickname;
    }
    if (data.avatar !== undefined) {
      user.avatar = data.avatar;
    }

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