<?php

namespace Modules\ClinicCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcPatient;
use Modules\ClinicCore\Entities\ClcPatientCondition;
use Modules\ClinicCore\Entities\ClcMedicalCondition;
use Modules\ClinicCore\Entities\ClcPatientContactDetail;
use Modules\ClinicCore\Entities\ClcDoctor;
use Modules\ClinicCore\Entities\ClcPreferredDoctorHistory;
use Modules\ClinicCore\Entities\ClcSpecialty;
use App\Contact;
use Yajra\DataTables\Facades\DataTables;
use Modules\ClinicCore\Http\Controllers\Traits\LogsClcActivity;

class ClcPatientController extends Controller
{
    use LogsClcActivity;
    public function index()
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $stats = [
            'total'    => ClcPatient::where('business_id', $businessId)->count(),
            'active'   => ClcPatient::where('business_id', $businessId)->where('status', 'active')->count(),
            'deceased' => ClcPatient::where('business_id', $businessId)->where('deceased', true)->count(),
        ];
        $speciesCounts = ClcPatient::where('business_id', $businessId)
            ->selectRaw('species, COUNT(*) as cnt')
            ->groupBy('species')
            ->orderByDesc('cnt')
            ->limit(5)
            ->pluck('cnt', 'species');

        return view('clinicCore::patients.index', compact('stats', 'speciesCounts'));
    }

    public function list(Request $request)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');

        $query = ClcPatient::select('clc_patients.*')
            ->selectRaw('(SELECT vx.weight_at_time FROM clc_vaccinations vx WHERE vx.patient_id = clc_patients.id AND vx.weight_at_time IS NOT NULL ORDER BY vx.administered_date DESC LIMIT 1) as last_weight')
            ->selectRaw('(SELECT COUNT(*) FROM clc_vaccinations vx WHERE vx.patient_id = clc_patients.id AND vx.waived_at IS NULL AND vx.status = "administered" AND vx.next_due_date IS NOT NULL AND vx.next_due_date < CURDATE()) as overdue_vax_count')
            ->selectRaw('(SELECT COUNT(*) FROM clc_vaccinations vx WHERE vx.patient_id = clc_patients.id AND vx.waived_at IS NULL AND vx.status = "administered" AND vx.next_due_date IS NOT NULL AND vx.next_due_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 30 DAY)) as due_soon_vax_count')
            ->withCount(['appointments', 'vaccinations'])
            ->withCount(['conditions as chronic_count' => fn($q) => $q->where('status', 'chronic')])
            ->with([
                'owner',
                'conditions' => fn($q) => $q->where('status', 'chronic')->with('condition'),
            ])
            ->where('clc_patients.business_id', $businessId);

        if ($request->filled('filter_status')) {
            $query->where('clc_patients.status', $request->filter_status);
        }
        if ($request->filled('filter_species')) {
            $query->where('clc_patients.species', $request->filter_species);
        }
        if ($request->filled('filter_search')) {
            $term = $request->filter_search;
            $query->where(function ($q) use ($term) {
                $q->where('clc_patients.patient_name', 'like', '%' . $term . '%')
                  ->orWhere('clc_patients.breed', 'like', '%' . $term . '%')
                  ->orWhere('clc_patients.microchip_no', 'like', '%' . $term . '%')
                  ->orWhereHas('owner', fn($sq) => $sq->where('name', 'like', '%' . $term . '%')
                                                        ->orWhere('mobile', 'like', '%' . $term . '%'));
            });
        }

        $speciesIcons = ['dog' => '🐕', 'cat' => '🐈', 'rabbit' => '🐇', 'bird' => '🦜', 'fish' => '🐟'];

        return DataTables::of($query)
            ->addColumn('patient_name_col', function ($row) use ($speciesIcons) {
                $icon = $speciesIcons[strtolower($row->species ?? '')] ?? '🐾';
                $url  = route('clinic.patients.show', $row->id);
                $photo = $row->photo_url
                    ? '<img src="' . e($row->photo_url) . '" style="width:32px;height:32px;border-radius:50%;object-fit:cover;margin-right:8px;vertical-align:middle;">'
                    : '<span style="display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:50%;background:#f1f5f9;margin-right:8px;font-size:14px;vertical-align:middle;">' . $icon . '</span>';
                $name = '<a href="' . $url . '" style="font-weight:700;color:#1e293b;">' . e($row->patient_name) . '</a>';
                $sub  = '';
                if (config('cliniccore.show_animal_fields', false) && ($row->species || $row->breed)) {
                    $sub = '<small class="text-muted" style="display:block;">' . ($row->species ? ucfirst($row->species) : '') . ($row->breed ? ' · ' . e($row->breed) : '') . '</small>';
                }
                return $photo . $name . $sub;
            })
            ->addColumn('owner_col', function ($row) {
                $owner = $row->owner;
                if (!$owner) return '—';
                $ownerDetailId = \Modules\ClinicCore\Entities\ClcPatientContactDetail::where('contact_id', $owner->id)->value('id');
                $url    = $ownerDetailId ? route('clinic.patient-contacts.show', $ownerDetailId) : '#';
                $name   = '<a href="' . $url . '" style="font-weight:600;">' . e($owner->name ?? $owner->supplier_business_name ?? '—') . '</a>';
                $mobile = $owner->mobile ? '<small class="text-muted"><i class="fa fa-phone"></i> ' . e($owner->mobile) . '</small>' : '';
                return $name . ($mobile ? '<br>' . $mobile : '');
            })
            ->addColumn('species_col', function ($row) use ($speciesIcons) {
                if (!config('cliniccore.show_animal_fields', false) || !$row->species) return '—';
                $icon = $speciesIcons[strtolower($row->species)] ?? '🐾';
                return $icon . ' ' . ucfirst($row->species);
            })
            ->addColumn('age', fn($row) => $row->dob ? $row->age . ' yrs' : '—')
            ->addColumn('status_badge', function ($row) {
                $color = $row->status === 'active' ? 'success' : 'danger';
                return '<span class="label label-' . $color . '">' . ucfirst($row->status) . '</span>';
            })
            ->addColumn('stats_col', function ($row) {
                $parts = [];
                $parts[] = '<span title="Total Appointments" style="white-space:nowrap;"><i class="fa fa-calendar" style="color:#3b82f6;"></i>&nbsp;' . ($row->appointments_count ?? 0) . '</span>';
                $parts[] = '<span title="Total Vaccinations" style="white-space:nowrap;"><i class="fas fa-syringe" style="color:#27ae60;"></i>&nbsp;' . ($row->vaccinations_count ?? 0) . '</span>';
                if ($row->last_weight) {
                    $parts[] = '<span title="Last Recorded Weight" style="white-space:nowrap;"><i class="fas fa-weight" style="color:#f59e0b;"></i>&nbsp;' . number_format((float) $row->last_weight, 1) . ' kg</span>';
                }
                return '<div style="display:flex;gap:10px;font-size:12px;">' . implode('', $parts) . '</div>';
            })
            ->addColumn('vaccine_alert_col', function ($row) {
                $overdue  = (int) ($row->overdue_vax_count ?? 0);
                $dueSoon  = (int) ($row->due_soon_vax_count ?? 0);
                $vaxTotal = (int) ($row->vaccinations_count ?? 0);
                if ($overdue > 0) {
                    return '<span class="badge" style="background:#ef4444;font-size:10px;padding:3px 7px;" title="' . $overdue . ' overdue vaccination(s)">'
                        . '<i class="fas fa-exclamation-triangle"></i> ' . $overdue . ' Overdue</span>';
                }
                if ($dueSoon > 0) {
                    return '<span class="badge" style="background:#f59e0b;font-size:10px;padding:3px 7px;" title="Due within 30 days">'
                        . '<i class="fa fa-clock"></i> ' . $dueSoon . ' Due Soon</span>';
                }
                if ($vaxTotal > 0) {
                    return '<span style="font-size:11px;color:#22c55e;" title="All vaccinations up to date"><i class="fa fa-check-circle"></i> Up to date</span>';
                }
                return '<span style="font-size:11px;color:#94a3b8;">—</span>';
            })
            ->addColumn('chronic_col', function ($row) {
                $chronic = $row->conditions->filter(fn($c) => $c->status === 'chronic');
                if ($chronic->isEmpty()) {
                    return '<span style="color:#94a3b8;font-size:11px;">—</span>';
                }
                $names = $chronic->map(fn($c) => e($c->condition->name ?? '?'))->implode('<br>');
                $label = $chronic->count() === 1
                    ? e($chronic->first()->condition->name ?? '1 Condition')
                    : $chronic->count() . ' Conditions';
                return '<a href="#" class="chronic-pop" tabindex="0"'
                    . ' data-toggle="popover" data-html="true" data-trigger="focus"'
                    . ' data-placement="right"'
                    . ' data-content="' . htmlspecialchars($names, ENT_QUOTES) . '"'
                    . ' style="font-size:11px;font-weight:700;color:#ef4444;text-decoration:none;">'
                    . '<i class="fas fa-heartbeat" style="margin-right:3px;"></i>' . $label . '</a>';
            })
            ->addColumn('show_url', fn($row) => route('clinic.patients.show', $row->id))
            ->addColumn('edit_url', fn($row) => route('clinic.patients.edit', $row->id))
            ->addColumn('photo_url', fn($row) => $row->photo_url)
            ->addColumn('age_str', fn($row) => $row->dob ? $row->age . ' yrs' : null)
            ->addColumn('owner_name_plain', fn($row) => optional($row->owner)->name ?? null)
            ->addColumn('owner_url', function ($row) {
                $detailId = \Modules\ClinicCore\Entities\ClcPatientContactDetail::where('contact_id', $row->contact_id)->value('id');
                return $detailId ? route('clinic.patient-contacts.show', $detailId) : null;
            })
            ->addColumn('overdue_vax', fn($row) => (int) ($row->overdue_vax_count ?? 0))
            ->addColumn('due_soon_vax', fn($row) => (int) ($row->due_soon_vax_count ?? 0))
            ->addColumn('action', function ($row) {
                $show = '<a href="' . route('clinic.patients.show', $row->id) . '" class="btn btn-xs btn-info" title="View"><i class="fa fa-eye"></i></a> ';
                $edit = '<a href="' . route('clinic.patients.edit', $row->id) . '" class="btn btn-xs btn-warning" title="Edit"><i class="fa fa-edit"></i></a> ';
                $del  = '<button class="btn btn-xs btn-danger btn-delete-pet" data-id="' . $row->id . '" title="Delete"><i class="fa fa-trash"></i></button>';
                return $show . $edit . $del;
            })
            ->rawColumns(['action', 'status_badge', 'patient_name_col', 'owner_col', 'species_col', 'stats_col', 'vaccine_alert_col', 'chronic_col'])
            ->make(true);
    }

    public function create()
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId      = request()->session()->get('user.business_id');
        $conditions      = ClcMedicalCondition::active()->forBusiness($businessId)->orderBy('name')->get();
        $doctors         = ClcDoctor::where('business_id', $businessId)->active()->orderBy('name')->get();
        $preselectedContact = null;

        if (request('contact_id')) {
            $preselectedContact = Contact::where('business_id', $businessId)
                ->find(request('contact_id'));
        }

        $specialties = ClcSpecialty::forBusiness($businessId)->active()
            ->orderBy('sort_order')->get();

        // P3-T1 registered-branch dropdown (ERP business_locations).
        $locations = \App\BusinessLocation::where('business_id', $businessId)
            ->orderBy('name')->get(['id', 'name']);

        return view('clinicCore::patients.create', compact('conditions', 'preselectedContact', 'doctors', 'specialties', 'locations'));
    }

    public function store(Request $request)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate([
            'contact_id' => 'required|integer',
            'patient_name'    => 'required|string|max:100',
            'species'    => 'nullable|string|max:50',
        ]);

        $businessId = request()->session()->get('user.business_id');

        $photoPath = null;
        if ($request->hasFile('photo') && $request->file('photo')->isValid()) {
            $photoPath = $request->file('photo')->store('clinic/patients', 'local');
        }

        $patient = ClcPatient::create(array_merge(
            $request->only(['contact_id', 'patient_name', 'gender', 'dob', 'bloodgroup',
                            'serial_no', 'status', 'height_cm',
                            'allergies', 'chronic_conditions', 'family_history',
                            // P3-T1 patient master identity extensions
                            'national_id', 'passport_number', 'marital_status', 'nationality',
                            'primary_language', 'preferred_name', 'gender_identity',
                            'registered_location_id']),
            [
                'business_id'            => $businessId,
                'photo_path'             => $photoPath,
                'preferred_doctor_id'    => $request->preferred_doctor_id ?: null,
                'default_specialty_id'   => $request->default_specialty_id ?: null,
                'registered_location_id' => $request->registered_location_id ?: null,
            ]
        ));
        $this->drmLog('create', $patient);
        $this->persistSpecialtyProfile($patient, $request);

        if ($patient->preferred_doctor_id) {
            ClcPreferredDoctorHistory::record([
                'business_id'   => $businessId,
                'contact_id'    => $patient->contact_id,
                'patient_id'        => $patient->id,
                'old_doctor_id' => null,
                'new_doctor_id' => $patient->preferred_doctor_id,
                'source'        => 'manual',
            ]);
        }

        // Ensure pet owner detail record exists
        ClcPatientContactDetail::firstOrCreate(
            ['contact_id' => $request->contact_id],
            ['business_id' => $businessId]
        );

        return redirect()->route('clinic.patients.show', $patient->id)
            ->with('status', ['success' => 1, 'msg' => __('clinicCore::lang.saved_successfully')]);
    }

    /**
     * Let the patient's default-specialty driver persist its own extension
     * fields (e.g. a dermatology skin profile) after the shared patient row is
     * saved. No-op for config-only specialties that have no registered driver.
     */
    protected function persistSpecialtyProfile(ClcPatient $patient, Request $request): void
    {
        $driver = optional($patient->defaultSpecialty)->driver();
        if ($driver) {
            try {
                $driver->persistPatientProfile($patient, $request->all());
            } catch (\Throwable $e) {
                \Log::warning('Specialty profile persist failed for patient ' . $patient->id . ': ' . $e->getMessage());
            }
        }
    }

    public function show($id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::with([
            'owner',
            'conditions.condition',
            'conditions.doctor',
            'vaccinations.vaccineType',
            'prescriptions.doctor',
            'appointments.doctor',
            'appointments.vaccinations.vaccineType',
            'appointments.prescriptions',
            'appointments.documents',
            'appointments.appointmentNotes',
            'medicalReports.doctor',
            // P3-T1 structured clinical baseline + P3-T8 alerts
            'structuredAllergies' => fn($q) => $q->orderByDesc('created_at'),
            'medications' => fn($q) => $q->orderByDesc('ongoing')->orderByDesc('created_at'),
            'insurances' => fn($q) => $q->orderByDesc('created_at'),
            'registeredLocation',
        ])->where('business_id', $businessId)->findOrFail($id);

        // P3-T8 active medical-safety alerts for the shared banner partial.
        $activeAlerts = app(\Modules\ClinicCore\Entities\Services\MedicalAlertService::class)
            ->activeFor((int) $patient->id, (int) $businessId);

        $businessId  = request()->session()->get('user.business_id');
        $allConditions = ClcMedicalCondition::active()->forBusiness($businessId)->orderBy('name')->get();

        // Last recorded weight: compare most recent vaccination weight vs appointment weight
        $lastWeightRecord = null;
        $lastVaxWeight = $patient->vaccinations()->whereNotNull('weight_at_time')->orderByDesc('administered_date')->first();
        $lastAptWeight = null;
        if (\Illuminate\Support\Facades\Schema::hasColumn('clc_appointments', 'weight_kg')) {
            $lastAptWeight = $patient->appointments()->whereNotNull('weight_kg')->orderByDesc('appointment_date')->first(['id', 'ref_no', 'appointment_date', 'weight_kg']);
        }
        if ($lastVaxWeight && $lastAptWeight) {
            if ($lastVaxWeight->administered_date->gte($lastAptWeight->appointment_date)) {
                $lastWeightRecord = ['weight' => $lastVaxWeight->weight_at_time, 'label' => 'Vaccination · ' . $lastVaxWeight->administered_date->format('d M Y'), 'url' => null];
            } else {
                $lastWeightRecord = ['weight' => $lastAptWeight->weight_kg, 'label' => 'Appointment ' . $lastAptWeight->ref_no, 'url' => route('clinic.appointments.show', $lastAptWeight->id)];
            }
        } elseif ($lastAptWeight) {
            $lastWeightRecord = ['weight' => $lastAptWeight->weight_kg, 'label' => 'Appointment ' . $lastAptWeight->ref_no, 'url' => route('clinic.appointments.show', $lastAptWeight->id)];
        } elseif ($lastVaxWeight) {
            $lastWeightRecord = ['weight' => $lastVaxWeight->weight_at_time, 'label' => 'Vaccination · ' . optional($lastVaxWeight->administered_date)->format('d M Y'), 'url' => $lastVaxWeight->appointment_id ? route('clinic.appointments.show', $lastVaxWeight->appointment_id) : null];
        }

        // Weight history (last 5 readings from appointments + vaccinations)
        $weightHistory = collect();
        if (\Illuminate\Support\Facades\Schema::hasColumn('clc_appointments', 'weight_kg')) {
            foreach ($patient->appointments as $apt) {
                if (!empty($apt->weight_kg)) {
                    $aptDateStr  = is_string($apt->appointment_date) ? $apt->appointment_date : (optional($apt->appointment_date)->format('Y-m-d') ?? '0000-00-00');
                    $aptTimeStr  = is_string($apt->appointment_time) ? $apt->appointment_time : (optional($apt->appointment_time)->format('H:i:s') ?? '00:00:00');
                    $weightHistory->push([
                        'weight'            => number_format((float) $apt->weight_kg, 2),
                        'date'              => $apt->appointment_date,
                        'sortable_datetime' => $aptDateStr . ' ' . $aptTimeStr,
                        'label'             => 'Appointment · ' . $apt->ref_no,
                        'url'               => route('clinic.appointments.show', $apt->id),
                        'icon'              => 'fa-calendar',
                        'vax_id'            => null,
                    ]);
                }
            }
        }
        foreach ($patient->vaccinations as $vax) {
            if (!empty($vax->weight_at_time)) {
                $vaxDate = $vax->administered_date;
                $vaxDateStr = $vaxDate ? (is_string($vaxDate) ? $vaxDate : $vaxDate->format('Y-m-d')) : '0000-00-00';
                $weightHistory->push([
                    'weight'             => number_format((float) $vax->weight_at_time, 2),
                    'date'               => $vaxDate,
                    'sortable_datetime'  => $vaxDateStr . ' 12:00:00',
                    'label'              => optional($vax->vaccineType)->name ?? 'Vaccination',
                    'url'                => $vax->appointment_id
                        ? route('clinic.appointments.show', $vax->appointment_id)
                        : route('clinic.patients.show', $patient->id) . '#tab-vaccinations',
                    'icon'               => 'fa-syringe',
                    'vax_id'             => $vax->id,
                ]);
            }
        }
        $weightHistory = $weightHistory->sortByDesc('sortable_datetime')->take(5)->values();

        // Item #2 - preferred doctor + change dropdown data.
        $patient->loadMissing('preferredDoctor', 'ownerDetail.preferredDoctor');
        $doctorsList = \Modules\ClinicCore\Entities\ClcDoctor::where('business_id', $patient->business_id)
            ->active()->orderBy('name')->get(['id', 'name', 'specialization']);

        // SIFA P5-T1 — simple per-patient cumulative radiation dose (sum of any
        // recorded DAP / DLP / CTDIvol across this patient's imaging studies).
        // Guarded + fail-soft: only computes when the imaging dose columns exist.
        $imagingDose = ['dap' => null, 'dlp' => null, 'ctdivol' => null];
        try {
            if (\Illuminate\Support\Facades\Schema::hasTable('clc_imaging_studies')
                && \Illuminate\Support\Facades\Schema::hasColumn('clc_imaging_studies', 'dose_dap')) {
                $doseRow = \Illuminate\Support\Facades\DB::table('clc_imaging_studies as s')
                    ->join('clc_imaging_requests as r', 'r.id', '=', 's.imaging_request_id')
                    ->where('r.business_id', $businessId)
                    ->where('r.patient_id', $patient->id)
                    ->selectRaw('SUM(s.dose_dap) as dap, SUM(s.dose_dlp) as dlp, SUM(s.ctdivol) as ctdivol')
                    ->first();
                $imagingDose = [
                    'dap'     => $doseRow && $doseRow->dap !== null ? (float) $doseRow->dap : null,
                    'dlp'     => $doseRow && $doseRow->dlp !== null ? (float) $doseRow->dlp : null,
                    'ctdivol' => $doseRow && $doseRow->ctdivol !== null ? (float) $doseRow->ctdivol : null,
                ];
            }
        } catch (\Throwable $e) {
            \Log::warning('ClcPatient show cumulative dose skipped: ' . $e->getMessage());
        }

        $this->drmLog('view', $patient);
        return view('clinicCore::patients.show', compact(
            'patient', 'allConditions', 'lastWeightRecord', 'weightHistory', 'doctorsList', 'activeAlerts', 'imagingDose'
        ));
    }

    /**
     * Item #2 - POST /clinic/patients/{id}/preferred-doctor
     * Set/clear the pet-level preferred doctor (overrides the owner-level
     * preferred doctor returned by ClcPatient::effectivePreferredDoctorId).
     * Snapshots into clc_preferred_doctor_history if available.
     */
    public function setPreferredDoctor(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }
        $request->validate([
            'preferred_doctor_id' => 'nullable|integer|exists:clc_doctors,id',
        ]);
        $businessId = $request->session()->get('user.business_id');
        $patient = \Modules\ClinicCore\Entities\ClcPatient::where('business_id', $businessId)->findOrFail($id);

        $previousId = $patient->preferred_doctor_id;
        $newId      = $request->preferred_doctor_id ?: null;
        if ($previousId == $newId) {
            return response()->json(['success' => true, 'changed' => false]);
        }
        $patient->preferred_doctor_id = $newId;
        $patient->save();

        try {
            if (\Schema::hasTable('clc_preferred_doctor_history')) {
                \DB::table('clc_preferred_doctor_history')->insert([
                    'business_id'        => $businessId,
                    'scope'              => 'pet',
                    'scope_id'           => $patient->id,
                    'contact_id'         => $patient->contact_id,
                    'patient_id'             => $patient->id,
                    'previous_doctor_id' => $previousId,
                    'new_doctor_id'      => $newId,
                    'changed_by'         => auth()->id(),
                    'changed_at'         => now(),
                    'created_at'         => now(),
                    'updated_at'         => now(),
                ]);
            }
        } catch (\Throwable $e) {
            \Log::warning('Pet preferred-doctor history snapshot failed: ' . $e->getMessage());
        }
        return response()->json([
            'success'         => true,
            'changed'         => true,
            'preferred_doctor'=> $newId
                ? optional(\Modules\ClinicCore\Entities\ClcDoctor::find($newId))->name
                : null,
        ]);
    }

    public function edit($id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId  = request()->session()->get('user.business_id');
        $patient         = ClcPatient::where('business_id', $businessId)->findOrFail($id);
        $conditions  = ClcMedicalCondition::active()->forBusiness($businessId)->orderBy('name')->get();
        $doctors     = ClcDoctor::where('business_id', $businessId)->active()->orderBy('name')->get();
        $specialties = ClcSpecialty::forBusiness($businessId)->active()->orderBy('sort_order')->get();
        $locations   = \App\BusinessLocation::where('business_id', $businessId)
            ->orderBy('name')->get(['id', 'name']);

        return view('clinicCore::patients.create', compact('patient', 'conditions', 'doctors', 'specialties', 'locations'));
    }

    public function update(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate(['patient_name' => 'required|string|max:100']);
        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::where('business_id', $businessId)->findOrFail($id);

        $oldPreferredDoctorId = $patient->preferred_doctor_id;
        $newPreferredDoctorId = $request->preferred_doctor_id ?: null;

        $data = array_merge(
            $request->only(['patient_name', 'gender', 'dob', 'bloodgroup', 'serial_no', 'status', 'height_cm',
                            'allergies', 'chronic_conditions', 'family_history',
                            // P3-T1 patient master identity extensions
                            'national_id', 'passport_number', 'marital_status', 'nationality',
                            'primary_language', 'preferred_name', 'gender_identity']),
            [
                'preferred_doctor_id'    => $newPreferredDoctorId,
                'default_specialty_id'   => $request->default_specialty_id ?: null,
                'registered_location_id' => $request->registered_location_id ?: null,
            ]
        );

        if ($request->hasFile('photo') && $request->file('photo')->isValid()) {
            $data['photo_path'] = $request->file('photo')->store('clinic/patients', 'local');
        }

        $original = $patient->getOriginal();
        $patient->update($data);
        $dirty = array_keys($patient->getChanges());
        $this->drmLog('update', $patient, [
            'before' => array_intersect_key($original, array_flip($dirty)),
            'after'  => array_intersect_key($patient->getAttributes(), array_flip($dirty)),
            'fields' => $dirty,
        ]);
        $this->persistSpecialtyProfile($patient, $request);

        ClcPreferredDoctorHistory::record([
            'business_id'   => $businessId,
            'contact_id'    => $patient->contact_id,
            'patient_id'        => $patient->id,
            'old_doctor_id' => $oldPreferredDoctorId,
            'new_doctor_id' => $newPreferredDoctorId,
            'source'        => 'manual',
        ]);

        return redirect()->route('clinic.patients.show', $id)
            ->with('status', ['success' => 1, 'msg' => __('clinicCore::lang.updated_successfully')]);
    }

    public function destroy($id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::where('business_id', $businessId)->findOrFail($id);
        $snap = $patient->getAttributes();
        $this->drmLog('delete', $patient, ['before' => $this->_drmFilterAttrs($snap)]);
        $patient->delete();

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

    public function markDeceased(\Illuminate\Http\Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        ClcPatient::where('business_id', $businessId)->findOrFail($id)->update([
            'deceased'      => true,
            'deceased_date' => $request->deceased_date ?? now()->toDateString(),
            'status'        => 'inactive',
        ]);

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

    public function getConditions($id)
    {
        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::where('business_id', $businessId)->findOrFail($id);
        $conditions = $patient->conditions()->with('condition')->get();
        return response()->json($conditions);
    }

    public function addCondition(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate(['condition_id' => 'required|integer']);
        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::where('business_id', $businessId)->findOrFail($id);

        $exists = ClcPatientCondition::where('patient_id', $patient->id)
            ->where('condition_id', $request->condition_id)
            ->where('status', '!=', 'resolved')
            ->exists();

        if (!$exists) {
            ClcPatientCondition::create([
                'patient_id'     => $patient->id,
                'condition_id'   => $request->condition_id,
                'diagnosed_date' => $request->diagnosed_date ?? now()->toDateString(),
                'diagnosed_by'   => $request->diagnosed_by,
                'appointment_id' => $request->appointment_id,
                'severity'       => $request->severity,
                'status'         => $request->status ?? 'active',
                'notes'          => $request->notes,
                // P3-T8 problem-list fields (all nullable)
                'certainty'      => in_array($request->certainty, ClcPatientCondition::CERTAINTIES, true) ? $request->certainty : null,
                'condition_type' => in_array($request->condition_type, ClcPatientCondition::CONDITION_TYPES, true) ? $request->condition_type : null,
                'resolved_date'  => $request->status === 'resolved' ? ($request->resolved_date ?? now()->toDateString()) : $request->resolved_date,
            ]);
        }

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

    public function removeCondition($conditionId)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        ClcPatientCondition::findOrFail($conditionId)->delete();
        return response()->json(['success' => true]);
    }

    public function updateCondition(Request $request, $conditionId)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $pc = ClcPatientCondition::whereHas('pet', fn($q) => $q->where('business_id', $businessId))->findOrFail($conditionId);
        $data = $request->only(['severity', 'status', 'diagnosed_date', 'notes', 'resolved_date']);
        // P3-T8 problem-list fields (validated against the enum whitelist).
        if (in_array($request->certainty, ClcPatientCondition::CERTAINTIES, true)) {
            $data['certainty'] = $request->certainty;
        }
        if (in_array($request->condition_type, ClcPatientCondition::CONDITION_TYPES, true)) {
            $data['condition_type'] = $request->condition_type;
        }
        // Auto-stamp resolved_date when moving to resolved without an explicit date.
        if (($data['status'] ?? null) === 'resolved' && empty($data['resolved_date'])) {
            $data['resolved_date'] = now()->toDateString();
        }
        $pc->update($data);

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

    public function byOwner($contactId)
    {
        $businessId = request()->session()->get('user.business_id');
        $patients = ClcPatient::where('business_id', $businessId)
            ->where('contact_id', $contactId)
            ->where('deceased', false)
            ->active()
            ->get(['id', 'patient_name', 'species', 'breed']);

        return response()->json($patients->map(fn($p) => [
            'id'   => $p->id,
            'text' => $p->patient_name . ((config('cliniccore.show_animal_fields', false) && $p->species) ? ' (' . $p->species . ')' : ''),
        ]));
    }

    /** Effective preferred doctor for a pet (pet override → owner general). */
    public function preferredDoctor($id)
    {
        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::with('ownerDetail')->where('business_id', $businessId)->findOrFail($id);

        $doctorId = $patient->effectivePreferredDoctorId();
        $doctor   = $doctorId ? ClcDoctor::where('business_id', $businessId)->find($doctorId) : null;

        return response()->json([
            'patient_id'      => $patient->id,
            'doctor_id'   => $doctor ? $doctor->id : null,
            'doctor_name' => $doctor ? $doctor->name : null,
            'source'      => $patient->preferred_doctor_id
                ? 'pet'
                : (optional($patient->ownerDetail)->preferred_doctor_id ? 'owner' : null),
        ]);
    }

    /** Print-friendly view of pet's full vaccination history + upcoming due dates */
    /**
     * Item #8 - generate a professional PDF clinical history for a pet.
     *
     * Follows the same pattern as printVaccinations() (QR with verify token,
     * clinic header, owner/pet info, etc.) but generated as a real PDF via
     * barryvdh/laravel-dompdf instead of browser print-to-paper.
     *
     *  ?download=1   force a download instead of inline view
     *  ?show=all     include cancelled/no_show visits (default: completed only)
     *
     * Reuses the existing cert_verify_token from the pet so paper copies can
     * be verified against /clinic/verify-vaccinations/{token}.
     */
    public function printClinicalHistoryPdf($id)
    {
        if (!auth()->user()->can('clinic.manage_pets')
            && !auth()->user()->can('clinic.view_appointments')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::with([
            'owner',
            'appointments' => function ($q) {
                $q->orderByDesc('appointment_date')->orderByDesc('appointment_time');
            },
            'appointments.doctor',
            'appointments.vaccinations.vaccineType',
            'appointments.prescriptions.items',
            'appointments.documents',
        ])->where('business_id', $businessId)->findOrFail($id);

        // Stamp a verify token on first print so subsequent paper copies
        // remain verifiable (reuses the same token as the vaccine print).
        if (empty($patient->cert_verify_token)) {
            $patient->cert_verify_token = bin2hex(random_bytes(16));
            $patient->saveQuietly();
        }
        $verifyUrl = route('clinic.vaccinations.verify', $patient->cert_verify_token);
        $qrSrc = 'https://api.qrserver.com/v1/create-qr-code/?size=140x140&data=' . urlencode($verifyUrl);

        // Filter visits: by default only "finalised" (completed / cancelled /
        // no_show). The print-history requirement in 5.1 explicitly excluded
        // pending appointments; the PDF honours the same rule.
        $showAll = request()->boolean('show');
        $finalised = ['completed', 'cancelled', 'no_show'];
        $visits = $showAll
            ? $patient->appointments
            : $patient->appointments->whereIn('status', $finalised);

        $business = \App\Business::findOrFail($businessId);
        $ownerName   = trim(optional($patient->owner)->name ?? '') ?: (optional($patient->owner)->supplier_business_name ?? '—');
        $ownerMobile = optional($patient->owner)->mobile ?? '';
        $dateFmt = session('business.date_format', 'd M Y');

        $data = compact(
            'patient', 'visits', 'business', 'ownerName', 'ownerMobile',
            'verifyUrl', 'qrSrc', 'dateFmt'
        );

        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('clinicCore::patients.print-clinical-history-pdf', $data)
            ->setPaper('a4', 'portrait')
            ->setOptions([
                'isHtml5ParserEnabled' => true,
                'isRemoteEnabled'      => true,   // for the external QR image
                'defaultFont'          => 'sans-serif',
                'dpi'                  => 110,
            ]);

        $filename = 'clinical-history-' . preg_replace('/[^A-Za-z0-9_-]/', '_', $patient->patient_name ?? 'pet') . '-' . now()->format('Ymd') . '.pdf';
        return request()->boolean('download')
            ? $pdf->download($filename)
            : $pdf->stream($filename);
    }

    public function printVaccinations($id)
    {
        if (!auth()->user()->can('clinic.manage_pets')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $patient = ClcPatient::with([
            'owner',
            'vaccinations' => fn($q) => $q->orderByDesc('administered_date'),
            'vaccinations.vaccineType',
            'vaccinations.appointment.doctor', // fallback when administered_by is null
        ])->where('business_id', $businessId)->findOrFail($id);

        // Allocate a verification token lazily — first print stamps it, every
        // subsequent print reuses the same QR so paper copies stay verifiable.
        if (empty($patient->cert_verify_token)) {
            $patient->cert_verify_token = bin2hex(random_bytes(16)); // 32 hex chars
            $patient->saveQuietly();
        }
        $verifyUrl = route('clinic.vaccinations.verify', $patient->cert_verify_token);
        $qrSrc = 'https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=' . urlencode($verifyUrl);

        // Resolve direct administered_by → doctor name
        $docIds = $patient->vaccinations->pluck('administered_by')->filter()->unique();
        $doctors = $docIds->isNotEmpty()
            ? \Modules\ClinicCore\Entities\ClcDoctor::whereIn('id', $docIds)->pluck('name', 'id')
            : collect();

        // Decorate each vaccination with a resolved "administered_by_name" so
        // the view doesn't need to guess. Falls back to the linked appointment's
        // doctor when the vaccination row itself has no administered_by.
        foreach ($patient->vaccinations as $vax) {
            $name = $vax->administered_by ? ($doctors[$vax->administered_by] ?? null) : null;
            if (!$name && optional($vax->appointment)->doctor) {
                $name = $vax->appointment->doctor->name . ' *';
            }
            $vax->administered_by_name = $name; // null if neither found
        }

        $business = \App\Business::findOrFail($businessId);

        return view('clinicCore::patients.print-vaccinations', compact('patient', 'business', 'doctors', 'verifyUrl', 'qrSrc'));
    }
}
