<?php

namespace Modules\DentalClinic\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcPatient;
use Modules\DentalClinic\Entities\DentalRecall;

/**
 * Dental recall CRUD + the clinic-wide "Due recalls" list. Recalls (cleaning,
 * perio maintenance, review…) are dental-owned because ClinicCore's reminder
 * settings are vaccine-specific. The daily dental:send-recalls command notifies
 * due rows via MedNotify. Gated on dental.treatment_plan.manage (recalls live in
 * the same treatment-planning surface).
 */
class DentalRecallController extends Controller
{
    private function biz()
    {
        return request()->session()->get('user.business_id');
    }

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

    private function guardPatient($patientId): ClcPatient
    {
        $this->guard();
        return ClcPatient::where('business_id', $this->biz())->findOrFail($patientId);
    }

    /** JSON list of a patient's recalls (soonest due first). */
    public function index($patientId)
    {
        $patient = $this->guardPatient($patientId);
        $rows = DentalRecall::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)
            ->orderByRaw("FIELD(status,'due','scheduled','done','cancelled')")
            ->orderBy('due_date')->get();

        return response()->json(['success' => true, 'data' => $rows->map(fn ($r) => $this->present($r))]);
    }

    /** Clinic-wide list of currently-due recalls (dashboard). */
    public function due()
    {
        $this->guard();
        $rows = DentalRecall::with('patient:id,patient_name')
            ->where('business_id', $this->biz())
            ->due()
            ->orderBy('due_date')->limit(500)->get();

        return response()->json(['success' => true, 'data' => $rows->map(function ($r) {
            return $this->present($r) + ['patient_name' => optional($r->patient)->patient_name];
        })]);
    }

    public function store(Request $request, $patientId)
    {
        $patient = $this->guardPatient($patientId);
        $data = $this->validated($request);

        $recall = DentalRecall::create($data + [
            'business_id' => $this->biz(),
            'patient_id'  => $patient->id,
        ]);

        return response()->json(['success' => true, 'msg' => 'Recall scheduled.', 'data' => $this->present($recall)]);
    }

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

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

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

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

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

    private function validated(Request $request): array
    {
        return $request->validate([
            'due_date'        => 'required|date',
            'interval_months' => 'nullable|integer|min:0|max:120',
            'reason'          => 'nullable|string|max:100',
            'status'          => 'nullable|in:' . implode(',', DentalRecall::STATUSES),
            'notes'           => 'nullable|string|max:1000',
        ]);
    }

    private function present(DentalRecall $r): array
    {
        return [
            'id'              => $r->id,
            'patient_id'      => $r->patient_id,
            'due_date'        => optional($r->due_date)->format('Y-m-d'),
            'interval_months' => $r->interval_months,
            'reason'          => $r->reason,
            'status'          => $r->status,
            'notes'           => $r->notes,
        ];
    }
}
