<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\Warehouse;
use App\Models\WarehouseStock;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class WarehouseController extends Controller
{
    /**
     * GET /api/warehouses
     */
    public function index(Request $request)
    {
        // Auto-sync: create missing warehouse_stock entries for all active warehouses & products
        $this->syncMissingWarehouseStock();

        $warehouses = Warehouse::query()
            ->when($request->search, fn($q) => $q->where('name', 'like', "%{$request->search}%")
                ->orWhere('code', 'like', "%{$request->search}%"))
            ->when($request->boolean('active_only', false), fn($q) => $q->active())
            ->orderBy('code')
            ->get();

        return response()->json($warehouses->map(fn($wh) => $this->format($wh)));
    }

    /**
     * POST /api/warehouses
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'code'    => ['required', 'string', 'max:20', 'unique:warehouses'],
            'name'    => ['required', 'string', 'max:255'],
            'address' => ['nullable', 'string'],
            'phone'   => ['nullable', 'string', 'max:30'],
        ]);

        $warehouse = Warehouse::create($data);

        // Create warehouse_stock entries for all active products
        $products = Product::active()->get(['id', 'min_stock', 'sell_price']);
        $stockEntries = $products->map(fn($p) => [
            'warehouse_id'  => $warehouse->id,
            'product_id'    => $p->id,
            'current_stock' => 0,
            'min_stock'     => $p->min_stock,
            'sell_price'    => $p->sell_price,
            'created_at'    => now(),
            'updated_at'    => now(),
        ]);
        WarehouseStock::insert($stockEntries->toArray());

        return response()->json($this->format($warehouse), 201);
    }

    /**
     * GET /api/warehouses/{id}
     */
    public function show(Warehouse $warehouse)
    {
        // Auto-sync missing entries for this specific warehouse
        $this->syncMissingWarehouseStockForWarehouse($warehouse);

        $warehouse->load(['warehouseStock' => function ($q) {
            $q->whereHas('product', fn($pq) => $pq->where('is_active', true));
        }, 'warehouseStock.product']);

        return response()->json($this->formatDetailed($warehouse));
    }

    /**
     * PUT /api/warehouses/{id}
     */
    public function update(Request $request, Warehouse $warehouse)
    {
        $data = $request->validate([
            'code'      => ['sometimes', 'string', 'max:20', Rule::unique('warehouses')->ignore($warehouse->id)],
            'name'      => ['sometimes', 'string', 'max:255'],
            'address'   => ['nullable', 'string'],
            'phone'     => ['nullable', 'string', 'max:30'],
            'is_active' => ['sometimes', 'boolean'],
        ]);

        $warehouse->update($data);

        return response()->json($this->format($warehouse));
    }

    /**
     * DELETE /api/warehouses/{id}
     * Soft-delete (nonaktifkan) jika masih punya stok.
     * Hard-delete jika semua stok = 0 dan tidak ada transaksi.
     */
    public function destroy(Warehouse $warehouse)
    {
        $hasStock = $warehouse->warehouseStock()->where('current_stock', '>', 0)->exists();
        if ($hasStock) {
            return response()->json(['message' => 'Gudang masih memiliki stok. Pindahkan stok terlebih dahulu.'], 422);
        }

        // Check for related transactions (sales, purchases, stock movements)
        $hasTransactions = $warehouse->sales()->exists()
            || $warehouse->purchases()->exists()
            || $warehouse->stockMovements()->exists();

        if ($hasTransactions) {
            // Soft delete: just deactivate, keep history
            $warehouse->warehouseStock()->delete();
            $warehouse->update(['is_active' => false]);
            return response()->json(['message' => 'Gudang berhasil dinonaktifkan. Data transaksi tetap tersimpan.']);
        }

        // Hard delete: no transactions, safe to remove completely
        $warehouse->warehouseStock()->delete();
        $warehouse->delete();

        return response()->json(['message' => 'Gudang berhasil dihapus.']);
    }

    /**
     * GET /api/warehouses/{id}/stock
     */
    public function stock(Request $request, Warehouse $warehouse)
    {
        $stock = WarehouseStock::with('product:id,sku,name,category_id,unit,barcode,buy_price,sell_price')
            ->select('id', 'warehouse_id', 'product_id', 'current_stock', 'min_stock', 'sell_price')
            ->where('warehouse_id', $warehouse->id)
            ->whereHas('product', fn($q) => $q->where('is_active', true))
            ->when($request->search, function ($q) use ($request) {
                $q->whereHas('product', fn($pq) => $pq->where('name', 'like', "%{$request->search}%")
                    ->orWhere('sku', 'like', "%{$request->search}%"));
            })
            ->when($request->boolean('low_stock'), fn($q) => $q->lowStock())
            ->paginate($request->integer('per_page', 20));

        return response()->json($stock);
    }

    /**
     * Auto-create missing warehouse_stock entries for all active warehouses & products.
     * This fixes the gap where warehouses created before products (or vice versa)
     * don't have corresponding warehouse_stock rows.
     */
    private function syncMissingWarehouseStock(): void
    {
        $activeWarehouseIds = Warehouse::active()->pluck('id');
        $activeProducts = Product::active()->get(['id', 'min_stock', 'sell_price']);

        if ($activeWarehouseIds->isEmpty() || $activeProducts->isEmpty()) {
            return;
        }

        foreach ($activeWarehouseIds as $warehouseId) {
            $existingProductIds = WarehouseStock::where('warehouse_id', $warehouseId)
                ->pluck('product_id');

            $missingProducts = $activeProducts->whereNotIn('id', $existingProductIds);

            if ($missingProducts->isNotEmpty()) {
                $entries = $missingProducts->map(fn($p) => [
                    'warehouse_id'  => $warehouseId,
                    'product_id'    => $p->id,
                    'current_stock' => 0,
                    'min_stock'     => $p->min_stock,
                    'sell_price'    => $p->sell_price,
                    'created_at'    => now(),
                    'updated_at'    => now(),
                ]);
                WarehouseStock::insert($entries->values()->toArray());
            }
        }
    }

    /**
     * Sync missing warehouse_stock for a single warehouse.
     */
    private function syncMissingWarehouseStockForWarehouse(Warehouse $warehouse): void
    {
        $activeProducts = Product::active()->get(['id', 'min_stock', 'sell_price']);
        $existingProductIds = WarehouseStock::where('warehouse_id', $warehouse->id)
            ->pluck('product_id');

        $missingProducts = $activeProducts->whereNotIn('id', $existingProductIds);

        if ($missingProducts->isNotEmpty()) {
            $entries = $missingProducts->map(fn($p) => [
                'warehouse_id'  => $warehouse->id,
                'product_id'    => $p->id,
                'current_stock' => 0,
                'min_stock'     => $p->min_stock,
                'sell_price'    => $p->sell_price,
                'created_at'    => now(),
                'updated_at'    => now(),
            ]);
            WarehouseStock::insert($entries->values()->toArray());
        }
    }

    private function format(Warehouse $wh): array
    {
        return [
            'id'            => $wh->id,
            'code'          => $wh->code,
            'name'          => $wh->name,
            'address'       => $wh->address,
            'phone'         => $wh->phone,
            'is_active'     => $wh->is_active,
            // Only count products that are still active
            'total_products'=> $wh->warehouseStock()
                ->whereHas('product', fn($q) => $q->where('is_active', true))
                ->count(),
            'total_stock'   => $wh->warehouseStock()
                ->whereHas('product', fn($q) => $q->where('is_active', true))
                ->sum('current_stock'),
            'low_stock'     => $wh->warehouseStock()
                ->whereHas('product', fn($q) => $q->where('is_active', true))
                ->lowStock()
                ->count(),
            'created_at'    => $wh->created_at->toISOString(),
        ];
    }

    private function formatDetailed(Warehouse $wh): array
    {
        $base = $this->format($wh);
        $base['stock'] = $wh->warehouseStock->map(fn($ws) => [
            'product_id'    => $ws->product_id,
            'sku'           => $ws->product->sku ?? '-',
            'product_name'  => $ws->product->name ?? '-',
            'current_stock' => $ws->current_stock,
            'min_stock'     => $ws->min_stock,
            'sell_price'    => $ws->sell_price ?? $ws->product->sell_price ?? 0,
        ]);
        return $base;
    }
}
