<?php

namespace Modules\ClinicCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcPatient;
use Modules\ClinicCore\Entities\ClcPatientAllergy;
use Modules\ClinicCore\Entities\ClcPatientMedication;
use Modules\ClinicCore\Entities\ClcPatientInsurance;
use Modules\ClinicCore\Entities\ClcMedicalAlert;
use Modules\ClinicCore\Entities\Services\MedicalAlertService;

/**
 * SIFA P3-T1 / P3-T8 — structured clinical baseline CRUD (allergies, current
 * medications, insurances) + medical-alert acknowledge/resolve, all rendered
 * inside the patient show screen. Every action is business_id-scoped and
 * permission-gated.
 */
class ClcPatientBaselineController extends Controller
{
    private function businessId(): int
    {
        return (int) request()->session()->get('user.business_id');
    }

    private function patient(int $id): ClcPatient
    {
        return ClcPatient::where('business_id', $this->businessId())->findOrFail($id);
    }

    private function guardManage(): void
    {
        if (!auth()->user()->can('clinic.allergy.manage')) {
            abort(403, 'Unauthorized action.');
        }
    }

    // ── Allergies ──────────────────────────────────────────────────────────

    public function storeAllergy(Request $request, $patientId, MedicalAlertService $alerts)
    {
        $this->guardManage();
        $patient = $this->patient($patientId);

        $data = $request->validate([
            'allergen' => 'required|string|max:191',
            'type'     => 'required|in:' . implode(',', ClcPatientAllergy::TYPES),
            'severity' => 'required|in:' . implode(',', ClcPatientAllergy::SEVERITIES),
            'reaction' => 'nullable|string',
            'source'   => 'nullable|in:' . implode(',', ClcPatientAllergy::SOURCES),
            'status'   => 'nullable|in:' . implode(',', ClcPatientAllergy::STATUSES),
            'notes'    => 'nullable|string',
        ]);

        $allergy = ClcPatientAllergy::create(array_merge($data, [
            'business_id' => $this->businessId(),
            'patient_id'  => $patient->id,
            'source'      => $data['source'] ?? 'patient_reported',
            'status'      => $data['status'] ?? 'active',
            'created_by'  => auth()->id(),
        ]));

        // Auto-raise / clear the allergy medical alert.
        $alerts->syncAllergyAlert($allergy);

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.saved_successfully')]);
    }

    public function updateAllergy(Request $request, $id, MedicalAlertService $alerts)
    {
        $this->guardManage();
        $allergy = ClcPatientAllergy::where('business_id', $this->businessId())->findOrFail($id);

        $data = $request->validate([
            'allergen' => 'required|string|max:191',
            'type'     => 'required|in:' . implode(',', ClcPatientAllergy::TYPES),
            'severity' => 'required|in:' . implode(',', ClcPatientAllergy::SEVERITIES),
            'reaction' => 'nullable|string',
            'source'   => 'nullable|in:' . implode(',', ClcPatientAllergy::SOURCES),
            'status'   => 'nullable|in:' . implode(',', ClcPatientAllergy::STATUSES),
            'notes'    => 'nullable|string',
        ]);

        // Mark verified when a clinician confirms a test-confirmed allergy.
        if (($data['source'] ?? null) === 'test_confirmed' && !$allergy->verified_at) {
            $data['verified_by'] = auth()->id();
            $data['verified_at'] = now();
        }

        $allergy->update($data);
        $alerts->syncAllergyAlert($allergy);

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.updated_successfully')]);
    }

    public function destroyAllergy($id, MedicalAlertService $alerts)
    {
        $this->guardManage();
        $allergy = ClcPatientAllergy::where('business_id', $this->businessId())->findOrFail($id);

        // Resolve any alert this allergy raised, then delete.
        $alerts->resolveBySource($this->businessId(), (int) $allergy->patient_id, 'clc_patient_allergies', (int) $allergy->id);
        $allergy->delete();

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.deleted_successfully')]);
    }

    // ── Current medications ────────────────────────────────────────────────

    public function storeMedication(Request $request, $patientId)
    {
        $this->guardManage();
        $patient = $this->patient($patientId);

        $data = $request->validate([
            'medication_name' => 'required|string|max:191',
            'dosage'          => 'nullable|string|max:191',
            'frequency'       => 'nullable|string|max:191',
            'route'           => 'nullable|string|max:100',
            'prescriber'      => 'nullable|string|max:191',
            'start_date'      => 'nullable|date',
            'end_date'        => 'nullable|date',
            'ongoing'         => 'nullable|boolean',
            'notes'           => 'nullable|string',
        ]);

        ClcPatientMedication::create(array_merge($data, [
            'business_id' => $this->businessId(),
            'patient_id'  => $patient->id,
            'ongoing'     => $request->boolean('ongoing', true),
            'created_by'  => auth()->id(),
        ]));

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.saved_successfully')]);
    }

    public function updateMedication(Request $request, $id)
    {
        $this->guardManage();
        $med = ClcPatientMedication::where('business_id', $this->businessId())->findOrFail($id);

        $data = $request->validate([
            'medication_name' => 'required|string|max:191',
            'dosage'          => 'nullable|string|max:191',
            'frequency'       => 'nullable|string|max:191',
            'route'           => 'nullable|string|max:100',
            'prescriber'      => 'nullable|string|max:191',
            'start_date'      => 'nullable|date',
            'end_date'        => 'nullable|date',
            'ongoing'         => 'nullable|boolean',
            'notes'           => 'nullable|string',
        ]);
        $data['ongoing'] = $request->boolean('ongoing', false);

        $med->update($data);

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.updated_successfully')]);
    }

    public function destroyMedication($id)
    {
        $this->guardManage();
        ClcPatientMedication::where('business_id', $this->businessId())->findOrFail($id)->delete();
        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.deleted_successfully')]);
    }

    // ── Insurances ─────────────────────────────────────────────────────────

    public function storeInsurance(Request $request, $patientId)
    {
        $this->guardManage();
        $patient = $this->patient($patientId);

        $data = $request->validate([
            'provider_name'     => 'required|string|max:191',
            'policy_number'     => 'nullable|string|max:191',
            'group_number'      => 'nullable|string|max:191',
            'plan_type'         => 'nullable|string|max:191',
            'effective_date'    => 'nullable|date',
            'expiry_date'       => 'nullable|date',
            'copay_amount'      => 'nullable|numeric',
            'pre_auth_required' => 'nullable|boolean',
            'status'            => 'nullable|in:' . implode(',', ClcPatientInsurance::STATUSES),
            'notes'             => 'nullable|string',
        ]);

        ClcPatientInsurance::create(array_merge($data, [
            'business_id'       => $this->businessId(),
            'patient_id'        => $patient->id,
            'pre_auth_required' => $request->boolean('pre_auth_required'),
            'status'            => $data['status'] ?? 'active',
            'created_by'        => auth()->id(),
        ]));

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.saved_successfully')]);
    }

    public function updateInsurance(Request $request, $id)
    {
        $this->guardManage();
        $ins = ClcPatientInsurance::where('business_id', $this->businessId())->findOrFail($id);

        $data = $request->validate([
            'provider_name'     => 'required|string|max:191',
            'policy_number'     => 'nullable|string|max:191',
            'group_number'      => 'nullable|string|max:191',
            'plan_type'         => 'nullable|string|max:191',
            'effective_date'    => 'nullable|date',
            'expiry_date'       => 'nullable|date',
            'copay_amount'      => 'nullable|numeric',
            'pre_auth_required' => 'nullable|boolean',
            'status'            => 'nullable|in:' . implode(',', ClcPatientInsurance::STATUSES),
            'notes'             => 'nullable|string',
        ]);
        $data['pre_auth_required'] = $request->boolean('pre_auth_required');

        $ins->update($data);

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.updated_successfully')]);
    }

    public function destroyInsurance($id)
    {
        $this->guardManage();
        ClcPatientInsurance::where('business_id', $this->businessId())->findOrFail($id)->delete();
        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.deleted_successfully')]);
    }

    // ── Medical alerts (acknowledge / resolve) ─────────────────────────────

    public function acknowledgeAlert($id, MedicalAlertService $alerts)
    {
        if (!auth()->user()->can('clinic.alert.acknowledge')) {
            abort(403, 'Unauthorized action.');
        }
        $alert = ClcMedicalAlert::where('business_id', $this->businessId())->findOrFail($id);
        $alerts->acknowledge((int) $alert->id, $this->businessId(), auth()->id());

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.alert_acknowledged')]);
    }

    public function resolveAlert($id, MedicalAlertService $alerts)
    {
        if (!auth()->user()->can('clinic.alert.manage')) {
            abort(403, 'Unauthorized action.');
        }
        $alert = ClcMedicalAlert::where('business_id', $this->businessId())->findOrFail($id);
        $alerts->resolve((int) $alert->id, $this->businessId());

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.alert_resolved')]);
    }

    public function storeAlert(Request $request, $patientId, MedicalAlertService $alerts)
    {
        if (!auth()->user()->can('clinic.alert.manage')) {
            abort(403, 'Unauthorized action.');
        }
        $patient = $this->patient($patientId);

        $data = $request->validate([
            'alert_type' => 'required|in:' . implode(',', ClcMedicalAlert::TYPES),
            'severity'   => 'required|in:' . implode(',', ClcMedicalAlert::SEVERITIES),
            'title'      => 'required|string|max:191',
            'details'    => 'nullable|string',
        ]);

        $alerts->raise(array_merge($data, [
            'business_id' => $this->businessId(),
            'patient_id'  => $patient->id,
            'created_by'  => auth()->id(),
        ]));

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.saved_successfully')]);
    }
}
