<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\StockMovement;
use App\Models\Product;
use App\Services\StockService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

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

    /**
     * GET /api/stock-movements
     */
    public function index(Request $request)
    {
        $movements = StockMovement::with(['product:id,sku,name', 'user:id,name', 'warehouse:id,code,name'])
            ->when($request->product_id, fn($q) => $q->where('product_id', $request->product_id))
            ->when($request->id,         fn($q) => $q->where('id', $request->id))
            ->when($request->reference_no, fn($q) => $q->where('reference_no', $request->reference_no))
            ->when($request->type,       fn($q) => $q->where('type', $request->type))
            ->when($request->reason,     fn($q) => $q->where('reason', $request->reason))
            ->when($request->warehouse_id, fn($q) => $q->where('warehouse_id', $request->warehouse_id))
            ->when($request->date_from,  fn($q) => $q->whereDate('created_at', '>=', $request->date_from))
            ->when($request->date_to,    fn($q) => $q->whereDate('created_at', '<=', $request->date_to))
            ->latest()
            ->paginate(30);

        return response()->json($movements->through(fn($m) => [
            'id'             => $m->id,
            'product_id'     => $m->product_id,
            'sku'            => $m->sku,
            'product_name'   => $m->product_name,
            'type'           => $m->type,
            'reason'         => $m->reason,
            'qty'            => $m->qty,
            'stock_before'   => $m->stock_before,
            'stock_after'    => $m->stock_after,
            'reference_no'   => $m->reference_no,
            'user_name'      => $m->user?->name ?? 'System',
            'warehouse_id'   => $m->warehouse_id,
            'warehouse_name' => $m->warehouse?->name ?? '-',
            'notes'          => $m->notes,
            'created_at'     => $m->created_at->toISOString(),
        ]));
    }

    /**
     * GET /api/stock-movements/surat-jalan
     */
    public function groupedBySuratJalan(Request $request)
    {
        $query = StockMovement::query()
            ->select(
                DB::raw('COALESCE(reference_no, id) as group_id'),
                DB::raw('MAX(reference_no) as reference_no'),
                DB::raw('MAX(type) as type'),
                DB::raw('MAX(user_id) as user_id'),
                DB::raw('MAX(warehouse_id) as warehouse_id'),
                DB::raw('SUM(qty) as total_qty'),
                DB::raw('MAX(created_at) as created_at')
            )
            ->groupBy(DB::raw('COALESCE(reference_no, id)'));

        $query->when($request->type, fn($q) => $q->having('type', $request->type));
        $query->when($request->warehouse_id, fn($q) => $q->having('warehouse_id', $request->warehouse_id));

        $paginated = $query->orderBy('created_at', 'desc')->paginate(20);

        $userIds = collect($paginated->items())->pluck('user_id')->unique()->filter();
        $users = \App\Models\User::whereIn('id', $userIds)->pluck('name', 'id');

        $warehouseIds = collect($paginated->items())->pluck('warehouse_id')->unique()->filter();
        $warehouses = \App\Models\Warehouse::whereIn('id', $warehouseIds)->pluck('name', 'id');

        return response()->json($paginated->through(fn($item) => [
            'group_id'       => (string)$item->group_id,
            'reference_no'   => $item->reference_no,
            'type'           => $item->type,
            'total_qty'      => (int)$item->total_qty,
            'user_name'      => $users[$item->user_id] ?? 'System',
            'warehouse_name' => $warehouses[$item->warehouse_id] ?? '-',
            'created_at'     => Carbon::parse($item->created_at)->toISOString(),
        ]));
    }

    /**
     * GET /api/stock-movements/next-reference
     * Returns the next auto-increment reference number for a given prefix.
     */
    public function nextReference(Request $request)
    {
        $prefix = $request->input('prefix', 'SJ-IN-' . now()->format('Ymd') . '-');
        $prefixLen = strlen($prefix) + 1;

        // Check stock_movements — only count entries with 1-4 digit suffix (not old HHmmss timestamps)
        $lastFromMovements = StockMovement::where('reference_no', 'like', "{$prefix}%")
            ->whereRaw("LENGTH(SUBSTRING(reference_no, ?)) <= 4", [$prefixLen])
            ->selectRaw("MAX(CAST(SUBSTRING(reference_no, ?) AS UNSIGNED)) as max_num", [$prefixLen])
            ->value('max_num') ?? 0;

        // Also check purchase_trackings for consistency
        $lastFromTrackings = \App\Models\PurchaseTracking::where('tracking_number', 'like', "{$prefix}%")
            ->whereRaw("LENGTH(SUBSTRING(tracking_number, ?)) <= 4", [$prefixLen])
            ->selectRaw("MAX(CAST(SUBSTRING(tracking_number, ?) AS UNSIGNED)) as max_num", [$prefixLen])
            ->value('max_num') ?? 0;

        $nextNum = max($lastFromMovements, $lastFromTrackings) + 1;
        $referenceNo = $prefix . str_pad($nextNum, 3, '0', STR_PAD_LEFT);

        return response()->json(['reference_no' => $referenceNo]);
    }

    /**
     * POST /api/stock-movements  (manual adjustment)
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'product_id'   => ['required', 'exists:products,id'],
            'new_stock'    => ['required', 'integer', 'min:0'],
            'reason'       => ['required', 'in:damage,internal,opname'],
            'notes'        => ['nullable', 'string'],
            'type'         => ['nullable', 'in:in,out,adjustment'],
            'reference_no' => ['nullable', 'string', 'max:100'],
            'warehouse_id' => ['required', 'exists:warehouses,id'],
        ]);

        $product  = Product::findOrFail($data['product_id']);
        $movement = $this->stockService->adjust(
            $product,
            $data['new_stock'],
            $data['reason'],
            $request->user()->id,
            $data['notes'] ?? null,
            $data['type'] ?? null,
            $data['reference_no'] ?? null,
            $data['warehouse_id']
        );

        return response()->json($movement, 201);
    }
}
