import { Inject, InternalServerErrorException } from '@nestjs/common';
import { type IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { DomainException, LoggerService } from '@modules/shared';
import {
  PAYMENT_REPOSITORY,
  type IPaymentRepository,
} from '../../../domain/repositories/payment.repository';
import { ListTransactionsQuery } from './list-transactions.query';

export interface TransactionItemDto {
  id: string;
  provider: string;
  type: string;
  amountVND: string;
  status: string;
  providerTxId: string | null;
  createdAt: Date;
}

export interface TransactionListDto {
  items: TransactionItemDto[];
  total: number;
  limit: number;
  offset: number;
}

@QueryHandler(ListTransactionsQuery)
export class ListTransactionsHandler implements IQueryHandler<ListTransactionsQuery> {
  constructor(
    @Inject(PAYMENT_REPOSITORY)
    private readonly paymentRepo: IPaymentRepository,
    private readonly logger: LoggerService,
  ) {}

  async execute(query: ListTransactionsQuery): Promise<TransactionListDto> {
    try {
      const limit = Math.min(query.limit ?? 20, 100);
      const offset = query.offset ?? 0;

      const { items, total } = await this.paymentRepo.findByUserId(query.userId, {
        status: query.status,
        limit,
        offset,
      });

      return {
        items: items.map((payment) => ({
          id: payment.id,
          provider: payment.provider,
          type: payment.type,
          amountVND: payment.amount.value.toString(),
          status: payment.status,
          providerTxId: payment.providerTxId,
          createdAt: payment.createdAt,
        })),
        total,
        limit,
        offset,
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to list transactions: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể truy vấn danh sách giao dịch. Vui lòng thử lại sau');
    }
  }
}
