<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Api\Concerns\ScopesApiToAccount;
use App\Http\Controllers\Controller;
use App\Models\ClinicalPathway;
use App\Models\Consultation;
use App\Models\Patient;
use App\Models\PatientPathway;
use App\Services\Care\CareFeatures;
use App\Services\Care\CarePermissions;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\PathwayService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class PathwayController extends Controller
{
    use ScopesApiToAccount;

    public function __construct(
        protected PathwayService $pathways,
        protected CareFeatures $features,
        protected CarePermissions $permissions,
    ) {}

    public function catalog(Request $request): JsonResponse
    {
        $this->assertEngineEnabled($request);
        $this->authorizeAbility($request, 'assessments.view');

        $pathways = ClinicalPathway::query()
            ->active()
            ->with('templates')
            ->orderBy('sort_order')
            ->get();

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

    public function index(Request $request, Patient $patient): JsonResponse
    {
        $this->assertEngineEnabled($request);
        $this->authorizeAbility($request, 'assessments.view');
        $this->authorizePatient($request, $patient);

        $active = $this->pathways->activeFor($patient)->load('pathway.templates');
        $history = PatientPathway::query()
            ->owned($this->ownerRef($request))
            ->where('patient_id', $patient->id)
            ->with('pathway')
            ->orderByDesc('activated_at')
            ->limit(50)
            ->get();

        return response()->json([
            'active' => $active->map(fn (PatientPathway $pp) => $this->serializePatientPathway($pp)),
            'history' => $history->map(fn (PatientPathway $pp) => $this->serializePatientPathway($pp)),
        ]);
    }

    public function store(Request $request, Patient $patient): JsonResponse
    {
        $this->assertEngineEnabled($request);
        $this->authorizeAbility($request, 'pathways.manage');
        $this->authorizePatient($request, $patient);

        $validated = $request->validate([
            'pathway_code' => ['required', 'string', 'max:100'],
            'consultation_uuid' => ['nullable', 'uuid'],
            'activation_diagnosis_text' => ['nullable', 'string', 'max:500'],
        ]);

        $pathway = ClinicalPathway::findByCode($validated['pathway_code']);
        abort_unless($pathway, 422, 'Unknown or inactive pathway.');

        $consultation = null;
        if (! empty($validated['consultation_uuid'])) {
            $consultation = Consultation::query()
                ->where('uuid', $validated['consultation_uuid'])
                ->where('patient_id', $patient->id)
                ->firstOrFail();
            $this->authorizeConsultation($request, $consultation);
            $consultation->loadMissing(['visit', 'diagnoses']);
        }

        $patientPathway = $this->pathways->activate(
            $patient,
            $pathway,
            $this->ownerRef($request),
            $this->member($request),
            [
                'consultation' => $consultation,
                'activation_diagnosis_text' => $validated['activation_diagnosis_text'] ?? null,
                'actor' => $this->ownerRef($request),
            ],
        );

        return response()->json($this->serializePatientPathway($patientPathway->load(['pathway.templates', 'assessments.template'])), 201);
    }

    public function deactivate(Request $request, Patient $patient, PatientPathway $patientPathway): JsonResponse
    {
        $this->assertEngineEnabled($request);
        $this->authorizeAbility($request, 'pathways.manage');
        $this->authorizePatient($request, $patient);
        abort_unless($patientPathway->patient_id === $patient->id, 404);
        $this->authorizeOwner($request, $patientPathway);

        $updated = $this->pathways->deactivate(
            $patientPathway,
            $this->ownerRef($request),
            $this->member($request),
            $this->ownerRef($request),
        );

        return response()->json($this->serializePatientPathway($updated->load('pathway')));
    }

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

        $consultation->loadMissing(['diagnoses', 'patient']);
        $suggestions = $this->pathways->suggest($consultation->patient, $consultation->diagnoses);

        return response()->json([
            'data' => $suggestions->map(fn (array $row) => [
                'pathway_code' => $row['pathway_code'],
                'pathway_name' => $row['pathway_name'],
                'rank' => $row['rank'],
                'match_reason' => $row['match_reason'],
                'already_active' => $row['already_active'],
            ])->values()->all(),
        ]);
    }

    protected function serializePatientPathway(PatientPathway $pp): array
    {
        return [
            'uuid' => $pp->uuid,
            'status' => $pp->status,
            'pathway_code' => $pp->pathway?->code,
            'pathway_name' => $pp->pathway?->name,
            'activated_at' => $pp->activated_at?->toIso8601String(),
            'activation_diagnosis_text' => $pp->activation_diagnosis_text,
            'resolved_at' => $pp->resolved_at?->toIso8601String(),
            'assessments' => $pp->relationLoaded('assessments')
                ? $pp->assessments->map(fn ($a) => [
                    'uuid' => $a->uuid,
                    'status' => $a->status,
                    'template_code' => $a->template?->code,
                ])->values()->all()
                : null,
        ];
    }

    protected function assertEngineEnabled(Request $request): void
    {
        abort_unless(
            $this->features->enabled($this->organization($request), CareFeatures::ASSESSMENTS_ENGINE),
            404,
        );
        $this->features->ensureAssessmentCatalog();
    }

    protected function authorizePatient(Request $request, Patient $patient): void
    {
        $this->authorizeOwner($request, $patient);
        abort_unless($patient->organization_id === $this->organization($request)->id, 404);

        $branchId = app(OrganizationResolver::class)->branchScope($this->member($request));
        if ($branchId !== null && $patient->branch_id !== $branchId) {
            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);

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