<?php

namespace App\Modules\Procurement\Services;

use App\Modules\Procurement\Contracts\ProcurementServiceInterface;
use App\Modules\Procurement\Models\PurchaseOrder;
use Illuminate\Support\Collection;

class ProcurementService implements ProcurementServiceInterface
{
    public function getPurchaseOrdersByDate(string $start, string $end, array $statuses = ['received', 'completed']): Collection
    {
        return PurchaseOrder::with(['vendor'])
            ->whereIn('status', $statuses)
            ->whereBetween('created_at', [$start . ' 00:00:00', $end . ' 23:59:59'])
            ->get();
    }

    public function getPurchaseOrdersByIds(array $ids, array $with = []): Collection
    {
        return PurchaseOrder::whereIn('id', $ids)->with($with)->get();
    }

    public function getDashboardStats(): array
    {
        return [
            'vendorsCount' => \App\Modules\Procurement\Models\Vendor::count(),
            'purchaseOrdersCount' => PurchaseOrder::count(),
            'pendingOrdersCount' => PurchaseOrder::whereIn('status', ['approved', 'partial'])->count(), // 改為真正待進貨的狀態
        ];
    }

    public function updateReceivedQuantity(int $poItemId, float $quantity): void
    {
        $item = \App\Modules\Procurement\Models\PurchaseOrderItem::findOrFail($poItemId);
        $item->increment('received_quantity', $quantity);
        $item->refresh();

        // Check PO status
        $po = $item->purchaseOrder;
        
        // Load items to check completion
        $po->load('items');
        
        $allReceived = $po->items->every(function ($i) {
            return $i->received_quantity >= $i->quantity;
        });

        $anyReceived = $po->items->contains(function ($i) {
            return $i->received_quantity > 0;
        });

        if ($allReceived) {
            $po->status = 'completed'; // or 'received' based on workflow
        } elseif ($anyReceived) {
            $po->status = 'partial';
        }
        
        $po->save();
    }

    public function searchPendingPurchaseOrders(string $query): Collection
    {
        return PurchaseOrder::with(['vendor', 'items'])
            ->whereIn('status', ['approved', 'partial'])
            ->where(function($q) use ($query) {
                $q->where('code', 'like', "%{$query}%")
                  ->orWhereHas('vendor', function($vq) use ($query) {
                      $vq->where('name', 'like', "%{$query}%");
                  });
            })
            ->limit(20)
            ->get();
    }

    public function searchVendors(string $query): Collection
    {
        return \App\Modules\Procurement\Models\Vendor::where('name', 'like', "%{$query}%")
            ->orWhere('code', 'like', "%{$query}%")
            ->limit(20)
            ->get(['id', 'name', 'code']);
    }

    public function getPendingPurchaseOrders(): Collection
    {
        return PurchaseOrder::with(['vendor', 'items'])
            ->whereIn('status', ['approved', 'partial'])
            ->orderBy('created_at', 'desc')
            ->limit(50)
            ->get();
    }

    public function getAllVendors(): Collection
    {
        return \App\Modules\Procurement\Models\Vendor::orderBy('name')->get(['id', 'name', 'code']);
    }

    public function getVendorsByIds(array $ids): Collection
    {
        return \App\Modules\Procurement\Models\Vendor::whereIn('id', $ids)->get(['id', 'name', 'code']);
    }

    public function attachProductToVendor(int $vendorId, int $productId, ?float $lastPrice): void
    {
        \Illuminate\Support\Facades\DB::table('product_vendor')->insert([
            'vendor_id' => $vendorId,
            'product_id' => $productId,
            'last_price' => $lastPrice,
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    public function updateVendorProductPrice(int $vendorId, int $productId, ?float $lastPrice): void
    {
        \Illuminate\Support\Facades\DB::table('product_vendor')
            ->where('vendor_id', $vendorId)
            ->where('product_id', $productId)
            ->update([
                'last_price' => $lastPrice,
                'updated_at' => now(),
            ]);
    }

    public function checkVendorHasProduct(int $vendorId, int $productId): bool
    {
        return \Illuminate\Support\Facades\DB::table('product_vendor')
            ->where('vendor_id', $vendorId)
            ->where('product_id', $productId)
            ->exists();
    }

    public function getVendorProductPrice(int $vendorId, int $productId): ?float
    {
        $pivot = \Illuminate\Support\Facades\DB::table('product_vendor')
            ->where('vendor_id', $vendorId)
            ->where('product_id', $productId)
            ->first();

        return $pivot ? (float) $pivot->last_price : null;
    }

    public function detachProductFromVendor(int $vendorId, int $productId): void
    {
        \Illuminate\Support\Facades\DB::table('product_vendor')
            ->where('vendor_id', $vendorId)
            ->where('product_id', $productId)
            ->delete();
    }

    public function syncVendorProducts(int $vendorId, array $productsData): void
    {
        \Illuminate\Support\Facades\DB::transaction(function () use ($vendorId, $productsData) {
            $existingPivots = \Illuminate\Support\Facades\DB::table('product_vendor')
                ->where('vendor_id', $vendorId)
                ->get();
            
            $existingProductIds = $existingPivots->pluck('product_id')->toArray();
            $newProductIds = array_column($productsData, 'product_id');
            
            $toDelete = array_diff($existingProductIds, $newProductIds);
            
            if (!empty($toDelete)) {
                \Illuminate\Support\Facades\DB::table('product_vendor')
                    ->where('vendor_id', $vendorId)
                    ->whereIn('product_id', $toDelete)
                    ->delete();
            }
            
            foreach ($productsData as $data) {
                $exists = in_array($data['product_id'], $existingProductIds);
                
                if ($exists) {
                    \Illuminate\Support\Facades\DB::table('product_vendor')
                        ->where('vendor_id', $vendorId)
                        ->where('product_id', $data['product_id'])
                        ->update([
                            'last_price' => $data['last_price'] ?? null,
                            'updated_at' => now(),
                        ]);
                } else {
                    \Illuminate\Support\Facades\DB::table('product_vendor')
                        ->insert([
                            'vendor_id' => $vendorId,
                            'product_id' => $data['product_id'],
                            'last_price' => $data['last_price'] ?? null,
                            'created_at' => now(),
                            'updated_at' => now(),
                        ]);
                }
            }
        });
    }
}
