<?php

namespace Modules\DentalClinic\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\ClinicCore\Entities\ClcPatient;
use Modules\DentalClinic\Entities\DentalTreatmentPlanItem;

/**
 * Dental treatment-plan builder. Dentists assemble a proposed plan (rows), see a
 * running estimate, print a patient-friendly copy, and convert the plan into a
 * shared ClinicCore treatment plan (clc_patient_treatment_plans + sessions) via
 * ClinicCore's own model API. Business-scoped, gated on
 * dental.treatment_plan.manage.
 */
class DentalTreatmentPlanController extends Controller
{
    private function biz()
    {
        return request()->session()->get('user.business_id');
    }

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

    /** JSON: a patient's plan items grouped by plan_name, with per-plan totals. */
    public function index($patientId)
    {
        $patient = $this->guardPatient($patientId);

        $items = DentalTreatmentPlanItem::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)
            ->orderBy('plan_name')->orderBy('sort_order')->orderBy('id')->get();

        $plans = $items->groupBy('plan_name')->map(function ($group, $planName) {
            return [
                'plan_name'      => $planName,
                'total_estimate' => (float) $group->sum('estimated_cost'),
                'converted'      => (bool) $group->firstWhere('clc_treatment_plan_id', '!=', null),
                'items'          => $group->map(fn ($i) => $this->present($i))->values(),
            ];
        })->values();

        return response()->json(['success' => true, 'plans' => $plans]);
    }

    /** Add one row to a plan. */
    public function store(Request $request, $patientId)
    {
        $patient = $this->guardPatient($patientId);
        $data = $this->validated($request);

        $item = DentalTreatmentPlanItem::create($data + [
            'business_id' => $this->biz(),
            'patient_id'  => $patient->id,
            'created_by'  => auth()->id(),
        ]);

        return response()->json(['success' => true, 'msg' => 'Item added.', 'data' => $this->present($item)]);
    }

    public function update(Request $request, $patientId, $id)
    {
        $patient = $this->guardPatient($patientId);
        $item = DentalTreatmentPlanItem::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)->findOrFail($id);

        $item->update($this->validated($request));

        return response()->json(['success' => true, 'msg' => 'Item updated.', 'data' => $this->present($item->fresh())]);
    }

    public function destroy($patientId, $id)
    {
        $patient = $this->guardPatient($patientId);
        DentalTreatmentPlanItem::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)->where('id', $id)->delete();

        return response()->json(['success' => true, 'msg' => 'Item removed.']);
    }

    /**
     * Convert a named plan into a shared ClinicCore treatment plan
     * (clc_patient_treatment_plans + one session slot per plan item). Uses
     * ClinicCore's own Eloquent models. Fail-soft: if those classes/columns are
     * absent (shape drift) we flag it and leave the dental plan untouched.
     */
    public function convert(Request $request, $patientId)
    {
        $patient = $this->guardPatient($patientId);
        $businessId = $this->biz();

        $request->validate(['plan_name' => 'required|string|max:150']);
        $planName = $request->plan_name;

        $items = DentalTreatmentPlanItem::where('business_id', $businessId)
            ->where('patient_id', $patient->id)
            ->where('plan_name', $planName)
            ->orderBy('sort_order')->orderBy('id')->get();

        if ($items->isEmpty()) {
            return response()->json(['success' => false, 'msg' => 'No items to convert.'], 422);
        }
        if ($items->firstWhere('clc_treatment_plan_id', '!=', null)) {
            return response()->json(['success' => false, 'msg' => 'This plan has already been converted.'], 422);
        }

        $planModel    = \Modules\ClinicCore\Entities\ClcPatientTreatmentPlan::class;
        $sessionModel = \Modules\ClinicCore\Entities\ClcTreatmentSession::class;
        if (! class_exists($planModel) || ! class_exists($sessionModel)) {
            return response()->json([
                'success' => false,
                'flag'    => 'clc_models_missing',
                'msg'     => 'ClinicCore treatment-plan models are unavailable; cannot convert.',
            ], 422);
        }

        try {
            $total = $items->count();
            $price = (float) $items->sum('estimated_cost');

            $plan = DB::transaction(function () use ($planModel, $sessionModel, $businessId, $patient, $planName, $total, $price, $items) {
                /** @var \Illuminate\Database\Eloquent\Model $plan */
                $plan = $planModel::create([
                    'business_id'    => $businessId,
                    'clc_patient_id' => $patient->id,
                    'package_id'     => null,
                    'name'           => $planName,
                    'total_sessions' => $total,
                    'price'          => $price,
                    'status'         => 'active',
                    'started_at'     => now()->toDateString(),
                    'notes'          => 'Converted from dental treatment plan.',
                    'created_by'     => auth()->id(),
                ]);

                $no = 1;
                foreach ($items as $it) {
                    $sessionModel::create([
                        'business_id' => $businessId,
                        'plan_id'     => $plan->id,
                        'session_no'  => $no++,
                        'status'      => 'scheduled',
                        'notes'       => trim(($it->tooth_number ? 'Tooth ' . $it->tooth_number . ' — ' : '') . $it->procedure_name),
                        'created_by'  => auth()->id(),
                    ]);
                }

                // Link every dental item to the new shared plan + mark scheduled.
                DentalTreatmentPlanItem::where('business_id', $businessId)
                    ->where('patient_id', $patient->id)
                    ->where('plan_name', $planName)
                    ->whereNull('clc_treatment_plan_id')
                    ->update(['clc_treatment_plan_id' => $plan->id, 'status' => 'scheduled']);

                return $plan;
            });

            return response()->json([
                'success'      => true,
                'msg'          => "Converted to ClinicCore treatment plan ({$total} sessions).",
                'clc_plan_id'  => $plan->id,
            ]);
        } catch (\Throwable $e) {
            Log::warning('DentalClinic plan conversion failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'flag'    => 'clc_shape_drift',
                'msg'     => 'Conversion failed — ClinicCore plan shape may have changed. No changes were made.',
            ], 422);
        }
    }

    /** Patient-friendly printable plan (plan + costs). */
    public function print($patientId, Request $request)
    {
        $patient = $this->guardPatient($patientId);

        $query = DentalTreatmentPlanItem::where('business_id', $this->biz())
            ->where('patient_id', $patient->id);
        if ($request->filled('plan_name')) {
            $query->where('plan_name', $request->plan_name);
        }
        $items = $query->orderBy('plan_name')->orderBy('sort_order')->orderBy('id')->get();

        $plans = $items->groupBy('plan_name');
        $grandTotal = (float) $items->sum('estimated_cost');

        return view('dentalClinic::specialty.treatment_plan_print', compact('patient', 'plans', 'grandTotal'));
    }

    private function validated(Request $request): array
    {
        $data = $request->validate([
            'plan_name'      => 'nullable|string|max:150',
            'tooth_number'   => 'nullable|integer|min:1|max:32',
            'cdt_code'       => 'nullable|string|max:20',
            'procedure_name' => 'required|string|max:191',
            'urgency'        => 'nullable|in:' . implode(',', DentalTreatmentPlanItem::URGENCIES),
            'estimated_cost' => 'nullable|numeric|min:0',
            'status'         => 'nullable|in:' . implode(',', DentalTreatmentPlanItem::STATUSES),
            'sort_order'     => 'nullable|integer|min:0',
        ]);

        $data['plan_name'] = $data['plan_name'] ?: 'Treatment plan';
        $data['urgency']   = $data['urgency'] ?? 'elective';

        return $data;
    }

    private function present(DentalTreatmentPlanItem $i): array
    {
        return [
            'id'                    => $i->id,
            'plan_name'             => $i->plan_name,
            'tooth_number'          => $i->tooth_number,
            'cdt_code'              => $i->cdt_code,
            'procedure_name'        => $i->procedure_name,
            'urgency'               => $i->urgency,
            'estimated_cost'        => $i->estimated_cost !== null ? (float) $i->estimated_cost : null,
            'status'                => $i->status,
            'sort_order'            => $i->sort_order,
            'clc_treatment_plan_id' => $i->clc_treatment_plan_id,
        ];
    }
}
