<?php

namespace Modules\VetClinic\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\VetClinic\Entities\Services\VcMedicineDispenseService;
use Modules\VetClinic\Entities\VcMedicine;
use Modules\VetClinic\Entities\VcPrescription;
use Modules\VetClinic\Entities\VcPrescriptionItem;
use Modules\VetClinic\Entities\VcDoctor;
use Modules\VetClinic\Entities\VcPet;
use Yajra\DataTables\Facades\DataTables;

class VcPrescriptionController extends Controller
{
    use \Modules\VetClinic\Http\Controllers\Traits\LogsVcActivity;

    public function index()
    {
        if (!auth()->user()->can('vet_clinic.manage_prescriptions')) {
            abort(403, 'Unauthorized action.');
        }

        return view('vetClinic::prescriptions.index');
    }

    /**
     * AI veterinary prescription safety check — screens the proposed drug list
     * against the pet's species, known conditions and active medications for
     * interaction / species-toxicity / contraindication / duplicate risks
     * (incl. interactions BETWEEN the new drugs). Decision-support only; runs on
     * the shared AiCore engine (Groq -> Bynara failover).
     */
    public function checkSafety(Request $request)
    {
        if (!auth()->user()->can('vet_clinic.manage_prescriptions') && !auth()->user()->can('vet_ai.use_assistant')) {
            abort(403, 'Unauthorized action.');
        }
        $request->validate([
            'drugs'          => 'required|array|min:1|max:30',
            'drugs.*.name'   => 'required|string|max:200',
            'drugs.*.dosage' => 'nullable|string|max:120',
            'pet_id'         => 'nullable|integer',
        ]);

        if (!class_exists('\Modules\AiCore\Entities\Services\AiClient')) {
            return response()->json(['success' => false, 'msg' => 'AI is not available. Configure AiCore.'], 422);
        }
        $businessId = (int) $request->session()->get('user.business_id');
        $settings = \Modules\AiCore\Entities\AiProvider::forBusiness($businessId, 'default');
        if (!$settings->isConfigured()) {
            return response()->json(['success' => false, 'msg' => 'AI is not configured. Open AI Settings.'], 422);
        }

        $petName = 'the patient';
        $species = '';
        $conditions = 'none recorded';
        if ($request->filled('pet_id')) {
            $pet = VcPet::where('business_id', $businessId)->find($request->pet_id);
            if ($pet) {
                $petName = $pet->petname ?: $petName;
                $species = (string) ($pet->species ?? '');
                try {
                    $conditions = $pet->conditions()->with('condition')->get()
                        ->map(fn ($c) => optional($c->condition)->name)
                        ->filter()->unique()->implode('; ') ?: 'none recorded';
                } catch (\Throwable $e) {
                    $conditions = 'none recorded';
                }
            }
        }
        $activeMeds = $this->activeMedicationsList($businessId, (int) $request->input('pet_id'));

        $newDrugs = collect($request->input('drugs', []))
            ->map(fn ($d) => trim(((string) ($d['name'] ?? '')) . ' ' . ((string) ($d['dosage'] ?? ''))))
            ->filter()->implode("\n- ");

        $system = "You are a VETERINARY medication-safety checker. Given a list of NEW drugs to be prescribed together to an animal patient, plus its species, known conditions and current medications, identify clinically significant problems: drug-drug interactions (including BETWEEN the new drugs), species-specific toxicity / contraindications (e.g. NSAIDs or paracetamol in cats, ivermectin in MDR1/herding breeds), condition contraindications, dosing/route concerns, and duplicate therapy. Be specific and concise.\n\n"
            . "Output STRICTLY a JSON object: {\"risk\":\"none|low|moderate|high\",\"flags\":[{\"type\":\"interaction|contraindication|species_toxicity|duplicate|dose\",\"severity\":\"low|moderate|high\",\"detail\":\"<one clear sentence>\"}],\"summary\":\"<one short sentence>\"}.\n"
            . "Rules: NEVER invent data — use only what is provided ('none recorded' means no data). If nothing concerning, risk='none' and flags=[]. Decision-support only; the attending vet must verify against a current veterinary formulary.";
        $user = "PATIENT: {$petName}" . ($species ? " (species: {$species})" : '') . "\n"
            . "KNOWN CONDITIONS: {$conditions}\n"
            . "CURRENT MEDICATIONS: {$activeMeds}\n\n"
            . "NEW DRUGS TO PRESCRIBE:\n- {$newDrugs}";

        // Deterministic for an identical drug+history set — short-TTL cacheable so
        // re-checking the same combination is instant and free.
        $res = (new \Modules\AiCore\Entities\Services\AiClient())->chat($settings, $system, $user, [
            'module' => 'VetClinic', 'feature' => 'rx_safety_check', 'cacheable' => true,
        ]);
        if (empty($res['ok'])) {
            return response()->json(['success' => false, 'msg' => $res['error'] ?? 'AI request failed.'], 502);
        }
        $clean = preg_replace('/^```(?:json)?\s*|\s*```$/m', '', trim((string) ($res['text'] ?? '')));
        $parsed = json_decode($clean, true);
        if (!is_array($parsed)) {
            return response()->json(['success' => true, 'risk' => 'unknown', 'flags' => [], 'summary' => trim((string) ($res['text'] ?? ''))]);
        }
        $risk = in_array(($parsed['risk'] ?? ''), ['none', 'low', 'moderate', 'high'], true) ? $parsed['risk'] : 'unknown';
        $flags = [];
        foreach ((array) ($parsed['flags'] ?? []) as $f) {
            if (!is_array($f)) continue;
            $flags[] = [
                'type'     => mb_substr((string) ($f['type'] ?? ''), 0, 24),
                'severity' => mb_substr((string) ($f['severity'] ?? ''), 0, 12),
                'detail'   => mb_substr((string) ($f['detail'] ?? ''), 0, 400),
            ];
        }
        return response()->json([
            'success' => true,
            'risk'    => $risk,
            'flags'   => $flags,
            'summary' => mb_substr((string) ($parsed['summary'] ?? ''), 0, 400),
        ]);
    }

    /** Active-medication names for a pet (empty-safe; "none recorded" fallback). */
    private function activeMedicationsList(int $businessId, int $petId): string
    {
        if (!$petId || !\Schema::hasTable('vc_prescription_items') || !\Schema::hasTable('vc_prescriptions')) {
            return 'none recorded';
        }
        try {
            $rows = \DB::table('vc_prescription_items as i')
                ->join('vc_prescriptions as p', 'p.id', '=', 'i.prescription_id')
                ->where('p.business_id', $businessId)
                ->where('p.pet_id', $petId)
                ->where('p.status', 'active')
                ->orderByDesc('p.prescribed_date')
                ->limit(25)
                ->get(['i.medicine_name', 'i.dosage']);
        } catch (\Throwable $e) {
            return 'none recorded';
        }
        $list = $rows->map(fn ($r) => trim($r->medicine_name . ' ' . ($r->dosage ?? '')))->filter()->unique()->implode('; ');
        return $list !== '' ? $list : 'none recorded';
    }

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

        $businessId = request()->session()->get('user.business_id');
        $query = VcPrescription::with(['pet', 'owner', 'doctor'])
            ->where('business_id', $businessId);

        if ($request->filled('filter_status')) {
            $query->where('status', $request->filter_status);
        }
        if ($request->filled('filter_search')) {
            $term = $request->filter_search;
            $query->where(function ($q) use ($term) {
                $q->where('ref_no', 'like', '%' . $term . '%')
                  ->orWhereHas('pet',   fn($sq) => $sq->where('petname', 'like', '%' . $term . '%'))
                  ->orWhereHas('owner', fn($sq) => $sq->where('name', 'like', '%' . $term . '%'));
            });
        }
        if ($request->filled('filter_date_from')) {
            try {
                $from = \Carbon\Carbon::createFromFormat(
                    session('business.date_format', 'd M Y'),
                    $request->filter_date_from
                )->toDateString();
                $query->whereDate('prescribed_date', '>=', $from);
            } catch (\Exception $e) {}
        }
        if ($request->filled('filter_date_to')) {
            try {
                $to = \Carbon\Carbon::createFromFormat(
                    session('business.date_format', 'd M Y'),
                    $request->filter_date_to
                )->toDateString();
                $query->whereDate('prescribed_date', '<=', $to);
            } catch (\Exception $e) {}
        }

        $dateFormat = session('business.date_format', 'd M Y');

        return DataTables::of($query)
            ->addColumn('ref_no_col', fn($row) => '<a href="' . route('vc.prescriptions.show', $row->id) . '" style="font-weight:700;font-family:monospace;color:#475569;">' . e($row->ref_no) . '</a>')
            ->addColumn('pet_name', function ($row) {
                if (!$row->pet) return '—';
                return '<a href="' . route('vc.pets.show', $row->pet->id) . '" style="font-weight:600;">' . e($row->pet->petname) . '</a>'
                    . ($row->pet->species ? '<br><small class="text-muted">' . e(ucfirst($row->pet->species)) . '</small>' : '');
            })
            ->addColumn('owner_name', function ($row) {
                if (!$row->owner) return '—';
                $ownerDetailId = \Modules\VetClinic\Entities\VcPetOwnerDetail::where('contact_id', $row->owner->id)->value('id');
                $url = $ownerDetailId ? route('vc.pet-owners.show', $ownerDetailId) : '#';
                return '<a href="' . $url . '" style="font-weight:600;">' . e($row->owner->name ?? '—') . '</a>';
            })
            ->addColumn('doctor_name', fn($row) => optional($row->doctor)->name ?? '—')
            ->addColumn('prescribed_date_col', fn($row) => $row->prescribed_date
                ? \Carbon\Carbon::parse($row->prescribed_date)->format($dateFormat) : '—')
            ->addColumn('valid_until_col', function ($row) use ($dateFormat) {
                if (!$row->valid_until) return '—';
                $expired = \Carbon\Carbon::parse($row->valid_until)->isPast();
                $fmt = \Carbon\Carbon::parse($row->valid_until)->format($dateFormat);
                return $expired
                    ? '<span class="text-danger" title="Expired">' . $fmt . '</span>'
                    : '<span class="text-success">' . $fmt . '</span>';
            })
            ->addColumn('status_badge', function ($row) {
                $colors = ['active' => 'success', 'completed' => 'info', 'cancelled' => 'danger'];
                return '<span class="label label-' . ($colors[$row->status] ?? 'default') . '">' . ucfirst($row->status) . '</span>';
            })
            ->addColumn('action', function ($row) {
                $show  = '<a href="' . route('vc.prescriptions.show', $row->id) . '" class="btn btn-xs btn-info" title="View"><i class="fa fa-eye"></i></a> ';
                $print = '<a href="' . route('vc.prescriptions.print', $row->id) . '" target="_blank" class="btn btn-xs btn-default" title="Print"><i class="fa fa-print"></i></a> ';
                $del   = auth()->user()->can('vet_clinic.manage_prescriptions')
                    ? '<button class="btn btn-xs btn-danger btn-delete-rx" data-id="' . $row->id . '" title="Delete"><i class="fa fa-trash"></i></button>'
                    : '';
                return $show . $print . $del;
            })
            ->rawColumns(['action', 'status_badge', 'ref_no_col', 'pet_name', 'owner_name', 'valid_until_col'])
            ->make(true);
    }

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

        $businessId = request()->session()->get('user.business_id');
        $doctors    = VcDoctor::where('business_id', $businessId)->active()->orderBy('name')->get();

        return view('vetClinic::prescriptions.create', compact('doctors'));
    }

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

        $request->validate([
            'contact_id'      => 'required|integer',
            'pet_id'          => 'required|integer',
            'prescribed_date' => 'required|date',
            'items'           => 'required|array|min:1',
            'items.*.medicine_name' => 'required|string',
        ]);

        $businessId = request()->session()->get('user.business_id');
        $refNo = 'RX-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -5));

        $prescription = VcPrescription::create([
            'business_id'    => $businessId,
            'ref_no'         => $refNo,
            'contact_id'     => $request->contact_id,
            'pet_id'         => $request->pet_id,
            'doctor_id'      => $request->doctor_id,
            'appointment_id' => $request->appointment_id,
            'prescribed_date'=> $request->prescribed_date,
            'valid_until'    => $request->valid_until,
            'diagnosis'      => $request->diagnosis,
            'notes'          => $request->notes,
            'status'         => 'active',
        ]);

        foreach ($request->items as $med) {
            VcPrescriptionItem::create([
                'prescription_id' => $prescription->id,
                'medicine_id'     => $med['medicine_id'] ?? null,
                'medicine_name'   => $med['medicine_name'],
                'dosage'          => $med['dosage'] ?? null,
                'frequency'       => $med['frequency'] ?? null,
                'duration_days'   => $med['duration_days'] ?? null,
                'instructions'    => $med['instructions'] ?? null,
                'quantity'        => $med['quantity'] ?? 1,
            ]);
        }

        $this->vcLog('create', $prescription, ['note' => 'Prescription with ' . count($request->items) . ' item(s)']);

        return redirect()->route('vc.prescriptions.show', $prescription->id)
            ->with('status', ['success' => 1, 'msg' => __('vetClinic::lang.saved_successfully')]);
    }

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

        $businessId = request()->session()->get('user.business_id');
        $prescription = VcPrescription::with(['pet', 'owner', 'doctor', 'items', 'appointment'])
            ->where('business_id', $businessId)->findOrFail($id);

        return view('vetClinic::prescriptions.show', compact('prescription'));
    }

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

        $businessId   = request()->session()->get('user.business_id');
        $prescription = VcPrescription::with(['items', 'appointment'])->where('business_id', $businessId)->findOrFail($id);
        $doctors      = VcDoctor::where('business_id', $businessId)->active()->orderBy('name')->get();

        // Load directly — avoids any scope/relationship issues with Contact
        $ownerContact = \App\Contact::find($prescription->contact_id);
        $petRecord    = VcPet::find($prescription->pet_id);

        return view('vetClinic::prescriptions.create', compact('prescription', 'doctors', 'ownerContact', 'petRecord'));
    }

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

        $businessId   = request()->session()->get('user.business_id');
        $prescription = VcPrescription::where('business_id', $businessId)->findOrFail($id);
        $before = $prescription->getOriginal();

        $prescription->update($request->only(['doctor_id', 'prescribed_date', 'diagnosis', 'notes', 'status']));
        $dirty = array_keys($prescription->getChanges());
        $this->vcLog('update', $prescription, [
            'before' => array_intersect_key($before, array_flip($dirty)),
            'after'  => array_intersect_key($prescription->getAttributes(), array_flip($dirty)),
            'fields' => $dirty,
        ]);

        if ($request->has('items')) {
            $prescription->items()->delete();
            foreach ($request->items as $med) {
                VcPrescriptionItem::create(array_merge($med, [
                    'prescription_id' => $prescription->id,
                    'quantity'        => 1,
                ]));
            }
        }

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

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

        $businessId = request()->session()->get('user.business_id');
        $prescription = VcPrescription::where('business_id', $businessId)->findOrFail($id);
        $this->vcLog('delete', $prescription, ['before' => $this->_vcFilterAttrs($prescription->getAttributes())]);
        $prescription->delete();

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

    public function storeFromConsultation(Request $request)
    {
        if (!auth()->user()->can('vet_clinic.manage_prescriptions')) {
            return response()->json(['success' => false, 'msg' => 'Unauthorized'], 403);
        }

        $request->validate([
            'appointment_id'        => 'required|integer',
            'items'                 => 'required|array|min:1',
            'items.*.medicine_name' => 'required|string',
        ]);

        $businessId  = request()->session()->get('user.business_id');
        $appointment = \Modules\VetClinic\Entities\VcAppointment::where('business_id', $businessId)
                           ->findOrFail($request->appointment_id);

        // Replace existing prescription for this appointment
        VcPrescription::where('appointment_id', $appointment->id)
                       ->where('business_id', $businessId)
                       ->each(function ($rx) { $rx->items()->delete(); $rx->delete(); });

        $refNo = 'RX-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -5));

        $prescription = VcPrescription::create([
            'business_id'    => $businessId,
            'ref_no'         => $refNo,
            'contact_id'     => $appointment->contact_id,
            'pet_id'         => $appointment->pet_id,
            'doctor_id'      => $appointment->doctor_id,
            'appointment_id' => $appointment->id,
            'prescribed_date'=> now()->toDateString(),
            'diagnosis'      => $request->diagnosis,
            'status'         => 'active',
        ]);

        foreach ($request->items as $med) {
            VcPrescriptionItem::create([
                'prescription_id' => $prescription->id,
                'medicine_id'     => $med['medicine_id'] ?? null,
                'medicine_name'   => $med['medicine_name'],
                'dosage'          => $med['dosage'] ?? null,
                'frequency'       => $med['frequency'] ?? null,
                'duration_days'   => $med['duration_days'] ?? null,
                'instructions'    => $med['note'] ?? null,
                'quantity'        => 1,
            ]);
        }

        $this->vcLog('create', $prescription, ['note' => 'Prescription auto-created from consultation #' . $appointment->id]);

        return response()->json([
            'success'         => true,
            'msg'             => 'Prescription created.',
            'prescription_id' => $prescription->id,
            'show_url'        => route('vc.prescriptions.show', $prescription->id),
            'print_url'       => route('vc.prescriptions.print', $prescription->id),
        ]);
    }

    public function print($id)
    {
        if (!auth()->user()->can('vet_clinic.manage_prescriptions')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId   = request()->session()->get('user.business_id');
        $prescription = VcPrescription::with(['pet', 'owner', 'doctor', 'items', 'appointment'])
            ->where('business_id', $businessId)->findOrFail($id);

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

        return view('vetClinic::prescriptions.print', compact('prescription', 'business'));
    }

    /**
     * AJAX: FEFO-sorted batches available to dispense for a prescription item.
     * Used by the dispense picker on the prescription show view.
     */
    public function dispenseOptions(Request $request, $itemId)
    {
        if (!auth()->user()->can('vet_clinic.manage_prescriptions')) {
            abort(403, 'Unauthorized action.');
        }
        $businessId = $request->session()->get('user.business_id');

        $item = VcPrescriptionItem::with('prescription')->findOrFail($itemId);
        if (!$item->prescription || $item->prescription->business_id != $businessId) {
            abort(404);
        }
        if (!$item->medicine_id) {
            return response()->json(['linked' => false, 'batches' => []]);
        }
        $medicine = VcMedicine::find($item->medicine_id);
        if (!$medicine || empty($medicine->product_id)) {
            return response()->json([
                'linked'  => false,
                'msg'     => "The medicine '{$item->medicine_name}' has no ERP product link — set it on the medicine catalogue first.",
                'batches' => [],
            ]);
        }

        $svc      = app(VcMedicineDispenseService::class);
        $batches  = $svc->fefoSuggestions($medicine);

        return response()->json([
            'linked'     => true,
            'product_id' => $medicine->product_id,
            'unit'       => $medicine->unit,
            'batches'    => $batches->values(),
            'already_dispensed' => !empty($item->dispensed_at),
        ]);
    }

    /**
     * Dispense a prescription item against a specific purchase_line. Decrements
     * ERP stock at the chosen location via the dispense service.
     */
    public function dispenseItem(Request $request, $itemId)
    {
        if (!auth()->user()->can('vet_clinic.manage_prescriptions')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate([
            'purchase_line_id' => 'required|integer',
            'qty'              => 'required|numeric|gt:0',
            'location_id'      => 'required|integer',
        ]);

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

        $item = VcPrescriptionItem::with('prescription')->findOrFail($itemId);
        if (!$item->prescription || $item->prescription->business_id != $businessId) {
            abort(404);
        }
        if (!empty($item->dispensed_at)) {
            return response()->json(['success' => false, 'msg' => 'This item has already been dispensed.'], 422);
        }

        try {
            $updated = app(VcMedicineDispenseService::class)->dispense(
                $item,
                (int) $request->purchase_line_id,
                (float) $request->qty,
                (int) $request->location_id,
                auth()->id()
            );
        } catch (\InvalidArgumentException $e) {
            return response()->json(['success' => false, 'msg' => $e->getMessage()], 422);
        }

        $this->vcLog('update', $updated, [
            'action'           => 'dispensed',
            'purchase_line_id' => $updated->purchase_line_id,
            'dispensed_qty'    => $updated->dispensed_qty,
        ]);

        return response()->json([
            'success'          => true,
            'msg'              => 'Dispensed — stock decremented.',
            'dispensed_at'     => $updated->dispensed_at?->toIso8601String(),
            'dispensed_qty'    => $updated->dispensed_qty,
            'purchase_line_id' => $updated->purchase_line_id,
        ]);
    }
}
