<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Care\Concerns\ScopesToAccount;
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\ConsultationReturnContext;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\PathwayService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PathwayController extends Controller
{
    use ScopesToAccount;

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

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

        $active = $this->pathways->activeFor($patient);
        $history = PatientPathway::query()
            ->owned($this->ownerRef($request))
            ->where('patient_id', $patient->id)
            ->with('pathway')
            ->orderByDesc('activated_at')
            ->paginate(20);

        $catalog = ClinicalPathway::query()->active()->orderBy('sort_order')->get();
        $canManage = $this->permissions->can($this->member($request), 'pathways.manage');

        return view('care.pathways.index', [
            'patient' => $patient,
            'active' => $active,
            'history' => $history,
            'catalog' => $catalog,
            'canManage' => $canManage,
            'statuses' => config('care.patient_pathway_statuses'),
            'returnConsultation' => app(ConsultationReturnContext::class)->resolve($request, (int) $patient->id),
        ]);
    }

    public function store(Request $request, Patient $patient): RedirectResponse
    {
        $this->assertPathwaysEnabled($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 = app(ConsultationReturnContext::class);

        return redirect()
            ->route('care.pathways.index', array_filter([
                'patient' => $patient,
                ...$return->routeQuery($request),
            ]))
            ->with('success', "Pathway “{$pathway->name}” activated.");
    }

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

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

        return back()->with('success', 'Pathway deactivated.');
    }

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

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

        $payload = [
            '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(),
        ];

        if ($request->wantsJson() || $request->ajax()) {
            return response()->json($payload);
        }

        // HTML fallthrough not used — consultation show embeds suggestions server-side.
        return back()->with('pathway_suggestions', $payload['data']);
    }

    protected function assertPathwaysEnabled(Request $request): void
    {
        $org = $this->organization($request);
        // Pathways require assessments engine; suggestions flag is optional UX.
        abort_unless(
            $this->features->enabled($org, 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);
        }
    }
}
