import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In } from 'typeorm';
import { UserTag } from '../../domain/entities/user-tag.entity';
import { IUserTagRepository } from '../../domain/repositories/user-tag.repository.interface';

@Injectable()
export class UserTagRepositoryImpl implements IUserTagRepository {
  constructor(
    @InjectRepository(UserTag)
    private readonly repo: Repository<UserTag>,
  ) {}

  async findTagsByUserId(userId: string): Promise<string[]> {
    const tags = await this.repo.find({ where: { userId }, select: ['tag'] });
    return tags.map((t) => t.tag);
  }

  async findUserIdsByTag(tag: string): Promise<string[]> {
    const rows = await this.repo.find({ where: { tag }, select: ['userId'] });
    return rows.map((r) => r.userId);
  }

  async addTag(userId: string, tag: string): Promise<void> {
    await this.repo
      .createQueryBuilder()
      .insert()
      .into(UserTag)
      .values({ userId, tag })
      .orIgnore()
      .execute();
  }

  async removeTags(userId: string, tags: string[]): Promise<void> {
    if (tags.length === 0) return;
    await this.repo.delete({ userId, tag: In(tags) });
  }

  async syncTags(userId: string, tags: string[]): Promise<void> {
    // Delete all existing tags for this user
    await this.repo.delete({ userId });

    if (tags.length === 0) return;

    // Insert new tags
    const values = tags.map((tag) => ({ userId, tag }));
    await this.repo
      .createQueryBuilder()
      .insert()
      .into(UserTag)
      .values(values)
      .orIgnore()
      .execute();
  }

  async getAllTags(): Promise<Array<{ tag: string; count: number }>> {
    const result = await this.repo
      .createQueryBuilder('ut')
      .select('ut.tag', 'tag')
      .addSelect('COUNT(ut.id)', 'count')
      .groupBy('ut.tag')
      .orderBy('count', 'DESC')
      .getRawMany();

    return result.map((r) => ({ tag: r.tag, count: parseInt(r.count, 10) }));
  }
}
