import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DeepPartial } from 'typeorm';
import { PurchaseOrder } from '../entities/purchase-order.entity';
import { PurchaseOrderItem } from '../entities/purchase-order-item.entity';
import { Supplier } from '../entities/supplier.entity';
import { CreatePurchaseOrderDto } from '../dto/create-purchase-order.dto';
import { UpdatePurchaseOrderDto } from '../dto/update-purchase-order.dto';

@Injectable()
export class PurchaseOrderService {
  constructor(
    @InjectRepository(PurchaseOrder)
    private purchaseOrderRepository: Repository<PurchaseOrder>,
    @InjectRepository(PurchaseOrderItem)
    private purchaseOrderItemRepository: Repository<PurchaseOrderItem>,
    @InjectRepository(Supplier)
    private supplierRepository: Repository<Supplier>,
  ) {}

  async create(createDto: CreatePurchaseOrderDto): Promise<PurchaseOrder> {
    const supplier = await this.supplierRepository.findOne({
      where: { id: createDto.supplierId },
    });

    if (!supplier) {
      throw new Error('Supplier not found');
    }

    const purchaseOrder = this.purchaseOrderRepository.create({
      ...createDto,
      supplier,
      status: 'pending',
      createdAt: new Date(),
    });

    return this.purchaseOrderRepository.save(purchaseOrder);
  }

  async findAll(): Promise<PurchaseOrder[]> {
    return this.purchaseOrderRepository.find({
      relations: ['supplier', 'items'],
      order: {
        createdAt: 'DESC',
      },
    });
  }

  async findOne(id: string): Promise<PurchaseOrder> {
    return this.purchaseOrderRepository.findOne({
      where: { id },
      relations: ['supplier', 'items'],
    });
  }

  async update(id: string, updateDto: UpdatePurchaseOrderDto): Promise<PurchaseOrder> {
    const purchaseOrder = await this.findOne(id);
    Object.assign(purchaseOrder, updateDto);
    return this.purchaseOrderRepository.save(purchaseOrder);
  }

  async addItem(
    orderId: string,
    itemData: any,
  ): Promise<PurchaseOrderItem> {
    if (Array.isArray(itemData)) {
      throw new Error('addItem only supports a single item.');
    }
    const purchaseOrder = await this.findOne(orderId);
    const item: DeepPartial<PurchaseOrderItem> = {
      ...itemData,
      order: purchaseOrder,
    };
    return await this.purchaseOrderItemRepository.save(item);
  }

  async removeItem(itemId: string): Promise<void> {
    await this.purchaseOrderItemRepository.delete(itemId);
  }

  async getPurchaseOrderMetrics(): Promise<any> {
    const [totalOrders, completedOrders] = await Promise.all([
      this.purchaseOrderRepository.count(),
      this.purchaseOrderRepository.count({
        where: { status: 'completed' },
      }),
    ]);

    const totalSpent = await this.purchaseOrderRepository
      .createQueryBuilder('order')
      .select('SUM(order.totalAmount)', 'total')
      .getRawOne();

    return {
      totalOrders,
      completedOrders,
      totalSpent: totalSpent.total,
    };
  }

  async getSupplierOrders(supplierId: string): Promise<any[]> {
    return this.purchaseOrderRepository
      .createQueryBuilder('order')
      .leftJoinAndSelect('order.supplier', 'supplier')
      .where('supplier.id = :supplierId', { supplierId })
      .orderBy('order.createdAt', 'DESC')
      .getMany();
  }
}
