<?php

namespace Modules\MedWard\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\MedWard\Entities\MedwardBed;
use Modules\MedWard\Entities\MedwardWard;
use Yajra\DataTables\Facades\DataTables;

/**
 * Ward + bed CRUD (SIFA P6-T1). Business-scoped; guarded by medward.wards.manage.
 * The dept picker links (never duplicates) MedOrganization clc_departments.
 */
class WardController extends MedWardBaseController
{
    // ── Wards ────────────────────────────────────────────────────────────

    public function index(Request $request)
    {
        $this->guard('medward.wards.manage');

        if ($request->ajax()) {
            $query = MedwardWard::forBusiness($this->businessId())
                ->select(['id', 'name', 'code', 'ward_type', 'floor', 'total_beds', 'is_active']);

            return DataTables::of($query)
                ->addColumn('occupied', fn ($r) => MedwardBed::where('ward_id', $r->id)->where('status', 'occupied')->count())
                ->editColumn('ward_type', fn ($r) => __('medward::lang.ward_type_' . $r->ward_type))
                ->editColumn('is_active', fn ($r) => $r->is_active
                    ? '<span class="label label-success">' . __('medward::lang.active') . '</span>'
                    : '<span class="label label-default">' . __('medward::lang.inactive') . '</span>')
                ->addColumn('action', function ($r) {
                    return '<a class="btn btn-xs btn-default" href="' . route('medward.wards.beds', $r->id) . '"><i class="fa fa-bed"></i> ' . __('medward::lang.beds') . '</a> '
                        . '<button class="btn btn-xs btn-default medward-modal-btn" data-href="' . route('medward.wards.edit', $r->id) . '"><i class="fa fa-edit"></i></button> '
                        . '<button class="btn btn-xs btn-danger medward-delete-btn" data-href="' . route('medward.wards.destroy', $r->id) . '"><i class="fa fa-trash"></i></button>';
                })
                ->rawColumns(['is_active', 'action'])
                ->make(true);
        }

        return view('medward::wards.index');
    }

    public function create()
    {
        $this->guard('medward.wards.manage');

        return view('medward::wards.form', [
            'ward'        => new MedwardWard(),
            'wardTypes'   => MedwardWard::WARD_TYPES,
            'departments' => $this->departments(),
        ]);
    }

    public function edit($id)
    {
        $this->guard('medward.wards.manage');

        return view('medward::wards.form', [
            'ward'        => MedwardWard::forBusiness($this->businessId())->findOrFail($id),
            'wardTypes'   => MedwardWard::WARD_TYPES,
            'departments' => $this->departments(),
        ]);
    }

    public function store(Request $request)
    {
        $this->guard('medward.wards.manage');
        $data = $this->validatedWard($request);

        try {
            $data['business_id'] = $this->businessId();
            MedwardWard::create($data);

            return $this->ok(__('medward::lang.ward_saved'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail();
        }
    }

    public function update(Request $request, $id)
    {
        $this->guard('medward.wards.manage');
        $ward = MedwardWard::forBusiness($this->businessId())->findOrFail($id);

        try {
            $ward->update($this->validatedWard($request));

            return $this->ok(__('medward::lang.ward_saved'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail();
        }
    }

    public function destroy($id)
    {
        $this->guard('medward.wards.manage');

        try {
            $ward = MedwardWard::forBusiness($this->businessId())->findOrFail($id);
            if ($ward->beds()->where('status', 'occupied')->exists()) {
                return $this->fail(__('medward::lang.ward_in_use'));
            }
            $ward->beds()->delete();
            $ward->delete();

            return $this->ok(__('medward::lang.ward_deleted'));
        } catch (\Exception $e) {
            return $this->fail();
        }
    }

    // ── Beds (per ward) ──────────────────────────────────────────────────

    public function beds(Request $request, $wardId)
    {
        $this->guard('medward.wards.manage');
        $ward = MedwardWard::forBusiness($this->businessId())->findOrFail($wardId);

        if ($request->ajax()) {
            $query = MedwardBed::forBusiness($this->businessId())->where('ward_id', $ward->id)
                ->select(['id', 'bed_number', 'bed_type', 'status', 'cleaning_status', 'ward_id']);

            return DataTables::of($query)
                ->editColumn('bed_type', fn ($r) => __('medward::lang.bed_type_' . $r->bed_type))
                ->editColumn('status', fn ($r) => '<span class="label label-' . $r->statusColor() . '">' . __('medward::lang.bed_status_' . $r->status) . '</span>')
                ->editColumn('cleaning_status', fn ($r) => __('medward::lang.clean_' . $r->cleaning_status))
                ->addColumn('action', function ($r) {
                    return '<button class="btn btn-xs btn-default medward-modal-btn" data-href="' . route('medward.beds.edit', $r->id) . '"><i class="fa fa-edit"></i></button> '
                        . '<button class="btn btn-xs btn-danger medward-delete-btn" data-href="' . route('medward.beds.destroy', $r->id) . '"><i class="fa fa-trash"></i></button>';
                })
                ->rawColumns(['status', 'action'])
                ->make(true);
        }

        return view('medward::beds.index', ['ward' => $ward]);
    }

    public function createBed($wardId)
    {
        $this->guard('medward.wards.manage');
        $ward = MedwardWard::forBusiness($this->businessId())->findOrFail($wardId);

        return view('medward::beds.form', [
            'ward'     => $ward,
            'bed'      => new MedwardBed(['ward_id' => $ward->id]),
            'bedTypes' => MedwardBed::BED_TYPES,
            'statuses' => MedwardBed::STATUSES,
        ]);
    }

    public function editBed($id)
    {
        $this->guard('medward.wards.manage');
        $bed = MedwardBed::forBusiness($this->businessId())->findOrFail($id);
        $ward = MedwardWard::forBusiness($this->businessId())->findOrFail($bed->ward_id);

        return view('medward::beds.form', [
            'ward'     => $ward,
            'bed'      => $bed,
            'bedTypes' => MedwardBed::BED_TYPES,
            'statuses' => MedwardBed::STATUSES,
        ]);
    }

    public function storeBed(Request $request)
    {
        $this->guard('medward.wards.manage');
        $data = $this->validatedBed($request);
        $ward = MedwardWard::forBusiness($this->businessId())->findOrFail($data['ward_id']);

        try {
            $data['business_id'] = $this->businessId();
            MedwardBed::create($data);
            $this->syncTotalBeds($ward);

            return $this->ok(__('medward::lang.bed_saved'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail(__('medward::lang.bed_number_taken'));
        }
    }

    public function updateBed(Request $request, $id)
    {
        $this->guard('medward.wards.manage');
        $bed = MedwardBed::forBusiness($this->businessId())->findOrFail($id);
        $data = $this->validatedBed($request);

        try {
            // Never let a hand-edit orphan an occupant: block status changes on an occupied bed.
            if ($bed->status === 'occupied' && $data['status'] !== 'occupied') {
                return $this->fail(__('medward::lang.bed_occupied_locked'));
            }
            $bed->update($data);

            return $this->ok(__('medward::lang.bed_saved'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail(__('medward::lang.bed_number_taken'));
        }
    }

    public function destroyBed($id)
    {
        $this->guard('medward.wards.manage');

        try {
            $bed = MedwardBed::forBusiness($this->businessId())->findOrFail($id);
            if ($bed->status === 'occupied') {
                return $this->fail(__('medward::lang.bed_occupied_locked'));
            }
            $ward = MedwardWard::forBusiness($this->businessId())->find($bed->ward_id);
            $bed->delete();
            if ($ward) {
                $this->syncTotalBeds($ward);
            }

            return $this->ok(__('medward::lang.bed_deleted'));
        } catch (\Exception $e) {
            return $this->fail();
        }
    }

    // ── helpers ──────────────────────────────────────────────────────────

    private function validatedWard(Request $request): array
    {
        $data = $this->validate($request, [
            'name'      => 'required|string|max:100',
            'code'      => 'nullable|string|max:30',
            'ward_type' => 'required|in:' . implode(',', MedwardWard::WARD_TYPES),
            'floor'     => 'nullable|string|max:30',
            'dept_id'   => 'nullable|integer',
            'business_location_id' => 'nullable|integer',
            'in_charge_user_id'    => 'nullable|integer',
            'notes'     => 'nullable|string',
            'is_active' => 'nullable|boolean',
        ]);

        return [
            'name'      => $data['name'],
            'code'      => $data['code'] ?? null,
            'ward_type' => $data['ward_type'],
            'floor'     => $data['floor'] ?? null,
            'dept_id'   => ! empty($data['dept_id']) ? (int) $data['dept_id'] : null,
            'business_location_id' => ! empty($data['business_location_id']) ? (int) $data['business_location_id'] : null,
            'in_charge_user_id'    => ! empty($data['in_charge_user_id']) ? (int) $data['in_charge_user_id'] : null,
            'notes'     => $data['notes'] ?? null,
            'is_active' => $request->boolean('is_active', true),
        ];
    }

    private function validatedBed(Request $request): array
    {
        $data = $this->validate($request, [
            'ward_id'         => 'required|integer',
            'bed_number'      => 'required|string|max:30',
            'bed_type'        => 'required|in:' . implode(',', MedwardBed::BED_TYPES),
            'status'          => 'required|in:' . implode(',', MedwardBed::STATUSES),
            'cleaning_status' => 'nullable|in:' . implode(',', MedwardBed::CLEANING_STATUSES),
            'notes'           => 'nullable|string',
        ]);

        return [
            'ward_id'         => (int) $data['ward_id'],
            'bed_number'      => $data['bed_number'],
            'bed_type'        => $data['bed_type'],
            'status'          => $data['status'],
            'cleaning_status' => $data['cleaning_status'] ?? 'clean',
            'notes'           => $data['notes'] ?? null,
        ];
    }

    /** Keep ward.total_beds in step with the bed count. */
    private function syncTotalBeds(MedwardWard $ward): void
    {
        $ward->update(['total_beds' => MedwardBed::where('ward_id', $ward->id)->count()]);
    }

    /** MedOrganization / ClinicCore departments for this business (link-only picker). */
    private function departments(): array
    {
        try {
            if (! Schema::hasTable('clc_departments')) {
                return [];
            }

            return DB::table('clc_departments')
                ->where('business_id', $this->businessId())
                ->orderBy('name')
                ->pluck('name', 'id')
                ->toArray();
        } catch (\Throwable $e) {
            return [];
        }
    }
}
