<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Api\Concerns\ScopesApiToAccount;
use App\Models\Consultation;
use App\Models\Prescription;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\PrescriptionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class PrescriptionController extends Controller
{
    use ScopesApiToAccount;

    public function __construct(
        protected PrescriptionService $prescriptions,
    ) {}

    public function index(Request $request): JsonResponse
    {
        $this->authorizeAbility($request, 'prescriptions.view');
        $organization = $this->organization($request);
        $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));

        $prescriptions = $this->prescriptions->list(
            $this->ownerRef($request),
            $organization->id,
            $request->only(['status', 'patient_id', 'per_page']),
            $branchScope,
        );

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

    public function queue(Request $request): JsonResponse
    {
        $this->authorizeAbility($request, 'prescriptions.view');
        $organization = $this->organization($request);

        $queue = $this->prescriptions->pharmacyQueue($this->ownerRef($request), $organization->id);

        return response()->json(['data' => $queue]);
    }

    public function store(Request $request, Consultation $consultation): JsonResponse
    {
        $this->authorizeAbility($request, 'prescriptions.manage');
        $this->authorizeConsultation($request, $consultation);

        $prescription = $this->prescriptions->createFromConsultation(
            $consultation,
            $this->ownerRef($request),
            $this->validatedPrescriptionData($request),
            $this->ownerRef($request),
        );

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

    public function show(Request $request, Prescription $prescription): JsonResponse
    {
        $this->authorizeAbility($request, 'prescriptions.view');
        $this->authorizePrescription($request, $prescription);

        return response()->json($prescription->load(['patient', 'practitioner', 'items']));
    }

    public function dispense(Request $request, Prescription $prescription): JsonResponse
    {
        $this->authorizeAbility($request, 'prescriptions.dispense');
        $this->authorizePrescription($request, $prescription);

        $updated = $this->prescriptions->dispense($prescription, $this->ownerRef($request), $this->ownerRef($request));

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

    protected function authorizeConsultation(Request $request, Consultation $consultation): void
    {
        $this->authorizeOwner($request, $consultation);
        $consultation->loadMissing('visit');
        abort_unless($consultation->visit->organization_id === $this->organization($request)->id, 404);
    }

    protected function authorizePrescription(Request $request, Prescription $prescription): void
    {
        $this->authorizeOwner($request, $prescription);
        abort_unless($prescription->organization_id === $this->organization($request)->id, 404);
    }

    /**
     * @return array<string, mixed>
     */
    protected function validatedPrescriptionData(Request $request): array
    {
        return $request->validate([
            'practitioner_id' => ['nullable', 'integer', 'exists:care_practitioners,id'],
            'notes' => ['nullable', 'string', 'max:5000'],
            'activate' => ['nullable', 'boolean'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.is_procedure' => ['nullable', 'boolean'],
            'items.*.name' => ['required', 'string', 'max:255'],
            'items.*.dosage' => ['nullable', 'string', 'max:100'],
            'items.*.frequency' => ['nullable', 'string', 'max:100'],
            'items.*.duration' => ['nullable', 'string', 'max:100'],
            'items.*.route' => ['nullable', 'string', 'max:50'],
            'items.*.quantity' => ['nullable', 'string', 'max:50'],
            'items.*.instructions' => ['nullable', 'string', 'max:2000'],
        ]);
    }
}
