<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\OpnameItem;
use App\Models\Product;
use App\Models\StockOpname;
use App\Models\WarehouseStock;
use App\Services\StockService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class StockOpnameController extends Controller
{
    public function __construct(private StockService $stockService) {}

    /**
     * GET /api/stock-opnames
     */
    public function index(Request $request)
    {
        $opnames = StockOpname::with(['user:id,name', 'warehouse:id,code,name'])
            ->withCount('items')
            ->when($request->warehouse_id, fn($q) => $q->where('warehouse_id', $request->warehouse_id))
            ->latest()
            ->paginate(10);

        return response()->json($opnames->through(fn($o) => [
            'id'             => $o->id,
            'period'         => $o->period,
            'status'         => $o->status,
            'conducted_by'   => $o->user?->name ?? 'Unknown',
            'warehouse_id'   => $o->warehouse_id,
            'warehouse_name' => $o->warehouse?->name ?? '-',
            'items_count'    => $o->items_count,
            'created_at'     => $o->created_at->toISOString(),
            'completed_at'   => $o->completed_at?->toISOString(),
        ]));
    }

    /**
     * POST /api/stock-opnames
     * Buat opname baru, snapshot stok dari warehouse_stock.
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'period'       => ['required', 'string', 'max:50'],
            'warehouse_id' => ['required', 'exists:warehouses,id'],
            'notes'        => ['nullable', 'string'],
        ]);

        return DB::transaction(function () use ($data, $request) {
            $opname = StockOpname::create([
                'period'       => $data['period'],
                'status'       => 'in_progress',
                'user_id'      => $request->user()->id,
                'warehouse_id' => $data['warehouse_id'],
                'notes'        => $data['notes'] ?? null,
            ]);

            // Snapshot stok dari warehouse_stock untuk warehouse ini
            $warehouseStocks = WarehouseStock::with('product:id,sku,name')
                ->where('warehouse_id', $data['warehouse_id'])
                ->whereHas('product', fn($q) => $q->active())
                ->get();

            $items = $warehouseStocks->map(fn($ws) => [
                'stock_opname_id' => $opname->id,
                'product_id'      => $ws->product_id,
                'sku'             => $ws->product->sku,
                'product_name'    => $ws->product->name,
                'system_stock'    => $ws->current_stock,
                'physical_count'  => null,
                'difference'      => 0,
                'created_at'      => now(),
                'updated_at'      => now(),
            ]);

            OpnameItem::insert($items->toArray());

            return response()->json($opname->load(['user:id,name', 'warehouse:id,code,name', 'items']), 201);
        });
    }

    /**
     * GET /api/stock-opnames/{id}
     */
    public function show(StockOpname $stockOpname)
    {
        $stockOpname->load(['user:id,name', 'warehouse:id,code,name', 'items.product:id,sku,name,current_stock']);

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

    /**
     * PUT /api/stock-opnames/{id}
     * Update physical_count per item.
     */
    public function update(Request $request, StockOpname $stockOpname)
    {
        if ($stockOpname->status === 'completed') {
            return response()->json(['message' => 'Opname sudah selesai, tidak dapat diubah.'], 422);
        }

        $data = $request->validate([
            'items'                 => ['required', 'array'],
            'items.*.id'            => ['required', 'exists:opname_items,id'],
            'items.*.physical_count'=> ['required', 'integer', 'min:0'],
            'items.*.notes'         => ['nullable', 'string'],
        ]);

        foreach ($data['items'] as $item) {
            $opnameItem = OpnameItem::findOrFail($item['id']);
            $difference = $item['physical_count'] - $opnameItem->system_stock;

            $opnameItem->update([
                'physical_count' => $item['physical_count'],
                'difference'     => $difference,
                'notes'          => $item['notes'] ?? null,
            ]);
        }

        return response()->json($stockOpname->load(['user:id,name', 'warehouse:id,code,name', 'items']));
    }

    /**
     * PATCH /api/stock-opnames/{id}/complete
     * Finalisasi opname dan terapkan adjustment stok di warehouse tertentu.
     */
    public function complete(Request $request, StockOpname $stockOpname)
    {
        if ($stockOpname->status !== 'in_progress') {
            return response()->json(['message' => 'Opname tidak dalam status in_progress.'], 422);
        }

        return DB::transaction(function () use ($stockOpname, $request) {
            foreach ($stockOpname->items as $item) {
                if ($item->physical_count !== null && $item->difference !== 0) {
                    $product = Product::find($item->product_id);
                    if ($product) {
                        $this->stockService->adjust(
                            $product,
                            $item->physical_count,
                            'opname',
                            $request->user()->id,
                            "Opname: {$stockOpname->period}",
                            null,
                            null,
                            $stockOpname->warehouse_id
                        );
                    }
                }
            }

            $stockOpname->update([
                'status'       => 'completed',
                'completed_at' => now(),
            ]);

            return response()->json($stockOpname->load(['user:id,name', 'warehouse:id,code,name', 'items']));
        });
    }
}
