<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Api\Concerns\ScopesApiToAccount;
use App\Models\Appointment;
use App\Models\Consultation;
use App\Services\Care\AppointmentService;
use App\Services\Care\ConsultationService;
use App\Services\Care\OrganizationResolver;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ConsultationController extends Controller
{
    use ScopesApiToAccount;

    public function __construct(
        protected ConsultationService $consultations,
        protected AppointmentService $appointments,
    ) {}

    public function show(Request $request, Consultation $consultation): JsonResponse
    {
        $this->authorizeAbility($request, 'consultations.view');
        $this->authorizeConsultation($request, $consultation);

        return response()->json($consultation->load([
            'patient', 'practitioner', 'visit', 'appointment',
            'vitalSigns', 'diagnoses', 'documents',
        ]));
    }

    public function start(Request $request, Appointment $appointment): JsonResponse
    {
        $this->authorizeAbility($request, 'consultations.manage');
        $this->authorizeAppointment($request, $appointment);

        $practitionerId = $request->input('practitioner_id')
            ? (int) $request->input('practitioner_id')
            : $appointment->practitioner_id;

        $this->appointments->startConsultation(
            $appointment,
            $this->ownerRef($request),
            $practitionerId,
            $this->ownerRef($request),
        );

        $consultation = $this->consultations->startFromAppointment(
            $appointment->fresh(),
            $this->ownerRef($request),
            $this->ownerRef($request),
        );

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

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

        $updated = $this->consultations->save(
            $consultation,
            $this->ownerRef($request),
            $this->validatedConsultationData($request),
            $this->ownerRef($request),
        );

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

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

        $completed = $this->consultations->complete(
            $consultation,
            $this->ownerRef($request),
            $this->ownerRef($request),
        );

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

    protected function authorizeAppointment(Request $request, Appointment $appointment): void
    {
        $this->authorizeOwner($request, $appointment);
        abort_unless($appointment->organization_id === $this->organization($request)->id, 404);

        $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));
        if ($branchScope !== null && $appointment->branch_id !== $branchScope) {
            abort(404);
        }
    }

    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);

        $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));
        if ($branchScope !== null && $consultation->visit->branch_id !== $branchScope) {
            abort(404);
        }
    }

    /**
     * @return array<string, mixed>
     */
    protected function validatedConsultationData(Request $request): array
    {
        return $request->validate([
            'symptoms' => ['nullable', 'string', 'max:10000'],
            'clinical_notes' => ['nullable', 'string', 'max:20000'],
            'practitioner_id' => ['nullable', 'integer', 'exists:care_practitioners,id'],
            'vitals' => ['nullable', 'array'],
            'vitals.bp_systolic' => ['nullable', 'integer', 'min:50', 'max:300'],
            'vitals.bp_diastolic' => ['nullable', 'integer', 'min:30', 'max:200'],
            'vitals.pulse' => ['nullable', 'integer', 'min:20', 'max:250'],
            'vitals.temperature' => ['nullable', 'numeric', 'min:30', 'max:45'],
            'vitals.weight_kg' => ['nullable', 'numeric', 'min:0', 'max:500'],
            'vitals.height_cm' => ['nullable', 'numeric', 'min:0', 'max:300'],
            'vitals.spo2' => ['nullable', 'integer', 'min:50', 'max:100'],
            'vitals.respiratory_rate' => ['nullable', 'integer', 'min:5', 'max:80'],
            'diagnoses' => ['nullable', 'array'],
            'diagnoses.*.code' => ['nullable', 'string', 'max:50'],
            'diagnoses.*.description' => ['nullable', 'string', 'max:500'],
            'diagnoses.*.is_primary' => ['nullable', 'boolean'],
            'diagnoses.*.notes' => ['nullable', 'string', 'max:2000'],
        ]);
    }
}
