<?php

namespace Modules\DentalClinic\Http\Controllers;

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

/**
 * CRUD for the dental procedures log. Rendered inside ClinicCore's shared
 * appointment screen (record during a visit) and the patient screen (history
 * list) via the DentalSpecialtyDriver fragments. Every action is business-
 * scoped and gated on dental.procedures.manage.
 */
class DentalProcedureController extends Controller
{
    private function biz()
    {
        return request()->session()->get('user.business_id');
    }

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

    /** JSON list of a patient's procedures (newest first). */
    public function index($patientId)
    {
        $patient = $this->guardPatient($patientId);

        $rows = DentalProcedure::where('business_id', $this->biz())
            ->where('patient_id', $patient->id)
            ->orderByDesc('performed_at')->orderByDesc('id')->get();

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

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

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

        return response()->json(['success' => true, 'msg' => 'Procedure recorded.', 'data' => $this->present($proc)]);
    }

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

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

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

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

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

    private function validated(Request $request): array
    {
        $data = $request->validate([
            'appointment_id'       => 'nullable|integer',
            'tooth_number'         => 'nullable|integer|min:1|max:32',
            'surfaces'             => 'nullable|string|max:20',
            'cdt_code'             => 'nullable|string|max:20',
            'procedure_name'       => 'required|string|max:191',
            'anesthesia_type'      => 'nullable|string|max:100',
            'materials'            => 'nullable|array',
            'materials.*.name'     => 'nullable|string|max:150',
            'materials.*.lot'      => 'nullable|string|max:60',
            'materials.*.qty'      => 'nullable|string|max:30',
            'complications'        => 'nullable|string|max:1000',
            'post_op_instructions' => 'nullable|string|max:2000',
            'performed_by'         => 'nullable|integer',
            'performed_at'         => 'nullable|date',
        ]);

        // Drop empty material rows so we never store [{}].
        if (! empty($data['materials'])) {
            $data['materials'] = array_values(array_filter($data['materials'], function ($m) {
                return is_array($m) && (($m['name'] ?? '') !== '');
            }));
            if (empty($data['materials'])) {
                $data['materials'] = null;
            }
        }

        $data['performed_at'] = $data['performed_at'] ?? now();

        return $data;
    }

    private function present(DentalProcedure $p): array
    {
        return [
            'id'                   => $p->id,
            'appointment_id'       => $p->appointment_id,
            'tooth_number'         => $p->tooth_number,
            'surfaces'             => $p->surfaces,
            'cdt_code'             => $p->cdt_code,
            'procedure_name'       => $p->procedure_name,
            'anesthesia_type'      => $p->anesthesia_type,
            'materials'            => $p->materials ?: [],
            'complications'        => $p->complications,
            'post_op_instructions' => $p->post_op_instructions,
            'performed_by'         => $p->performed_by,
            'performed_at'         => optional($p->performed_at)->format('Y-m-d H:i'),
        ];
    }
}
