import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { OrderEntity, OrderStatus, ServiceType } from '../domain/entities/order.entity';

// 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 CreateOrderDto {
  userId: string;
  serviceType: ServiceType;
  serviceCategory?: string;
  conversationId?: string;
}

@Injectable()
export class OrderService {
  constructor(
    @InjectRepository(OrderEntity)
    private orderRepo: Repository<OrderEntity>,
  ) {}

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

    const order = this.orderRepo.create({
      userId: dto.userId,
      serviceType: dto.serviceType,
      serviceCategory: dto.serviceCategory,
      conversationId: dto.conversationId,
      amount: price,
      currency: 'CNY',
      status: OrderStatus.CREATED,
    });

    return this.orderRepo.save(order);
  }

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

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

    return order;
  }

  async findByUserId(userId: string): Promise<OrderEntity[]> {
    return this.orderRepo.find({
      where: { userId },
      order: { createdAt: 'DESC' },
    });
  }

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

    if (status === OrderStatus.PAID) {
      order.paidAt = new Date();
    } else if (status === OrderStatus.COMPLETED) {
      order.completedAt = new Date();
    }

    return this.orderRepo.save(order);
  }

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

    if (order.status !== OrderStatus.CREATED && order.status !== OrderStatus.PENDING_PAYMENT) {
      throw new BadRequestException('Order cannot be marked as paid');
    }

    order.status = OrderStatus.PAID;
    order.paymentId = paymentId;
    order.paymentMethod = paymentMethod;
    order.paidAt = new Date();

    return this.orderRepo.save(order);
  }

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

    if (order.status === OrderStatus.PAID || order.status === OrderStatus.COMPLETED) {
      throw new BadRequestException('Cannot cancel paid or completed order');
    }

    order.status = OrderStatus.CANCELLED;
    return this.orderRepo.save(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
  }
}
