<?php

namespace App\Services\Dashboard;

use App\Models\InventoryBalance;
use App\Models\PurchaseOrder;
use App\Models\StockTransfer;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Schema;

class WarehouseDashboardService
{
    /**
     * @return array<string, mixed>
     */
    public function build(?int $locationId, Collection $warehouseLocations): array
    {
        $locationIds = $locationId
            ? collect([$locationId])
            : $warehouseLocations->pluck('id');

        $onHandUnits = 0;
        $approxStockCost = 0.0;
        $lowStockProducts = 0;
        $lowStockItems = collect();
        $reservedUnits = 0;

        if (Schema::hasTable('inventory_balances') && $locationIds->isNotEmpty()) {
            $balances = InventoryBalance::query()
                ->with('product:id,name,purchase_price,image_path,is_active')
                ->whereIn('location_id', $locationIds)
                ->get();

            $onHandUnits = (int) $balances->sum('on_hand');
            $reservedUnits = (int) $balances->sum('reserved');
            $approxStockCost = (float) $balances->sum(function (InventoryBalance $b) {
                return $b->on_hand * (float) ($b->product?->purchase_price ?? 0);
            });

            $low = $balances->filter(fn (InventoryBalance $b) => ($b->on_hand - $b->reserved) <= 10);
            $lowStockProducts = $low->count();
            $lowStockItems = $low
                ->sortBy(fn (InventoryBalance $b) => $b->on_hand - $b->reserved)
                ->take(8)
                ->map(function (InventoryBalance $balance) {
                    return (object) [
                        'id' => $balance->product_id,
                        'name' => $balance->product?->name,
                        'current_stock' => max(0, $balance->on_hand - $balance->reserved),
                        'on_hand' => $balance->on_hand,
                        'reserved' => $balance->reserved,
                        'image_path' => $balance->product?->image_path,
                        'location_id' => $balance->location_id,
                    ];
                })
                ->values();
        }

        $openPurchaseOrders = 0;
        $recentPurchaseOrders = collect();
        if (Schema::hasTable('purchase_orders')) {
            $poQuery = PurchaseOrder::query()
                ->with(['supplier:id,name', 'location:id,name'])
                ->when($locationIds->isNotEmpty(), fn ($q) => $q->whereIn('location_id', $locationIds))
                ->whereIn('status', [
                    PurchaseOrder::STATUS_DRAFT,
                    PurchaseOrder::STATUS_ORDERED,
                    PurchaseOrder::STATUS_PARTIAL,
                ]);

            $openPurchaseOrders = (clone $poQuery)->count();
            $recentPurchaseOrders = (clone $poQuery)
                ->orderByDesc('id')
                ->take(6)
                ->get();
        }

        $openTransfersOut = 0;
        $transfersInTransit = 0;
        $recentTransfers = collect();
        if (Schema::hasTable('stock_transfers')) {
            $openTransfersOut = StockTransfer::query()
                ->when($locationIds->isNotEmpty(), fn ($q) => $q->whereIn('from_location_id', $locationIds))
                ->whereIn('status', [
                    StockTransfer::STATUS_DRAFT,
                    StockTransfer::STATUS_APPROVED,
                    StockTransfer::STATUS_IN_TRANSIT,
                ])
                ->count();

            $transfersInTransit = StockTransfer::query()
                ->when($locationIds->isNotEmpty(), fn ($q) => $q->whereIn('from_location_id', $locationIds))
                ->where('status', StockTransfer::STATUS_IN_TRANSIT)
                ->count();

            $recentTransfers = StockTransfer::query()
                ->with(['fromLocation:id,name', 'toLocation:id,name'])
                ->when($locationIds->isNotEmpty(), function ($q) use ($locationIds) {
                    $q->where(function ($q2) use ($locationIds) {
                        $q2->whereIn('from_location_id', $locationIds)
                            ->orWhereIn('to_location_id', $locationIds);
                    });
                })
                ->whereIn('status', [
                    StockTransfer::STATUS_DRAFT,
                    StockTransfer::STATUS_APPROVED,
                    StockTransfer::STATUS_IN_TRANSIT,
                ])
                ->orderByDesc('id')
                ->take(8)
                ->get();
        }

        $topValueSkus = collect();
        if (Schema::hasTable('inventory_balances') && $locationIds->isNotEmpty()) {
            $topValueSkus = InventoryBalance::query()
                ->with('product:id,name,purchase_price,sku')
                ->whereIn('location_id', $locationIds)
                ->where('on_hand', '>', 0)
                ->get()
                ->map(function (InventoryBalance $b) {
                    $unitCost = (float) ($b->product?->purchase_price ?? 0);

                    return (object) [
                        'name' => $b->product?->name,
                        'sku' => $b->product?->sku,
                        'on_hand' => $b->on_hand,
                        'value' => $b->on_hand * $unitCost,
                    ];
                })
                ->sortByDesc('value')
                ->take(5)
                ->values();
        }

        return [
            'onHandUnits' => $onHandUnits,
            'approxStockCost' => $approxStockCost,
            'reservedUnits' => $reservedUnits,
            'availableUnits' => max(0, $onHandUnits - $reservedUnits),
            'lowStockProducts' => $lowStockProducts,
            'lowStockItems' => $lowStockItems,
            'openPurchaseOrders' => $openPurchaseOrders,
            'recentPurchaseOrders' => $recentPurchaseOrders,
            'openTransfersOut' => $openTransfersOut,
            'transfersInTransit' => $transfersInTransit,
            'recentTransfers' => $recentTransfers,
            'topValueSkus' => $topValueSkus,
        ];
    }
}
