<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Http\Controllers\Controller;
use App\Models\Assessment;
use App\Models\AssessmentTemplate;
use App\Models\Consultation;
use App\Models\InvestigationType;
use App\Models\Practitioner;
use App\Services\Care\AssessmentService;
use App\Services\Care\BranchContext;
use App\Services\Care\CareFeatures;
use App\Services\Care\CarePermissions;
use App\Services\Care\CareQueueBridge;
use App\Services\Care\CareQueueContexts;
use App\Services\Care\ConsultationReturnContext;
use App\Services\Care\ConsultationService;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\PathwayService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ConsultationController extends Controller
{
    use ScopesToAccount;

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

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

        $consultation->load([
            'patient', 'practitioner', 'visit', 'appointment',
            'vitalSigns', 'diagnoses', 'documents',
            'investigationRequests.investigationType', 'prescriptions.items',
        ]);

        app(ConsultationReturnContext::class)->remember($consultation);

        $permissions = app(CarePermissions::class);
        $member = $this->member($request);
        $organization = $this->organization($request);

        $canManage = $permissions->can($member, 'consultations.manage');
        $canVitals = $permissions->can($member, 'vitals.manage');
        $canRequestInvestigations = $permissions->can($member, 'investigations.request');
        $canPrescribe = $permissions->can($member, 'prescriptions.manage');
        $canGenerateBill = $permissions->can($member, 'bills.manage');

        $careFeatures = app(CareFeatures::class);
        $assessmentsEnabled = $careFeatures->enabled($organization, CareFeatures::ASSESSMENTS_ENGINE);
        if ($assessmentsEnabled) {
            $careFeatures->ensureAssessmentCatalog();
        }
        $canViewAssessments = $assessmentsEnabled && $permissions->can($member, 'assessments.view');
        $canCaptureAssessment = $assessmentsEnabled && (
            $permissions->can($member, 'assessments.capture')
            || $permissions->can($member, 'assessments.manage')
        );

        $consultationAssessments = collect();
        $startableTemplates = collect();
        $universalTemplate = null;
        $universalAssessment = null;
        $canCaptureUniversal = false;
        $canManagePathways = $assessmentsEnabled && $permissions->can($member, 'pathways.manage');
        $pathwaySuggestions = collect();
        $activePathways = collect();

        if ($canViewAssessments) {
            $consultationAssessments = Assessment::query()
                ->owned($this->ownerRef($request))
                ->where('consultation_id', $consultation->id)
                ->with(['template', 'answers.question'])
                ->orderByDesc('created_at')
                ->get();

            $universalTemplate = AssessmentTemplate::currentSystemByCode('universal_intake');
            if ($universalTemplate) {
                $universalAssessment = $consultationAssessments
                    ->first(fn (Assessment $a) => $a->template_id === $universalTemplate->id)
                    ?? Assessment::query()
                        ->owned($this->ownerRef($request))
                        ->where('patient_id', $consultation->patient_id)
                        ->where('template_id', $universalTemplate->id)
                        ->whereIn('status', [Assessment::STATUS_DRAFT, Assessment::STATUS_COMPLETED])
                        ->with(['template', 'answers.question'])
                        ->orderByDesc('created_at')
                        ->first();
            }

            if ($canCaptureAssessment) {
                $startableTemplates = AssessmentTemplate::query()
                    ->system()
                    ->current()
                    ->orderBy('category')
                    ->orderBy('name')
                    ->get()
                    // Universal has a dedicated CTA; keep other templates in the general list.
                    ->reject(fn (AssessmentTemplate $t) => $t->code === 'universal_intake')
                    ->values();

                if ($universalTemplate) {
                    try {
                        app(AssessmentService::class)
                            ->assertCaptureAllowed($member, $universalTemplate);
                        $canCaptureUniversal = true;
                    } catch (\Throwable) {
                        $canCaptureUniversal = false;
                    }
                }
            }

            $pathwayService = app(PathwayService::class);
            $activePathways = $pathwayService->activeFor($consultation->patient)
                ->load(['pathway.templates', 'assessments.template', 'assessments.score']);
            // Suggestions from **persisted** diagnoses only (after save).
            $pathwaySuggestions = $pathwayService->suggest(
                $consultation->patient,
                $consultation->diagnoses,
            );

            // Instruments for active pathways (e.g. stroke → NIHSS, mRS) with draft/complete status.
            $pathwayInstruments = collect();
            foreach ($activePathways as $patientPathway) {
                foreach ($patientPathway->pathway->templates as $binding) {
                    $template = AssessmentTemplate::currentSystemByCode($binding->template_code);
                    $assessment = $patientPathway->assessments
                        ->first(fn (Assessment $a) => $a->template?->code === $binding->template_code)
                        ?? $consultationAssessments
                            ->first(fn (Assessment $a) => $a->template?->code === $binding->template_code)
                        ?? ($template
                            ? Assessment::query()
                                ->owned($this->ownerRef($request))
                                ->where('patient_id', $consultation->patient_id)
                                ->where('template_id', $template->id)
                                ->with(['template', 'score'])
                                ->orderByDesc('created_at')
                                ->first()
                            : null);

                    $pathwayInstruments->push([
                        'pathway_code' => $patientPathway->pathway->code,
                        'pathway_name' => $patientPathway->pathway->name,
                        'template_code' => $binding->template_code,
                        'template_name' => $template?->name ?? $binding->template_code,
                        'required' => $binding->is_required_on_activation,
                        'phase' => $binding->phase,
                        'template' => $template,
                        'assessment' => $assessment,
                        'pack_missing' => $template === null,
                    ]);
                }
            }
        }

        $practitioners = Practitioner::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->where('is_active', true)
            ->orderBy('name')
            ->get();

        $investigationTypes = InvestigationType::query()
            ->where('organization_id', $organization->id)
            ->where('is_active', true)
            ->orderBy('name')
            ->get();

        $queueIntegration = ['enabled' => false];
        $queueBranchId = null;
        $queueBridge = app(CareQueueBridge::class);
        $canAccessPatientQueue = $permissions->canAccessPatientQueue($member);
        if ($canAccessPatientQueue && $queueBridge->isEnabled($organization)) {
            $queueBranchId = app(BranchContext::class)->resolve($request, $organization, $member)
                ?: (int) ($consultation->practitioner?->branch_id
                    ?: $consultation->visit?->branch_id
                    ?: $consultation->appointment?->branch_id
                    ?: 0);
            if ($queueBranchId > 0) {
                $queueIntegration = $queueBridge->listMeta(
                    $organization,
                    CareQueueContexts::CONSULTATION,
                    $queueBranchId,
                );
            }
        }

        return view('care.consultations.show', [
            'consultation' => $consultation,
            'practitioners' => $practitioners,
            'investigationTypes' => $investigationTypes,
            'canManage' => $canManage,
            'canVitals' => $canVitals,
            'canRequestInvestigations' => $canRequestInvestigations,
            'canPrescribe' => $canPrescribe,
            'canGenerateBill' => $canGenerateBill,
            'isCompleted' => $consultation->status === Consultation::STATUS_COMPLETED,
            'assessmentsEnabled' => $assessmentsEnabled,
            'canViewAssessments' => $canViewAssessments,
            'canCaptureAssessment' => $canCaptureAssessment,
            'consultationAssessments' => $consultationAssessments,
            'startableTemplates' => $startableTemplates,
            'assessmentStatuses' => config('care.assessment_statuses'),
            'canAccessPatientQueue' => $canAccessPatientQueue,
            'universalTemplate' => $universalTemplate,
            'universalAssessment' => $universalAssessment,
            'canCaptureUniversal' => $canCaptureUniversal,
            'canManagePathways' => $canManagePathways,
            'pathwaySuggestions' => $pathwaySuggestions,
            'activePathways' => $activePathways,
            'pathwayInstruments' => $pathwayInstruments ?? collect(),
            'queueIntegration' => $queueIntegration,
            'queueBranchId' => $queueBranchId,
            'medicationRoutes' => config('care.medication_routes'),
        ]);
    }

    public function update(Request $request, Consultation $consultation): RedirectResponse
    {
        $canManage = app(CarePermissions::class)
            ->can($this->member($request), 'consultations.manage');
        $canVitals = app(CarePermissions::class)
            ->can($this->member($request), 'vitals.manage');

        abort_unless($canManage || $canVitals, 403);
        $this->authorizeConsultation($request, $consultation);
        abort_if($consultation->status === Consultation::STATUS_COMPLETED, 422);

        $validated = $this->validatedConsultationData($request, $canManage, $canVitals);

        $this->consultations->save(
            $consultation,
            $this->ownerRef($request),
            $validated,
            $this->ownerRef($request),
        );

        $message = 'Consultation saved.';
        if ($canManage && $request->boolean('suggest_pathways')) {
            $consultation->load('diagnoses');
            $count = $consultation->diagnoses->filter(fn ($d) => filled($d->description) || filled($d->code))->count();
            $message = $count > 0
                ? 'Diagnoses saved — review pathway suggestions below.'
                : 'Consultation saved. Add and save diagnoses to see pathway suggestions.';
        }

        return back()->with('success', $message);
    }

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

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

        app(ConsultationReturnContext::class)->forget();

        $completed->loadMissing(['appointment.organization']);
        if ($completed->appointment
            && $completed->appointment->organization
            && app(CareFeatures::class)->enabled(
                $completed->appointment->organization,
                CareFeatures::WORKFLOW_ENGINE,
            )) {
            return redirect()->route('care.appointments.show', $completed->appointment)
                ->with('success', 'Consultation completed. Continue the patient journey from the next stage.');
        }

        return redirect()->route(
            app(CarePermissions::class)->canAccessPatientQueue($this->member($request))
                ? 'care.queue.index'
                : 'care.appointments.index'
        )->with('success', 'Consultation completed.');
    }

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

    /**
     * @return array<string, mixed>
     */
    protected function validatedConsultationData(Request $request, bool $canManage, bool $canVitals): array
    {
        $rules = [];

        if ($canManage) {
            $rules = array_merge($rules, [
                'symptoms' => ['nullable', 'string', 'max:10000'],
                'clinical_notes' => ['nullable', 'string', 'max:20000'],
                'practitioner_id' => ['nullable', 'integer', 'exists:care_practitioners,id'],
                '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'],
                'documents' => ['nullable', 'array'],
                'documents.*' => ['file', 'max:10240', 'mimes:pdf,jpeg,png,jpg,webp'],
            ]);
            $canVitals = true;
        }

        if ($canVitals) {
            $rules['vitals'] = ['nullable', 'array'];
            $rules['vitals.bp_systolic'] = ['nullable', 'integer', 'min:50', 'max:300'];
            $rules['vitals.bp_diastolic'] = ['nullable', 'integer', 'min:30', 'max:200'];
            $rules['vitals.pulse'] = ['nullable', 'integer', 'min:20', 'max:250'];
            $rules['vitals.temperature'] = ['nullable', 'numeric', 'min:30', 'max:45'];
            $rules['vitals.weight_kg'] = ['nullable', 'numeric', 'min:0', 'max:500'];
            $rules['vitals.height_cm'] = ['nullable', 'numeric', 'min:0', 'max:300'];
            $rules['vitals.spo2'] = ['nullable', 'integer', 'min:50', 'max:100'];
            $rules['vitals.respiratory_rate'] = ['nullable', 'integer', 'min:5', 'max:80'];
        }

        return $request->validate($rules);
    }
}
