/**
 * Supplier Service
 * Mecánicas Diesel - ERP Suite
 *
 * Business logic for supplier management.
 */

import { Repository, DataSource } from 'typeorm';
import { Supplier } from '../entities/supplier.entity';
import { Part } from '../entities/part.entity';

// DTOs
export interface CreateSupplierDto {
  name: string;
  legalName?: string;
  rfc?: string;
  contactName?: string;
  phone?: string;
  email?: string;
  address?: string;
  creditDays?: number;
  discountPct?: number;
  notes?: string;
}

export interface UpdateSupplierDto {
  name?: string;
  legalName?: string;
  rfc?: string;
  contactName?: string;
  phone?: string;
  email?: string;
  address?: string;
  creditDays?: number;
  discountPct?: number;
  notes?: string;
  isActive?: boolean;
}

export class SupplierService {
  private supplierRepository: Repository<Supplier>;
  private partRepository: Repository<Part>;

  constructor(dataSource: DataSource) {
    this.supplierRepository = dataSource.getRepository(Supplier);
    this.partRepository = dataSource.getRepository(Part);
  }

  /**
   * Create a new supplier
   */
  async create(tenantId: string, dto: CreateSupplierDto): Promise<Supplier> {
    const supplier = this.supplierRepository.create({
      tenantId,
      name: dto.name,
      legalName: dto.legalName,
      rfc: dto.rfc,
      contactName: dto.contactName,
      phone: dto.phone,
      email: dto.email,
      address: dto.address,
      creditDays: dto.creditDays || 0,
      discountPct: dto.discountPct || 0,
      notes: dto.notes,
      isActive: true,
    });

    return this.supplierRepository.save(supplier);
  }

  /**
   * Find supplier by ID
   */
  async findById(tenantId: string, id: string): Promise<Supplier | null> {
    return this.supplierRepository.findOne({
      where: { id, tenantId },
    });
  }

  /**
   * List suppliers
   */
  async findAll(
    tenantId: string,
    filters: { search?: string; isActive?: boolean } = {},
    pagination = { page: 1, limit: 20 }
  ) {
    const queryBuilder = this.supplierRepository.createQueryBuilder('supplier')
      .where('supplier.tenant_id = :tenantId', { tenantId });

    if (filters.isActive !== undefined) {
      queryBuilder.andWhere('supplier.is_active = :isActive', { isActive: filters.isActive });
    }
    if (filters.search) {
      queryBuilder.andWhere(
        '(supplier.name ILIKE :search OR supplier.contact_name ILIKE :search OR supplier.rfc ILIKE :search)',
        { search: `%${filters.search}%` }
      );
    }

    const skip = (pagination.page - 1) * pagination.limit;

    const [data, total] = await queryBuilder
      .orderBy('supplier.name', 'ASC')
      .skip(skip)
      .take(pagination.limit)
      .getManyAndCount();

    return {
      data,
      total,
      page: pagination.page,
      limit: pagination.limit,
      totalPages: Math.ceil(total / pagination.limit),
    };
  }

  /**
   * Update supplier
   */
  async update(tenantId: string, id: string, dto: UpdateSupplierDto): Promise<Supplier | null> {
    const supplier = await this.findById(tenantId, id);
    if (!supplier) return null;

    Object.assign(supplier, dto);
    return this.supplierRepository.save(supplier);
  }

  /**
   * Deactivate supplier
   */
  async deactivate(tenantId: string, id: string): Promise<boolean> {
    const supplier = await this.findById(tenantId, id);
    if (!supplier) return false;

    supplier.isActive = false;
    await this.supplierRepository.save(supplier);
    return true;
  }

  /**
   * Get supplier with part count
   */
  async getSupplierWithStats(tenantId: string, id: string): Promise<{
    supplier: Supplier;
    partCount: number;
    totalInventoryValue: number;
  } | null> {
    const supplier = await this.findById(tenantId, id);
    if (!supplier) return null;

    const [partCount, inventoryResult] = await Promise.all([
      this.partRepository
        .createQueryBuilder('part')
        .where('part.tenant_id = :tenantId', { tenantId })
        .andWhere('part.supplier_id = :supplierId', { supplierId: id })
        .getCount(),
      this.partRepository
        .createQueryBuilder('part')
        .select('SUM(part.current_stock * part.cost_price)', 'value')
        .where('part.tenant_id = :tenantId', { tenantId })
        .andWhere('part.supplier_id = :supplierId', { supplierId: id })
        .getRawOne(),
    ]);

    return {
      supplier,
      partCount,
      totalInventoryValue: parseFloat(inventoryResult?.value) || 0,
    };
  }

  /**
   * Search suppliers for autocomplete
   */
  async search(tenantId: string, query: string, limit = 10): Promise<Supplier[]> {
    return this.supplierRepository
      .createQueryBuilder('supplier')
      .where('supplier.tenant_id = :tenantId', { tenantId })
      .andWhere('supplier.is_active = true')
      .andWhere(
        '(supplier.name ILIKE :query OR supplier.rfc ILIKE :query)',
        { query: `%${query}%` }
      )
      .orderBy('supplier.name', 'ASC')
      .take(limit)
      .getMany();
  }
}
