<?php

namespace Modules\VetClinic\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\VetClinic\Entities\VcAppointment;
use Modules\VetClinic\Entities\VcDoctor;
use Modules\VetClinic\Entities\VcDoctorChangeRequest;
use Modules\VetClinic\Entities\VcPetOwnerDetail;
use Modules\VetClinic\Entities\VcPreferredDoctorHistory;
use Yajra\DataTables\Facades\DataTables;

class VcDoctorChangeRequestController extends Controller
{
    use \Modules\VetClinic\Http\Controllers\Traits\LogsVcActivity;

    /** Submit a request to change an appointment's doctor. */
    public function store(Request $request, $appointmentId)
    {
        if (!auth()->user()->can('vet_clinic.manage_appointments')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate([
            'requested_doctor_id' => 'required|integer',
            'reason'              => 'required|string|max:1000',
            'scope'               => 'required|in:this_appointment,set_preferred',
        ]);

        $businessId  = $request->session()->get('user.business_id');
        $appointment = VcAppointment::where('business_id', $businessId)->findOrFail($appointmentId);

        $newDoctor = VcDoctor::where('business_id', $businessId)->find($request->requested_doctor_id);
        if (!$newDoctor) {
            return response()->json(['success' => false, 'msg' => 'Selected doctor not found.'], 422);
        }
        if ((int) $appointment->doctor_id === (int) $request->requested_doctor_id) {
            return response()->json(['success' => false, 'msg' => 'That doctor is already assigned to this appointment.'], 422);
        }

        $existing = VcDoctorChangeRequest::where('appointment_id', $appointment->id)
            ->where('status', 'pending')
            ->exists();
        if ($existing) {
            return response()->json(['success' => false, 'msg' => 'There is already a pending doctor-change request for this appointment.'], 422);
        }

        $changeRequest = VcDoctorChangeRequest::create([
            'business_id'         => $businessId,
            'appointment_id'      => $appointment->id,
            'pet_id'              => $appointment->pet_id,
            'contact_id'          => $appointment->contact_id,
            'requested_by'        => auth()->id(),
            'current_doctor_id'   => $appointment->doctor_id,
            'requested_doctor_id' => $request->requested_doctor_id,
            'scope'               => $request->scope,
            'reason'              => $request->reason,
            'status'              => 'pending',
        ]);

        $this->vcLog('create', $changeRequest, ['note' => 'Doctor-change request for appointment #' . $appointment->id]);

        return response()->json(['success' => true, 'msg' => 'Doctor-change request submitted for approval.']);
    }

    /** Approver dashboard. */
    public function index()
    {
        if (!auth()->user()->can('vet_clinic.approve_doctor_change')) {
            abort(403, 'Unauthorized action.');
        }
        return view('vetClinic::doctor-change-requests.index');
    }

    public function list(Request $request)
    {
        if (!auth()->user()->can('vet_clinic.approve_doctor_change')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = $request->session()->get('user.business_id');
        $query = VcDoctorChangeRequest::with([
                'appointment.pet', 'currentDoctor', 'requestedDoctor', 'requester', 'reviewer',
            ])
            ->forBusiness($businessId)
            ->latest();

        if ($request->filled('status') && in_array($request->status, ['pending', 'approved', 'rejected'])) {
            $query->where('status', $request->status);
        }

        return DataTables::of($query)
            ->addColumn('appointment_ref', function ($row) {
                $apt = $row->appointment;
                if (!$apt) return '—';
                $ref = $apt->ref_no ?: ('#' . $apt->id);
                return '<a href="' . route('vc.appointments.show', $apt->id) . '" target="_blank">' . e($ref) . '</a>';
            })
            ->addColumn('pet_name', fn($row) => e(optional(optional($row->appointment)->pet)->petname ?? '—'))
            ->addColumn('doctor_change', function ($row) {
                $from = e(optional($row->currentDoctor)->name ?? '— none —');
                $to   = e(optional($row->requestedDoctor)->name ?? '?');
                return '<span class="text-muted">' . $from . '</span> '
                     . '<i class="fa fa-arrow-right" style="font-size:10px;"></i> '
                     . '<strong>' . $to . '</strong>';
            })
            ->addColumn('scope_badge', function ($row) {
                return $row->scope === 'set_preferred'
                    ? '<span class="label label-primary">Set as preferred</span>'
                    : '<span class="label label-default">This appointment only</span>';
            })
            ->addColumn('requester_name', fn($row) => e(optional($row->requester)->first_name ?? ('User #' . $row->requested_by)))
            ->editColumn('reason', fn($row) => '<span title="' . e($row->reason) . '">' . e(\Illuminate\Support\Str::limit($row->reason, 60)) . '</span>')
            ->addColumn('requested_at', fn($row) => optional($row->created_at)->format('d M Y H:i'))
            ->addColumn('status_badge', function ($row) {
                $map = ['pending' => 'warning', 'approved' => 'success', 'rejected' => 'danger'];
                return '<span class="label label-' . ($map[$row->status] ?? 'default') . '">' . ucfirst($row->status) . '</span>';
            })
            ->addColumn('reviewed_info', function ($row) {
                if ($row->status === 'pending') return '<span class="text-muted">—</span>';
                $by = optional($row->reviewer)->first_name ?? '—';
                $at = optional($row->reviewed_at)->format('d M Y H:i') ?? '';
                $notes = $row->review_notes ? '<br><small class="text-muted">' . e($row->review_notes) . '</small>' : '';
                return e($by) . '<br><small class="text-muted">' . $at . '</small>' . $notes;
            })
            ->addColumn('action', function ($row) {
                if ($row->status !== 'pending') {
                    return '<span class="text-muted">—</span>';
                }
                return '<button class="btn btn-xs btn-success btn-approve-dcr" data-id="' . $row->id . '"><i class="fa fa-check"></i> Approve</button> '
                     . '<button class="btn btn-xs btn-danger btn-reject-dcr" data-id="' . $row->id . '"><i class="fa fa-times"></i> Reject</button>';
            })
            ->rawColumns(['appointment_ref', 'doctor_change', 'scope_badge', 'reason', 'status_badge', 'reviewed_info', 'action'])
            ->make(true);
    }

    public function approve(Request $request, $id)
    {
        return $this->review($request, $id, 'approved');
    }

    public function reject(Request $request, $id)
    {
        return $this->review($request, $id, 'rejected');
    }

    private function review(Request $request, $id, string $decision)
    {
        if (!auth()->user()->can('vet_clinic.approve_doctor_change')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId    = $request->session()->get('user.business_id');
        $changeRequest = VcDoctorChangeRequest::forBusiness($businessId)->findOrFail($id);

        if ($changeRequest->status !== 'pending') {
            return response()->json(['success' => false, 'msg' => 'This request has already been reviewed.'], 422);
        }

        $before = ['status' => $changeRequest->status];
        $changeRequest->update([
            'status'       => $decision,
            'reviewed_by'  => auth()->id(),
            'reviewed_at'  => now(),
            'review_notes' => $request->input('review_notes'),
        ]);

        $msg = 'Request rejected.';

        if ($decision === 'approved') {
            $appointment = VcAppointment::find($changeRequest->appointment_id);
            if ($appointment) {
                $oldDoctorId = $appointment->doctor_id;
                $appointment->update(['doctor_id' => $changeRequest->requested_doctor_id]);
                $this->vcLog('update', $appointment, [
                    'before' => ['doctor_id' => $oldDoctorId],
                    'after'  => ['doctor_id' => $changeRequest->requested_doctor_id],
                    'fields' => ['doctor_id'],
                    'note'   => 'Doctor changed via approved request #' . $changeRequest->id,
                ]);
            }

            $changeRequest->update(['consumed_at' => now()]);
            $msg = 'Request approved — the appointment doctor has been updated.';

            // Optionally promote to the owner's general preferred doctor
            if ($changeRequest->scope === 'set_preferred' && $changeRequest->contact_id) {
                $ownerDetail = VcPetOwnerDetail::firstOrCreate(
                    ['contact_id' => $changeRequest->contact_id],
                    ['business_id' => $businessId]
                );
                $oldPreferred = $ownerDetail->preferred_doctor_id;
                $ownerDetail->update(['preferred_doctor_id' => $changeRequest->requested_doctor_id]);

                VcPreferredDoctorHistory::record([
                    'business_id'    => $businessId,
                    'contact_id'     => $changeRequest->contact_id,
                    'pet_id'         => null,
                    'old_doctor_id'  => $oldPreferred,
                    'new_doctor_id'  => $changeRequest->requested_doctor_id,
                    'source'         => 'doctor_change_request',
                    'appointment_id' => $changeRequest->appointment_id,
                    'reason'         => $changeRequest->reason,
                ]);
                $msg = 'Request approved — appointment doctor updated and set as the owner\'s preferred doctor.';
            }
        }

        $this->vcLog('update', $changeRequest, [
            'before' => $before,
            'after'  => ['status' => $decision, 'review_notes' => $request->input('review_notes')],
            'fields' => ['status', 'reviewed_by', 'reviewed_at', 'review_notes'],
        ]);

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