import { Injectable } from '@nestjs/common';
import { DataSource, FindManyOptions, IsNull, ObjectLiteral, Repository } from 'typeorm';

import { Warehouse } from './entities/warehouse.entity';
import { WarehouseInventory } from './entities/warehouse-inventory.entity';

export interface WarehouseDashboard {
  totalWarehouses: number;
  totalInventory: number;
  receivedToday: number;
  // Inspection gate
  awaitingInspection: number;
  inspected: number;
  // Export branch
  stored: number;
  reserved: number;
  readyForLoading: number;
  loaded: number;
  dispatched: number;
  // Import branch
  readyForPickup: number;
  delivered: number;
}

@Injectable()
export class WarehouseDashboardService {
  constructor(private readonly dataSource: DataSource) {}

  private async safeCount<T extends ObjectLiteral>(
    repo: Repository<T>,
    options?: FindManyOptions<T>,
  ): Promise<number> {
    try {
      return await repo.count(options);
    } catch {
      return 0;
    }
  }

  private async safeReceivedToday(startOfToday: Date): Promise<number> {
    try {
      return await this.dataSource
        .getRepository(WarehouseInventory)
        .createQueryBuilder('inv')
        .where('inv.arrived_at >= :start', { start: startOfToday })
        .getCount();
    } catch {
      return 0;
    }
  }

  async getDashboard(): Promise<WarehouseDashboard> {
    const warehouseRepo = this.dataSource.getRepository(Warehouse);
    const inventoryRepo = this.dataSource.getRepository(WarehouseInventory);

    const startOfToday = new Date();
    startOfToday.setHours(0, 0, 0, 0);

    const [
      totalWarehouses,
      totalInventory,
      awaitingInspection,
      inspected,
      stored,
      reserved,
      readyForLoading,
      loaded,
      dispatched,
      readyForPickup,
      delivered,
      receivedToday,
    ] = await Promise.all([
      this.safeCount(warehouseRepo),
      this.safeCount(inventoryRepo),
      this.safeCount(inventoryRepo, { where: { status: 'RECEIVED', inspectionStatus: IsNull() } }),
      this.safeCount(inventoryRepo, { where: { inspectionStatus: 'PASSED' } }),
      this.safeCount(inventoryRepo, { where: { status: 'STORED' } }),
      this.safeCount(inventoryRepo, { where: { status: 'RESERVED' } }),
      this.safeCount(inventoryRepo, { where: { status: 'READY_FOR_LOADING' } }),
      this.safeCount(inventoryRepo, { where: { status: 'LOADED' } }),
      this.safeCount(inventoryRepo, { where: { status: 'DISPATCHED' } }),
      this.safeCount(inventoryRepo, { where: { status: 'READY_FOR_PICKUP' } }),
      this.safeCount(inventoryRepo, { where: { status: 'DELIVERED' } }),
      this.safeReceivedToday(startOfToday),
    ]);

    return {
      totalWarehouses,
      totalInventory,
      receivedToday,
      awaitingInspection,
      inspected,
      stored,
      reserved,
      readyForLoading,
      loaded,
      dispatched,
      readyForPickup,
      delivered,
    };
  }
}
