import { HttpStatus, Inject } from '@nestjs/common';
import { type IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { DomainException, ErrorCode } from '@modules/shared';
import { ESCROW_REPOSITORY, type IEscrowRepository } from '../../../domain/repositories/escrow.repository';
import { ORDER_REPOSITORY, type IOrderRepository } from '../../../domain/repositories/order.repository';
import { GetOrderStatusQuery } from './get-order-status.query';

export interface OrderStatusDto {
  id: string;
  buyerId: string;
  sellerId: string;
  listingId: string;
  status: string;
  amountVND: string;
  platformFeeVND: string;
  sellerPayoutVND: string;
  escrow: {
    id: string;
    status: string;
    heldAt: string | null;
    releasedAt: string | null;
  } | null;
  createdAt: string;
  updatedAt: string;
}

@QueryHandler(GetOrderStatusQuery)
export class GetOrderStatusHandler implements IQueryHandler<GetOrderStatusQuery> {
  constructor(
    @Inject(ORDER_REPOSITORY) private readonly orderRepo: IOrderRepository,
    @Inject(ESCROW_REPOSITORY) private readonly escrowRepo: IEscrowRepository,
  ) {}

  async execute(query: GetOrderStatusQuery): Promise<OrderStatusDto> {
    const order = await this.orderRepo.findById(query.orderId);
    if (!order) {
      throw new DomainException(ErrorCode.ORDER_NOT_FOUND, 'Đơn hàng không tồn tại', HttpStatus.NOT_FOUND);
    }

    // Only buyer or seller can view the order
    if (order.buyerId !== query.userId && order.sellerId !== query.userId) {
      throw new DomainException(
        ErrorCode.FORBIDDEN,
        'Bạn không có quyền xem đơn hàng này',
        HttpStatus.FORBIDDEN,
      );
    }

    const escrow = await this.escrowRepo.findByOrderId(order.id);

    return {
      id: order.id,
      buyerId: order.buyerId,
      sellerId: order.sellerId,
      listingId: order.listingId,
      status: order.status,
      amountVND: order.amount.value.toString(),
      platformFeeVND: order.platformFee.value.toString(),
      sellerPayoutVND: order.sellerPayout.value.toString(),
      escrow: escrow
        ? {
            id: escrow.id,
            status: escrow.status,
            heldAt: escrow.heldAt?.toISOString() ?? null,
            releasedAt: escrow.releasedAt?.toISOString() ?? null,
          }
        : null,
      createdAt: order.createdAt.toISOString(),
      updatedAt: order.updatedAt.toISOString(),
    };
  }
}
