import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { Category } from 'src/category/entities/category.entity';
import { CategoryService } from 'src/category/category.service';
import { LANGUAGES } from 'src/shared/enum/languages.enum';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserResponse } from './dto/user-response';
import { ServerConstants } from 'src/constants/server.contants';

@Injectable()
/**
 * Service responsible for handling user-related operations.
 */
export class UserService {
  constructor(
    @InjectRepository(User) private userRepository: Repository<User>,
    private categoryService: CategoryService,
  ) {}

  async findOne(email: string): Promise<User> {
    const user = await this.userRepository.findOneBy({ email });
    return user;
  }

  async create(createUserDto: CreateUserDto) {
    await this.userRepository.insert(createUserDto);
  }

  async userExists(email: string): Promise<boolean> {
    const user = await this.userRepository.findOneBy({ email });
    if (user) return true;
    else return false;
  }

  async updatePassword(email: string, password: string) {
    await this.userRepository.update({ email }, { password });
  }

  async updatePreferedCategories(email: string, idCategories: number[]) {
    const user = await this.userRepository.findOneBy({ email });
    const categories: Category[] = [];
    for (const idCategory of idCategories) {
      const categoryEN: Category = await this.categoryService.findOne(idCategory);
      if (!categoryEN) throw new BadRequestException('Category not found');
      categoryEN.language = LANGUAGES.EN;
      const categoryES: Category = {
        ...categoryEN,
        language: LANGUAGES.ES,
      };
      categories.push(categoryEN);
      categories.push(categoryES);
    }
    user.preferedCategories = categories;
    await this.userRepository.save(user);
  }

  async getPreferedCategories(email: string, language: LANGUAGES): Promise<any[]> {
    const user: any = await this.userRepository.findOne({
      relations: {
        preferedCategories: true,
      },
      where: {
        email,
        preferedCategories: {
          language,
        },
      },
    });
    return user?.preferedCategories || [];
  }

  async confirmEmail(email: string) {
    try {
      await this.userRepository.update({ email }, { isEmailConfirmed: true });
    } catch (error) {
      throw new BadRequestException('Error confirming email');
    }
  }

  async updateInfo(email: string, updateUserDto: UpdateUserDto) {
    try {
      await this.userRepository.update({ email }, updateUserDto);
    } catch (error) {
      throw new BadRequestException('Error updating user info');
    }
  }

  async updatePhoto(email: string, photo: string) {
    try {
      await this.userRepository.update({ email }, { imageUrl: photo });
    } catch (error) {
      throw new BadRequestException('Error updating user photo');
    }
  }

  async getUserInfo(email: string) {
    try {
      const user = await this.userRepository.findOneBy({ email });
      user.imageUrl = `${ServerConstants.HOST}/user/${user.imageUrl}`;
      const res: UserResponse = {
        imageUrl: user.imageUrl,
        lastName: user.lastName,
        email: user.email,
        name: user.name,
        emailConfirmed: user.isEmailConfirmed,
      };
      return res;
    } catch (error) {
      throw new BadRequestException('Error getting user info');
    }
  }
}
