import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Refund, RefundStatus } from '../../domain/entities/refund.entity';
import { IRefundRepository } from '../../domain/repositories/refund.repository.interface';

@Injectable()
export class RefundRepository implements IRefundRepository {
  constructor(
    @InjectRepository(Refund)
    private readonly repo: Repository<Refund>,
  ) {}

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

  async findAndCount(options: {
    status?: RefundStatus;
    page: number;
    limit: number;
  }): Promise<[Refund[], number]> {
    const qb = this.repo.createQueryBuilder('r');

    if (options.status) {
      qb.where('r.status = :status', { status: options.status });
    }

    qb.orderBy('r.created_at', 'DESC')
      .skip((options.page - 1) * options.limit)
      .take(options.limit);

    return qb.getManyAndCount();
  }

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

  async update(id: string, data: Partial<Refund>): Promise<void> {
    await this.repo.update(id, data);
  }

  async getRefundStats(): Promise<{ count: number; total: string }> {
    const result = await this.repo
      .createQueryBuilder('r')
      .select('COUNT(r.id)', 'count')
      .addSelect('COALESCE(SUM(r.amount::numeric), 0)', 'total')
      .getRawOne();

    return {
      count: parseInt(result?.count || '0', 10),
      total: result?.total || '0',
    };
  }

  async getCompletedRefundTotal(): Promise<string> {
    const result = await this.repo
      .createQueryBuilder('r')
      .select('COALESCE(SUM(r.amount::numeric), 0)', 'total')
      .where('r.status = :status', { status: RefundStatus.COMPLETED })
      .getRawOne();

    return result?.total || '0';
  }

  async getMonthlyRefundCounts(): Promise<
    Array<{ month: string; refunds: number }>
  > {
    const results = await this.repo
      .createQueryBuilder('r')
      .select("TO_CHAR(r.created_at, 'YYYY-MM')", 'month')
      .addSelect('COUNT(r.id)', 'refunds')
      .where("r.created_at >= NOW() - INTERVAL '12 months'")
      .groupBy("TO_CHAR(r.created_at, 'YYYY-MM')")
      .getRawMany();

    return results.map((row) => ({
      month: row.month,
      refunds: parseInt(row.refunds, 10),
    }));
  }
}
