<?php

namespace Modules\ClinicCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Modules\ClinicCore\Entities\ClcPatient;
use Modules\ClinicCore\Entities\ClcTreatmentPackage;
use Modules\ClinicCore\Entities\ClcPatientTreatmentPlan;
use Modules\ClinicCore\Entities\ClcTreatmentSession;

/**
 * Treatment packages (catalogue) + a patient's purchased plans and their
 * sessions. Shared ClinicCore feature used by derma/aesthetic/dental clinics
 * to sell and track multi-session courses.
 */
class ClcTreatmentPlanController extends Controller
{
    private function biz()
    {
        return request()->session()->get('user.business_id');
    }

    // ───────────────────────── Patient plans ─────────────────────────

    private function guardPatient($patientId): ClcPatient
    {
        if (!auth()->user()->can('clinic.manage_pets')) abort(403, 'Unauthorized action.');
        return ClcPatient::where('business_id', $this->biz())->findOrFail($patientId);
    }

    /** JSON: a patient's plans (with sessions/progress) + packages for the dropdown. */
    public function patientPlans($patientId)
    {
        $patient = $this->guardPatient($patientId);

        $plans = ClcPatientTreatmentPlan::with(['sessions.doctor:id,name'])
            ->where('clc_patient_id', $patient->id)
            ->orderByDesc('id')->get();

        $packages = ClcTreatmentPackage::active()->forBusiness($this->biz())
            ->orderBy('sort_order')->orderBy('name')
            ->get(['id', 'name', 'total_sessions', 'interval_days', 'price']);

        return response()->json([
            'success'  => true,
            'packages' => $packages,
            'plans'    => $plans->map(function ($p) {
                return [
                    'id'             => $p->id,
                    'name'           => $p->name,
                    'status'         => $p->status,
                    'total_sessions' => $p->total_sessions,
                    'used_sessions'  => $p->used_sessions,
                    'progress_pct'   => $p->progress_pct,
                    'price'          => $p->price,
                    'started_at'     => optional($p->started_at)->format('Y-m-d'),
                    'notes'          => $p->notes,
                    'sessions'       => $p->sessions->map(fn ($s) => [
                        'id'           => $s->id,
                        'session_no'   => $s->session_no,
                        'status'       => $s->status,
                        'performed_at' => optional($s->performed_at)->format('Y-m-d'),
                        'doctor'       => optional($s->doctor)->name,
                        'notes'        => $s->notes,
                    ]),
                ];
            }),
        ]);
    }

    /** Assign a plan to a patient (from a package, or custom). Creates session slots. */
    public function assignPlan(Request $request, $patientId)
    {
        $patient = $this->guardPatient($patientId);
        $businessId = $this->biz();

        $request->validate([
            'package_id'     => 'nullable|integer',
            'name'           => 'required_without:package_id|nullable|string|max:150',
            'total_sessions' => 'nullable|integer|min:1|max:60',
            'price'          => 'nullable|numeric|min:0',
            'started_at'     => 'nullable|date',
        ]);

        $name  = $request->name;
        $total = (int) $request->total_sessions;
        $price = $request->price;

        if ($request->filled('package_id')) {
            $pkg = ClcTreatmentPackage::forBusiness($businessId)->findOrFail($request->package_id);
            $name  = $name ?: $pkg->name;
            $total = $total ?: (int) $pkg->total_sessions;
            $price = $request->filled('price') ? $price : $pkg->price;
        }
        $total = max(1, $total ?: 1);

        $plan = DB::transaction(function () use ($businessId, $patient, $request, $name, $total, $price) {
            $plan = ClcPatientTreatmentPlan::create([
                'business_id'    => $businessId,
                'clc_patient_id' => $patient->id,
                'package_id'     => $request->package_id ?: null,
                'name'           => $name,
                'total_sessions' => $total,
                'price'          => $price,
                'status'         => 'active',
                'started_at'     => $request->started_at ?: now()->toDateString(),
                'notes'          => $request->notes,
                'created_by'     => auth()->id(),
            ]);
            for ($i = 1; $i <= $total; $i++) {
                ClcTreatmentSession::create([
                    'business_id' => $businessId,
                    'plan_id'     => $plan->id,
                    'session_no'  => $i,
                    'status'      => 'scheduled',
                    'created_by'  => auth()->id(),
                ]);
            }
            return $plan;
        });

        return response()->json(['success' => true, 'plan_id' => $plan->id, 'msg' => 'Treatment plan created.']);
    }

    /** Mark the next scheduled session of a plan as completed. */
    public function recordSession(Request $request, $planId)
    {
        if (!auth()->user()->can('clinic.manage_pets')) abort(403);
        $businessId = $this->biz();
        $plan = ClcPatientTreatmentPlan::where('business_id', $businessId)->findOrFail($planId);

        $session = ClcTreatmentSession::where('plan_id', $plan->id)
            ->where('status', 'scheduled')->orderBy('session_no')->first();
        if (!$session) {
            return response()->json(['success' => false, 'msg' => 'All sessions are already completed.'], 422);
        }

        $session->update([
            'status'       => 'completed',
            'performed_at' => $request->performed_at ?: now()->toDateString(),
            'performed_by' => $request->performed_by ?: null,
            'appointment_id' => $request->appointment_id ?: null,
            'notes'        => $request->notes,
        ]);
        $plan->refreshStatus();

        return response()->json([
            'success' => true,
            'msg'     => "Session {$session->session_no} recorded.",
            'used'    => $plan->fresh()->used_sessions,
            'status'  => $plan->fresh()->status,
        ]);
    }

    /** Cancel a plan. */
    public function cancelPlan($planId)
    {
        if (!auth()->user()->can('clinic.manage_pets')) abort(403);
        $plan = ClcPatientTreatmentPlan::where('business_id', $this->biz())->findOrFail($planId);
        $plan->update(['status' => 'cancelled']);
        return response()->json(['success' => true, 'msg' => 'Plan cancelled.']);
    }

    // ───────────────────────── Package catalogue ─────────────────────────

    public function packages()
    {
        if (!auth()->user()->can('clinic.access_settings')) abort(403, 'Unauthorized action.');
        return view('clinicCore::settings.treatment-packages');
    }

    public function packagesList()
    {
        if (!auth()->user()->can('clinic.access_settings')) abort(403);
        $rows = ClcTreatmentPackage::forBusiness($this->biz())
            ->orderBy('sort_order')->orderBy('name')->get();
        return response()->json(['data' => $rows->map(fn ($p) => [
            'id'             => $p->id,
            'name'           => $p->name,
            'total_sessions' => $p->total_sessions,
            'interval_days'  => $p->interval_days,
            'price'          => $p->price,
            'is_active'      => (bool) $p->is_active,
            'is_system'      => is_null($p->business_id),
        ])]);
    }

    public function storePackage(Request $request)
    {
        if (!auth()->user()->can('clinic.access_settings')) abort(403);
        $request->validate([
            'name'           => 'required|string|max:150',
            'total_sessions' => 'required|integer|min:1|max:60',
            'interval_days'  => 'nullable|integer|min:0|max:365',
            'price'          => 'nullable|numeric|min:0',
            'description'    => 'nullable|string',
        ]);
        ClcTreatmentPackage::create([
            'business_id'    => $this->biz(),
            'name'           => $request->name,
            'description'    => $request->description,
            'total_sessions' => $request->total_sessions,
            'interval_days'  => $request->interval_days,
            'price'          => $request->price,
            'is_active'      => true,
        ]);
        return response()->json(['success' => true, 'msg' => 'Package added.']);
    }

    public function updatePackage(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.access_settings')) abort(403);
        // Only the owning business can edit its own packages (not system templates).
        $pkg = ClcTreatmentPackage::where('business_id', $this->biz())->findOrFail($id);
        $request->validate([
            'name'           => 'required|string|max:150',
            'total_sessions' => 'required|integer|min:1|max:60',
            'interval_days'  => 'nullable|integer|min:0|max:365',
            'price'          => 'nullable|numeric|min:0',
            'is_active'      => 'nullable|boolean',
        ]);
        $pkg->update($request->only(['name', 'description', 'total_sessions', 'interval_days', 'price'])
            + ['is_active' => $request->boolean('is_active', true)]);
        return response()->json(['success' => true, 'msg' => 'Package updated.']);
    }

    public function destroyPackage($id)
    {
        if (!auth()->user()->can('clinic.access_settings')) abort(403);
        $pkg = ClcTreatmentPackage::where('business_id', $this->biz())->findOrFail($id);
        $pkg->delete();
        return response()->json(['success' => true, 'msg' => 'Package deleted.']);
    }
}
