import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Notification, NotificationStatus } from '../../domain/entities/notification.entity';
import { INotificationRepository } from '../../domain/repositories/notification.repository.interface';

@Injectable()
export class NotificationRepository implements INotificationRepository {
  constructor(
    @InjectRepository(Notification)
    private readonly repo: Repository<Notification>,
  ) {}

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

  async findByIdAndUserId(id: string, userId: string): Promise<Notification | null> {
    return this.repo.findOne({ where: { id, userId } });
  }

  async findByUserId(userId: string, skip: number, take: number): Promise<[Notification[], number]> {
    return this.repo.findAndCount({
      where: { userId },
      skip,
      take,
      order: { createdAt: 'DESC' },
    });
  }

  async countByUserIdAndStatus(userId: string, status: NotificationStatus): Promise<number> {
    return this.repo.count({ where: { userId, status } });
  }

  async create(data: Partial<Notification>): Promise<Notification> {
    const notification = this.repo.create(data);
    return this.repo.save(notification);
  }

  async save(notification: Notification): Promise<Notification> {
    return this.repo.save(notification);
  }

  async updateStatus(id: string, status: NotificationStatus, extra?: Partial<Notification>): Promise<void> {
    await this.repo.update(id, { status, ...extra });
  }

  async getStatusCounts(): Promise<Array<{ status: string; count: string }>> {
    return this.repo
      .createQueryBuilder('n')
      .select('n.status', 'status')
      .addSelect('COUNT(n.id)', 'count')
      .groupBy('n.status')
      .getRawMany();
  }

  async getChannelStatusCounts(): Promise<Array<{ channel: string; status: string; count: string }>> {
    return this.repo
      .createQueryBuilder('n')
      .select('n.channel', 'channel')
      .addSelect('n.status', 'status')
      .addSelect('COUNT(n.id)', 'count')
      .groupBy('n.channel')
      .addGroupBy('n.status')
      .getRawMany();
  }

  async countTodaySent(): Promise<number> {
    const result = await this.repo
      .createQueryBuilder('n')
      .select('COUNT(n.id)', 'count')
      .where('n.status = :status', { status: NotificationStatus.SENT })
      .andWhere('n.sent_at >= CURRENT_DATE')
      .getRawOne();
    return parseInt(result?.count || '0', 10);
  }
}
