<?php

namespace Modules\ClinicCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcDoctor;
use Modules\ClinicCore\Entities\ClcDepartment;
use Modules\ClinicCore\Entities\ClcDoctorSchedule;
use App\User;
use Yajra\DataTables\Facades\DataTables;

class ClcDoctorController extends Controller
{
    use \Modules\ClinicCore\Http\Controllers\Traits\LogsClcActivity;

    public function index()
    {
        if (!auth()->user()->can('clinic.manage_doctors')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId  = request()->session()->get('user.business_id');
        $departments = ClcDepartment::with('location')->where('business_id', $businessId)->active()->orderBy('name')->get();
        $users       = User::where('business_id', $businessId)->get(['id', 'first_name', 'last_name', 'email', 'contact_no']);

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

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

        $businessId = request()->session()->get('user.business_id');
        $query = ClcDoctor::with(['departments'])
            ->withCount('appointments')
            ->where('business_id', $businessId);

        return DataTables::of($query)
            ->addColumn('doctor_info', function ($row) {
                $html  = '<strong>' . e($row->name) . '</strong>';
                if ($row->specialization) $html .= '<br><small class="text-muted">' . e($row->specialization) . '</small>';
                if ($row->email)  $html .= '<br><small><i class="fa fa-envelope"></i> ' . e($row->email) . '</small>';
                if ($row->phone)  $html .= '<br><small><i class="fa fa-phone"></i> ' . e($row->phone) . '</small>';
                return $html;
            })
            ->addColumn('departments_list', function ($row) {
                if ($row->departments->isEmpty()) return '<span class="text-muted">—</span>';
                return $row->departments->map(function ($d) use ($row) {
                    $isPrimary = $d->id == $row->department_id;
                    $badge = $isPrimary ? 'primary' : 'default';
                    return '<span class="label label-' . $badge . '" style="display:inline-block;margin:1px 2px;">' . e($d->name) . '</span>';
                })->implode(' ');
            })
            ->addColumn('appointments_col', function ($row) {
                $url = url('clinic/appointments') . '?filter_doctor_id=' . $row->id;
                $color = $row->appointments_count > 0 ? 'primary' : 'default';
                return '<a href="' . $url . '" class="btn btn-xs btn-' . $color . '" title="View appointments">'
                    . '<i class="fa fa-calendar"></i> ' . $row->appointments_count . '</a>';
            })
            ->addColumn('status_badge', function ($row) {
                $color = $row->status === 'active' ? 'success' : 'danger';
                return '<span class="label label-' . $color . '">' . ucfirst($row->status) . '</span>';
            })
            ->addColumn('product_badge', function ($row) {
                $hasFee     = (float) ($row->consultation_fee ?? 0) > 0;
                $hasProduct = !empty($row->product_id);
                if ($hasProduct && $hasFee) {
                    return '<span class="label label-success" title="Product linked + per-doctor fee override"><i class="fa fa-link"></i> Linked &middot; Fee override</span>';
                }
                if ($hasProduct) {
                    return '<span class="label label-success" title="Linked to ERP product (uses product price)"><i class="fa fa-link"></i> Linked</span>';
                }
                if ($hasFee) {
                    return '<span class="label label-warning" title="Has consultation_fee but no linked product — won\'t auto-bill in POS"><i class="fa fa-money"></i> Fee only</span>';
                }
                return '<span class="label label-default" title="No product link, no fee — visit won\'t appear in POS"><i class="fa fa-chain-broken"></i> Not linked</span>';
            })
            ->addColumn('action', function ($row) {
                $edit     = '<button class="btn btn-xs btn-primary btn-edit-doctor" data-id="' . $row->id . '" title="Edit"><i class="fa fa-edit"></i></button> ';
                $schedule = '<button class="btn btn-xs btn-info btn-schedule-doctor" data-id="' . $row->id . '" data-name="' . e($row->name) . '" title="Schedule"><i class="fas fa-clock"></i></button> ';
                $del      = '<button class="btn btn-xs btn-danger btn-delete-doctor" data-id="' . $row->id . '" title="Delete"><i class="fa fa-trash"></i></button>';
                return $edit . $schedule . $del;
            })
            ->rawColumns(['action', 'status_badge', 'doctor_info', 'departments_list', 'appointments_col', 'product_badge'])
            ->make(true);
    }

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

        $request->validate([
            'user_id' => 'required|integer|exists:users,id',
        ]);

        $businessId    = request()->session()->get('user.business_id');
        $user          = User::findOrFail($request->user_id);
        $deptIds       = array_filter((array) $request->input('dept_ids', []));
        $primaryDeptId = $deptIds[0] ?? null;

        $doctor = ClcDoctor::create([
            'business_id'      => $businessId,
            'user_id'          => $user->id,
            'name'             => trim($user->first_name . ' ' . $user->last_name),
            'email'            => $user->email,
            'phone'            => $user->contact_no,
            'department_id'    => $primaryDeptId,
            'specialization'   => $request->specialization,
            'about'            => $request->about,
            'consultation_fee' => $request->consultation_fee ?? 0,
            'status'           => $request->status ?? 'active',
            'color'            => $this->sanitizeHexColor($request->color),
            'product_id'       => $request->filled('product_id') ? (int) $request->product_id : null,
        ]);

        if (!empty($deptIds)) {
            $doctor->departments()->sync($deptIds);
        }
        $this->drmLog('create', $doctor);

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

    public function edit($id)
    {
        $businessId = request()->session()->get('user.business_id');
        $doctor = ClcDoctor::with('departments')->where('business_id', $businessId)->findOrFail($id);
        return response()->json(array_merge($doctor->toArray(), [
            'dept_ids' => $doctor->departments->pluck('id')->toArray(),
        ]));
    }

    public function update(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_doctors')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate([
            'user_id' => 'required|integer|exists:users,id',
        ]);

        $businessId    = request()->session()->get('user.business_id');
        $user          = User::findOrFail($request->user_id);
        $deptIds       = array_filter((array) $request->input('dept_ids', []));
        $primaryDeptId = $deptIds[0] ?? null;

        $doctor = ClcDoctor::where('business_id', $businessId)->findOrFail($id);
        $doctor->update([
            'user_id'          => $user->id,
            'name'             => trim($user->first_name . ' ' . $user->last_name),
            'email'            => $user->email,
            'phone'            => $user->contact_no,
            'department_id'    => $primaryDeptId,
            'specialization'   => $request->specialization,
            'about'            => $request->about,
            'consultation_fee' => $request->consultation_fee ?? 0,
            'status'           => $request->status ?? 'active',
            'color'            => $this->sanitizeHexColor($request->color),
            'product_id'       => $request->filled('product_id') ? (int) $request->product_id : null,
        ]);

        if (!empty($deptIds)) {
            $doctor->departments()->sync($deptIds);
        }
        $this->drmLog('update', $doctor, ['fields' => array_keys($doctor->getChanges())]);

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

    public function destroy($id)
    {
        if (!auth()->user()->can('clinic.manage_doctors')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $doctor = ClcDoctor::where('business_id', $businessId)->findOrFail($id);
        $this->drmLog('delete', $doctor, ['before' => $this->_drmFilterAttrs($doctor->getAttributes())]);
        $doctor->delete();

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

    public function search(Request $request)
    {
        $businessId = request()->session()->get('user.business_id');
        $doctors = ClcDoctor::where('business_id', $businessId)
            ->active()
            ->where('name', 'LIKE', '%' . $request->q . '%')
            ->get(['id', 'name', 'specialization']);

        return response()->json($doctors);
    }

    /** AJAX: schedule summary for a doctor (used by create appointment sidebar) */
    public function scheduleSummary(Request $request)
    {
        $doctorId = $request->doctor_id;
        if (!$doctorId) return response()->json([]);

        $days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
        $schedules = ClcDoctorSchedule::with('department')
            ->where('doctor_id', $doctorId)
            ->active()
            ->orderBy('day_of_week')
            ->get();

        return response()->json($schedules->map(fn($s) => [
            'day'        => $days[$s->day_of_week] ?? $s->day_of_week,
            'start'      => substr($s->start_time, 0, 5),
            'end'        => substr($s->end_time, 0, 5),
            'slot_mins'  => $s->slot_duration_minutes,
            'department' => optional($s->department)->name,
        ]));
    }

    /** Return schedules for a doctor (for management UI) */
    public function schedules($id)
    {
        $businessId = request()->session()->get('user.business_id');
        $doctor = ClcDoctor::where('business_id', $businessId)->findOrFail($id);
        $schedules = ClcDoctorSchedule::with('department')
            ->where('doctor_id', $id)
            ->orderBy('day_of_week')
            ->get();

        return response()->json($schedules);
    }

    public function storeSchedule(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_doctors')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate([
            'day_of_week'           => 'required|integer|between:0,6',
            'start_time'            => 'required',
            'end_time'              => 'required',
            'slot_duration_minutes' => 'required|integer|min:5',
        ]);

        $businessId = request()->session()->get('user.business_id');
        ClcDoctor::where('business_id', $businessId)->findOrFail($id);

        $attrs = [
            'doctor_id'             => $id,
            'day_of_week'           => $request->day_of_week,
            'start_time'            => $request->start_time,
            'end_time'              => $request->end_time,
            'slot_duration_minutes' => $request->slot_duration_minutes,
            'department_id'         => $request->filled('department_id') ? $request->department_id : null,
            'status'                => 'active',
        ];

        ClcDoctorSchedule::create(array_merge($attrs, $this->schedulePatternAttrs($request)));

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

    public function updateSchedule(Request $request, $sid)
    {
        if (!auth()->user()->can('clinic.manage_doctors')) {
            abort(403, 'Unauthorized action.');
        }

        $schedule = ClcDoctorSchedule::findOrFail($sid);
        $schedule->update(array_merge([
            'day_of_week'           => $request->day_of_week,
            'start_time'            => $request->start_time,
            'end_time'              => $request->end_time,
            'slot_duration_minutes' => $request->slot_duration_minutes,
            'department_id'         => $request->filled('department_id') ? $request->department_id : null,
            'status'                => $request->input('status', $schedule->status),
        ], $this->schedulePatternAttrs($request)));

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

    /**
     * SIFA P3-T7 — additive schedule-pattern attributes (effective range,
     * break, capacity / overbooking, branch). Each guarded so it's a no-op when
     * the column isn't present yet, and only written when the field is supplied.
     */
    private function schedulePatternAttrs(Request $request): array
    {
        $tbl  = 'clc_doctor_schedules';
        $out  = [];
        $has  = fn ($c) => \Illuminate\Support\Facades\Schema::hasColumn($tbl, $c);

        if ($has('effective_from')) $out['effective_from'] = $request->filled('effective_from') ? $request->effective_from : null;
        if ($has('effective_to'))   $out['effective_to']   = $request->filled('effective_to') ? $request->effective_to : null;
        if ($has('break_from'))     $out['break_from']      = $request->filled('break_from') ? $request->break_from : null;
        if ($has('break_to'))       $out['break_to']        = $request->filled('break_to') ? $request->break_to : null;
        if ($has('max_per_slot'))   $out['max_per_slot']    = max(1, (int) $request->input('max_per_slot', 1));
        if ($has('overbooking_allowed')) $out['overbooking_allowed'] = $request->boolean('overbooking_allowed');
        if ($has('overbooking_max'))     $out['overbooking_max']     = max(0, (int) $request->input('overbooking_max', 0));
        if ($has('location_id'))    $out['location_id']     = $request->filled('location_id') ? (int) $request->location_id : null;

        return $out;
    }

    public function destroySchedule($sid)
    {
        if (!auth()->user()->can('clinic.manage_doctors')) {
            abort(403, 'Unauthorized action.');
        }

        ClcDoctorSchedule::findOrFail($sid)->delete();

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

    /** Return a #RRGGBB hex string or null. Rejects malformed input silently. */
    private function sanitizeHexColor($value): ?string
    {
        $value = trim((string) $value);
        if ($value === '') return null;
        if ($value[0] !== '#') $value = '#' . $value;
        return preg_match('/^#[0-9A-Fa-f]{6}$/', $value) ? strtoupper($value) : null;
    }
}
