import { Repository, FindOptionsWhere } from 'typeorm';
import { PurchaseOrder } from '../entities';
import { CreatePurchaseOrderDto, UpdatePurchaseOrderDto } from '../dto';

// Export 3-Way Matching Service
export { ThreeWayMatchingService, MatchingSearchParams, InvoiceData, InvoiceLineData } from './three-way-matching.service';

export interface PurchaseSearchParams {
  tenantId: string;
  supplierId?: string;
  status?: string;
  buyerId?: string;
  limit?: number;
  offset?: number;
}

export class PurchasesService {
  constructor(private readonly orderRepository: Repository<PurchaseOrder>) {}

  async findAll(params: PurchaseSearchParams): Promise<{ data: PurchaseOrder[]; total: number }> {
    const { tenantId, supplierId, status, buyerId, limit = 50, offset = 0 } = params;
    const where: FindOptionsWhere<PurchaseOrder> = { tenantId };
    if (supplierId) where.supplierId = supplierId;
    if (status) where.status = status as any;
    if (buyerId) where.buyerId = buyerId;
    const [data, total] = await this.orderRepository.findAndCount({ where, take: limit, skip: offset, order: { createdAt: 'DESC' } });
    return { data, total };
  }

  async findOne(id: string, tenantId: string): Promise<PurchaseOrder | null> {
    return this.orderRepository.findOne({ where: { id, tenantId } });
  }

  async create(tenantId: string, dto: CreatePurchaseOrderDto, createdBy?: string): Promise<PurchaseOrder> {
    const count = await this.orderRepository.count({ where: { tenantId } });
    const orderNumber = `OC-${String(count + 1).padStart(6, '0')}`;
    const order = this.orderRepository.create({ ...dto, tenantId, orderNumber, createdBy, orderDate: new Date(), expectedDate: dto.expectedDate ? new Date(dto.expectedDate) : undefined });
    return this.orderRepository.save(order);
  }

  async update(id: string, tenantId: string, dto: UpdatePurchaseOrderDto, updatedBy?: string): Promise<PurchaseOrder | null> {
    const order = await this.findOne(id, tenantId);
    if (!order) return null;
    Object.assign(order, { ...dto, updatedBy });
    return this.orderRepository.save(order);
  }

  async delete(id: string, tenantId: string): Promise<boolean> {
    const result = await this.orderRepository.softDelete({ id, tenantId });
    return (result.affected ?? 0) > 0;
  }

  async confirmOrder(id: string, tenantId: string, userId?: string): Promise<PurchaseOrder | null> {
    const order = await this.findOne(id, tenantId);
    if (!order || order.status !== 'draft') return null;
    order.status = 'confirmed';
    order.updatedBy = userId;
    return this.orderRepository.save(order);
  }

  async receiveOrder(id: string, tenantId: string, userId?: string): Promise<PurchaseOrder | null> {
    const order = await this.findOne(id, tenantId);
    if (!order || !['sent', 'confirmed', 'partial'].includes(order.status)) return null;
    order.status = 'received';
    order.receivedDate = new Date();
    order.updatedBy = userId;
    return this.orderRepository.save(order);
  }
}
