<?php

namespace Modules\ClinicCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcAppointmentWaitlist;
use Modules\ClinicCore\Entities\ClcDepartment;
use Modules\ClinicCore\Entities\ClcDoctor;
use Modules\ClinicCore\Entities\ClcPatient;

/**
 * SIFA P3-T7 — appointment waitlist (spec §7 "waitlist: automatic fill from
 * cancellations"). Staff add/list/cancel entries; "book now" opens the normal
 * appointment create prefilled and marks the entry booked.
 *
 * All business_id-scoped and gated by clinic.waitlist.manage.
 */
class ClcWaitlistController extends Controller
{
    private function guard(): void
    {
        if (!auth()->user()->can('clinic.waitlist.manage')) {
            abort(403, 'Unauthorized action.');
        }
    }

    public function index(Request $request)
    {
        $this->guard();
        $businessId = $request->session()->get('user.business_id');

        $doctors     = ClcDoctor::where('business_id', $businessId)->active()->orderBy('name')->get(['id', 'name']);
        $departments = ClcDepartment::where('business_id', $businessId)->where('status', 'active')->orderBy('name')->get(['id', 'name']);

        return view('clinicCore::waitlist.index', compact('doctors', 'departments'));
    }

    /** JSON list for the table, filterable by status / doctor. */
    public function list(Request $request)
    {
        $this->guard();
        $businessId = $request->session()->get('user.business_id');

        $query = ClcAppointmentWaitlist::with(['patient', 'doctor', 'department', 'contact'])
            ->forBusiness($businessId);

        if ($request->filled('status') && $request->status !== 'all') {
            $query->where('status', $request->status);
        } else {
            // Default view: hide terminal entries unless explicitly asked.
            $query->whereIn('status', ['waiting', 'offered']);
        }
        if ($request->filled('doctor_id')) {
            $query->where('doctor_id', $request->doctor_id);
        }

        $rows = $query->orderByDesc('created_at')->get();

        return response()->json($rows->map(fn ($w) => [
            'id'              => $w->id,
            'patient'         => optional($w->patient)->patient_name,
            'patient_id'      => $w->patient_id,
            'contact_id'      => $w->contact_id,
            'doctor'          => optional($w->doctor)->name,
            'doctor_id'       => $w->doctor_id,
            'department'      => optional($w->department)->name,
            'preferred_date'  => $w->preferred_date ? $w->preferred_date->toDateString() : null,
            'time_from'       => $w->preferred_time_from ? substr((string) $w->preferred_time_from, 0, 5) : null,
            'time_to'         => $w->preferred_time_to ? substr((string) $w->preferred_time_to, 0, 5) : null,
            'reason'          => $w->reason,
            'status'          => $w->status,
            'created_at'      => optional($w->created_at)->format('d M Y H:i'),
        ]));
    }

    public function store(Request $request)
    {
        $this->guard();
        $businessId = $request->session()->get('user.business_id');

        $data = $request->validate([
            'patient_id'          => 'required|integer',
            'doctor_id'           => 'nullable|integer',
            'department_id'       => 'nullable|integer',
            'preferred_date'      => 'nullable|date',
            'preferred_time_from' => 'nullable',
            'preferred_time_to'   => 'nullable',
            'reason'              => 'nullable|string|max:255',
        ]);

        $patient = ClcPatient::where('business_id', $businessId)->findOrFail($data['patient_id']);

        ClcAppointmentWaitlist::create([
            'business_id'         => $businessId,
            'patient_id'          => $patient->id,
            'contact_id'          => $patient->contact_id,
            'doctor_id'           => $data['doctor_id'] ?: null,
            'department_id'       => $data['department_id'] ?: null,
            'preferred_date'      => $data['preferred_date'] ?: null,
            'preferred_time_from' => $data['preferred_time_from'] ?: null,
            'preferred_time_to'   => $data['preferred_time_to'] ?: null,
            'reason'              => $data['reason'] ?? null,
            'status'              => 'waiting',
            'created_by'          => auth()->id(),
        ]);

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

    public function cancel(Request $request, $id)
    {
        $this->guard();
        $businessId = $request->session()->get('user.business_id');

        $entry = ClcAppointmentWaitlist::forBusiness($businessId)->findOrFail($id);
        $entry->update(['status' => 'cancelled']);

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

    /**
     * "Book now": mark the entry booked and redirect to the appointment create
     * form, prefilled from the waitlist entry (patient/contact/doctor/date).
     */
    public function bookNow(Request $request, $id)
    {
        $this->guard();
        $businessId = $request->session()->get('user.business_id');

        $entry = ClcAppointmentWaitlist::forBusiness($businessId)->findOrFail($id);
        $entry->update(['status' => 'booked']);

        $params = array_filter([
            'patient_id'  => $entry->patient_id,
            'contact_id'  => $entry->contact_id,
            'doctor_id'   => $entry->doctor_id,
            'date'        => $entry->preferred_date ? $entry->preferred_date->toDateString() : null,
            'from_waitlist' => $entry->id,
        ], fn ($v) => $v !== null && $v !== '');

        return redirect()->route('clinic.appointments.create', $params)
            ->with('status', ['success' => 1, 'msg' => __('clinicCore::lang.waitlist_booked_notice')]);
    }
}
