<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\WarehouseResource;
use App\Models\Warehouse;
use App\Support\CrmModuleManager;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class WarehouseController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Warehouse::class, 'warehouse');
    }

    public function index(Request $request)
    {
        $search = trim((string) $request->input('q', ''));
        $status = trim((string) $request->input('status', ''));
        $managerId = $request->integer('manager_id');

        $warehouses = Warehouse::query()
            ->with('manager')
            ->when($search !== '', function ($query) use ($search): void {
                $query->where(function ($sub) use ($search): void {
                    $sub->where('name', 'like', "%{$search}%")
                        ->orWhere('code', 'like', "%{$search}%")
                        ->orWhere('location', 'like', "%{$search}%")
                        ->orWhere('description', 'like', "%{$search}%");
                });
            })
            ->when(in_array($status, ['active', 'inactive'], true), fn ($query) => $query->where('status', $status))
            ->when($managerId > 0, fn ($query) => $query->where('manager_id', $managerId))
            ->latest('id')
            ->paginate(20)
            ->withQueryString();

        return WarehouseResource::collection($warehouses);
    }

    public function store(Request $request, CrmModuleManager $moduleManager)
    {
        $payload = $this->validatedData($request);
        $payload = $moduleManager->applyPayloadHooks('warehouses.store', $payload, [
            'hook' => 'warehouses.store',
            'user_id' => $request->user()->id,
            'source' => 'api',
        ], array_keys($payload));

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

        return WarehouseResource::make($warehouse->load('manager'))
            ->response()
            ->setStatusCode(201);
    }

    public function show(Warehouse $warehouse): WarehouseResource
    {
        return WarehouseResource::make($warehouse->load([
            'manager',
            'addresses' => fn ($query) => $query->with('creator')->orderBy('y')->orderBy('x')->orderBy('id'),
        ]));
    }

    public function update(Request $request, Warehouse $warehouse, CrmModuleManager $moduleManager): WarehouseResource
    {
        $payload = $this->validatedData($request, $warehouse);
        $payload = $moduleManager->applyPayloadHooks('warehouses.update', $payload, [
            'hook' => 'warehouses.update',
            'user_id' => $request->user()->id,
            'warehouse_id' => $warehouse->id,
            'source' => 'api',
        ], array_keys($payload));

        $warehouse->update($payload);

        return WarehouseResource::make($warehouse->load('manager'));
    }

    public function destroy(Warehouse $warehouse)
    {
        $warehouse->delete();

        return response()->noContent();
    }

    public function updateMap(Request $request, Warehouse $warehouse, CrmModuleManager $moduleManager): WarehouseResource
    {
        $this->authorize('update', $warehouse);

        $payload = $request->validate([
            'map_rows' => ['required', 'integer', 'min:1', 'max:200'],
            'map_columns' => ['required', 'integer', 'min:1', 'max:200'],
        ]);

        $payload['map_rows'] = (int) $payload['map_rows'];
        $payload['map_columns'] = (int) $payload['map_columns'];
        $payload = $moduleManager->applyPayloadHooks('warehouses.map.update', $payload, [
            'hook' => 'warehouses.map.update',
            'warehouse_id' => $warehouse->id,
            'user_id' => $request->user()->id,
            'source' => 'api',
        ], ['map_rows', 'map_columns']);

        $warehouse->update($payload);

        return WarehouseResource::make($warehouse->load('manager'));
    }

    /**
     * @return array<string, mixed>
     */
    private function validatedData(Request $request, ?Warehouse $warehouse = null): array
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'code' => [
                'nullable',
                'string',
                'max:100',
                Rule::unique('warehouses', 'code')->ignore($warehouse?->id),
            ],
            'location' => ['nullable', 'string', 'max:255'],
            'capacity' => ['nullable', 'numeric', 'min:0'],
            'status' => ['required', Rule::in(['active', 'inactive'])],
            'manager_id' => ['nullable', 'exists:users,id'],
            'description' => ['nullable', 'string'],
            'map_rows' => ['nullable', 'integer', 'min:1', 'max:200'],
            'map_columns' => ['nullable', 'integer', 'min:1', 'max:200'],
        ]);

        $validated['capacity'] = (float) ($validated['capacity'] ?? 0);
        $validated['map_rows'] = (int) ($validated['map_rows'] ?? ($warehouse?->map_rows ?? 8));
        $validated['map_columns'] = (int) ($validated['map_columns'] ?? ($warehouse?->map_columns ?? 12));

        return $validated;
    }
}
