<?php

namespace App\Http\Controllers;

use App\Http\Requests\RegisterLaundryScanRequest;
use App\Http\Requests\StoreLaundryScanRequest;
use App\Models\Area;
use App\Models\OrdenLavanderia;
use App\Services\LaundryWorkflowService;
use App\Support\LaundryScanOperatorResolver;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class LaundryWorkflowController extends Controller
{
    public function __construct(
        private readonly LaundryWorkflowService $workflow
    ) {
    }

    /**
     * Operadores que pueden escanear en el área indicada (para selector en pantalla).
     */
    public function scanOperators(Request $request): JsonResponse
    {
        $this->authorize('registerScan', OrdenLavanderia::class);

        $areaCode = trim((string) $request->query('area_code', $request->query('areaCode', '')));
        if ($areaCode === '') {
            return response()->json([
                'message' => 'Indique area_code.',
                'errors' => ['area_code' => ['El código de área es obligatorio.']],
                'meta' => null,
                'data' => null,
            ], JsonResponse::HTTP_UNPROCESSABLE_ENTITY);
        }

        $area = Area::query()->operational()->where('code', $areaCode)->first();
        if ($area === null) {
            return response()->json([
                'message' => 'Área no encontrada o inactiva.',
                'errors' => ['area_code' => ['Área no válida.']],
                'meta' => null,
                'data' => null,
            ], JsonResponse::HTTP_NOT_FOUND);
        }

        $operators = LaundryScanOperatorResolver::eligibleForArea($area);

        return response()->json([
            'data' => LaundryScanOperatorResolver::toListPayload($operators),
            'meta' => [
                'area_code' => $area->code,
                'area_name' => $area->name,
                'can_delegate' => LaundryScanOperatorResolver::sessionCanDelegate($request->user()),
            ],
            'errors' => null,
        ], JsonResponse::HTTP_OK);
    }

    public function registerScan(RegisterLaundryScanRequest $request): JsonResponse
    {
        return $this->executeScan($request);
    }

    /**
     * POST /laundry/scans — cuerpo { qrOrFolio, areaCode, operatorUserId? }.
     */
    public function storeScan(StoreLaundryScanRequest $request): JsonResponse
    {
        return $this->executeScan($request);
    }

    private function executeScan(FormRequest $request): JsonResponse
    {
        $session = $request->user();
        if ($session === null) {
            return response()->json([
                'message' => 'No autenticado.',
                'errors' => ['auth' => ['Debe enviar un token válido.']],
                'meta' => null,
                'data' => null,
            ], JsonResponse::HTTP_UNAUTHORIZED);
        }

        $this->authorize('registerScan', OrdenLavanderia::class);

        $validated = $request->validated();
        $area = Area::query()->operational()->where('code', $validated['area_code'])->first();
        if ($area === null) {
            return response()->json([
                'message' => 'Área no encontrada o inactiva.',
                'errors' => ['area_code' => ['El código de área no existe o no está habilitado.']],
                'meta' => null,
                'data' => null,
            ], JsonResponse::HTTP_NOT_FOUND);
        }

        $operatorId = isset($validated['operator_user_id'])
            ? (int) $validated['operator_user_id']
            : null;

        $resolved = LaundryScanOperatorResolver::resolve($session, $area, $operatorId);
        if (! ($resolved['ok'] ?? false)) {
            return response()->json([
                'message' => $resolved['message'] ?? 'Error.',
                'errors' => $resolved['errors'] ?? [],
                'meta' => null,
                'data' => null,
            ], $resolved['status'] ?? JsonResponse::HTTP_FORBIDDEN);
        }

        /** @var \App\Models\User $operator */
        $operator = $resolved['user'];

        $result = $this->workflow->registerScan(
            $validated['qr_or_folio'],
            $validated['area_code'],
            $operator,
            $request->ip()
        );

        if (! ($result['ok'] ?? false)) {
            return response()->json([
                'message' => $result['message'] ?? 'Error.',
                'errors' => $result['errors'] ?? [],
                'meta' => null,
                'data' => null,
            ], $result['status'] ?? JsonResponse::HTTP_UNPROCESSABLE_ENTITY);
        }

        $payload = $result['data'];
        if (is_array($payload)) {
            $payload['operator'] = [
                'id' => $operator->id,
                'name' => $operator->name,
            ];
            $payload['registered_by'] = [
                'id' => $session->id,
                'name' => $session->name,
            ];
        }

        return response()->json([
            'data' => $payload,
            'meta' => null,
            'errors' => null,
        ], JsonResponse::HTTP_OK);
    }
}
