import { Injectable, Inject, NotFoundException, BadRequestException } from '@nestjs/common';
import { OrderEntity, OrderStatus, ServiceType } from '../../domain/entities/order.entity';
import { IOrderRepository, ORDER_REPOSITORY } from '../../domain/repositories/order.repository.interface';

// Default pricing
const SERVICE_PRICING: Record<string, Record<string, number>> = {
  ASSESSMENT: {
    QMAS: 99,
    GEP: 99,
    IANG: 79,
    TTPS: 99,
    CIES: 199,
    TECHTAS: 99,
  },
};

export interface CreateOrderParams {
  userId: string;
  serviceType: ServiceType;
  serviceCategory?: string;
  conversationId?: string;
}

@Injectable()
export class OrderService {
  constructor(
    @Inject(ORDER_REPOSITORY)
    private readonly orderRepo: IOrderRepository,
  ) {}

  async createOrder(params: CreateOrderParams): Promise<OrderEntity> {
    // Get price based on service type and category
    const price = this.getPrice(params.serviceType, params.serviceCategory);

    const order = OrderEntity.create({
      userId: params.userId,
      serviceType: params.serviceType,
      serviceCategory: params.serviceCategory,
      conversationId: params.conversationId,
      amount: price,
      currency: 'CNY',
    });

    return this.orderRepo.save(order);
  }

  async findById(orderId: string): Promise<OrderEntity> {
    const order = await this.orderRepo.findById(orderId);

    if (!order) {
      throw new NotFoundException('Order not found');
    }

    return order;
  }

  async findByUserId(userId: string): Promise<OrderEntity[]> {
    return this.orderRepo.findByUserId(userId);
  }

  async updateStatus(orderId: string, status: OrderStatus): Promise<OrderEntity> {
    const order = await this.findById(orderId);
    order.updateStatus(status);
    return this.orderRepo.update(order);
  }

  async markAsPaid(orderId: string, paymentId: string, paymentMethod: string): Promise<OrderEntity> {
    const order = await this.findById(orderId);

    if (!order.canBePaid()) {
      throw new BadRequestException('Order cannot be marked as paid');
    }

    order.markAsPaid(paymentId, paymentMethod);
    return this.orderRepo.update(order);
  }

  async cancelOrder(orderId: string): Promise<OrderEntity> {
    const order = await this.findById(orderId);

    if (!order.canBeCancelled()) {
      throw new BadRequestException('Cannot cancel paid or completed order');
    }

    order.cancel();
    return this.orderRepo.update(order);
  }

  private getPrice(serviceType: ServiceType, category?: string): number {
    const servicePricing = SERVICE_PRICING[serviceType];
    if (!servicePricing) {
      return 99; // Default price
    }

    if (category && servicePricing[category]) {
      return servicePricing[category];
    }

    return 99; // Default price
  }
}
