import { Inject, InternalServerErrorException } from '@nestjs/common';
import { type IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { DomainException, PrismaService, LoggerService } from '@modules/shared';
import {
  SUBSCRIPTION_REPOSITORY,
  type ISubscriptionRepository,
} from '../../../domain/repositories/subscription.repository';
import { GetBillingHistoryQuery } from './get-billing-history.query';

export interface BillingHistoryDto {
  subscription: {
    id: string;
    planTier: string;
    status: string;
    currentPeriodStart: Date;
    currentPeriodEnd: Date;
    cancelledAt: Date | null;
    createdAt: Date;
  } | null;
  payments: Array<{
    id: string;
    amountVND: string;
    status: string;
    provider: string;
    createdAt: Date;
  }>;
  total: number;
}

@QueryHandler(GetBillingHistoryQuery)
export class GetBillingHistoryHandler implements IQueryHandler<GetBillingHistoryQuery> {
  constructor(
    @Inject(SUBSCRIPTION_REPOSITORY)
    private readonly subscriptionRepo: ISubscriptionRepository,
    private readonly prisma: PrismaService,
    private readonly logger: LoggerService,
  ) {}

  async execute(query: GetBillingHistoryQuery): Promise<BillingHistoryDto> {
    try {
      const subscription = await this.subscriptionRepo.findByUserId(query.userId);

      // Fetch subscription-related payments
      const where = {
        userId: query.userId,
        type: 'SUBSCRIPTION' as const,
      };

      const [payments, total] = await Promise.all([
        this.prisma.payment.findMany({
          where,
          orderBy: { createdAt: 'desc' },
          take: query.limit ?? 20,
          skip: query.offset ?? 0,
        }),
        this.prisma.payment.count({ where }),
      ]);

      return {
        subscription: subscription
          ? {
              id: subscription.id,
              planTier: subscription.planTier,
              status: subscription.status,
              currentPeriodStart: subscription.currentPeriodStart,
              currentPeriodEnd: subscription.currentPeriodEnd,
              cancelledAt: subscription.cancelledAt,
              createdAt: subscription.createdAt,
            }
          : null,
        payments: payments.map((p) => ({
          id: p.id,
          amountVND: p.amountVND.toString(),
          status: p.status,
          provider: p.provider,
          createdAt: p.createdAt,
        })),
        total,
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to truy vấn lịch sử thanh toán: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể truy vấn lịch sử thanh toán. Vui lòng thử lại sau.');
    }
  }
}
