<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\CareUnit;
use App\Models\Department;
use App\Models\Visit;
use App\Services\Care\AuditLogger;
use App\Services\Care\CarePermissions;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class CareUnitController extends Controller
{
    use ScopesToAccount;

    public function index(Request $request): View
    {
        $this->authorizeAbility($request, 'admin.departments.view');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);
        $member = $this->member($request);
        $permissions = app(CarePermissions::class);

        $units = CareUnit::owned($owner)
            ->where('organization_id', $organization->id)
            ->with(['department.branch'])
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get();

        $heroStats = [
            'total' => $units->count(),
            'inpatient' => $units->where('kind', 'inpatient')->count(),
            'float' => $units->where('kind', 'float_pool')->count(),
            'active' => $units->where('is_active', true)->count(),
        ];

        return view('care.admin.care-units.index', [
            'units' => $units,
            'organization' => $organization,
            'kinds' => config('care.care_unit_kinds'),
            'heroStats' => $heroStats,
            'canManage' => $permissions->can($member, 'admin.departments.manage'),
        ]);
    }

    public function create(Request $request): View
    {
        $this->authorizeAbility($request, 'admin.departments.manage');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $departments = Department::owned($owner)
            ->whereHas('branch', fn ($q) => $q->where('organization_id', $organization->id))
            ->with('branch')
            ->where('is_active', true)
            ->orderBy('name')
            ->get();

        return view('care.admin.care-units.create', [
            'organization' => $organization,
            'departments' => $departments,
            'kinds' => config('care.care_unit_kinds'),
            'selectedDepartmentId' => $request->integer('department_id') ?: null,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $this->authorizeAbility($request, 'admin.departments.manage');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $validated = $request->validate([
            'department_id' => ['required', 'integer', 'exists:care_departments,id'],
            'name' => ['required', 'string', 'max:255'],
            'code' => ['nullable', 'string', 'max:50'],
            'kind' => ['required', 'string', Rule::in(array_keys(config('care.care_unit_kinds')))],
        ]);

        $department = Department::owned($owner)->with('branch')->findOrFail($validated['department_id']);
        abort_unless((int) $department->branch?->organization_id === (int) $organization->id, 404);

        $unit = CareUnit::create([
            'owner_ref' => $owner,
            'organization_id' => $organization->id,
            'department_id' => $department->id,
            'name' => $validated['name'],
            'code' => $validated['code'] ?? null,
            'kind' => $validated['kind'],
            'is_active' => true,
        ]);

        AuditLogger::record($owner, 'care_unit.created', $organization->id, $owner, CareUnit::class, $unit->id);

        return redirect()->route('care.care-units.show', $unit)->with('success', 'Care unit created.');
    }

    public function show(Request $request, CareUnit $careUnit): View
    {
        $this->authorizeCareUnitView($request);
        $this->authorizeOwner($request, $careUnit);
        $organization = $this->organization($request);
        abort_unless((int) $careUnit->organization_id === (int) $organization->id, 404);

        $careUnit->load(['department.branch', 'beds']);

        $placedVisits = Visit::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->where('care_unit_id', $careUnit->id)
            ->whereIn('status', [Visit::STATUS_OPEN, Visit::STATUS_IN_PROGRESS])
            ->with(['patient', 'bed'])
            ->orderBy('placed_at')
            ->get();

        $placeableVisits = Visit::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->where('branch_id', $careUnit->department?->branch_id)
            ->whereIn('status', [Visit::STATUS_OPEN, Visit::STATUS_IN_PROGRESS])
            ->where(function ($q) use ($careUnit) {
                $q->whereNull('care_unit_id')
                    ->orWhere('care_unit_id', '!=', $careUnit->id);
            })
            ->with(['patient', 'careUnit'])
            ->orderByDesc('checked_in_at')
            ->limit(50)
            ->get();

        $availableBeds = $careUnit->beds
            ->where('is_active', true)
            ->whereIn('status', ['available', 'reserved'])
            ->values();

        $canPlace = app(CarePermissions::class)->can($this->member($request), 'inpatient.placement.manage');

        return view('care.admin.care-units.show', [
            'unit' => $careUnit,
            'kinds' => config('care.care_unit_kinds'),
            'bedStatuses' => config('care.bed_statuses'),
            'placedVisits' => $placedVisits,
            'placeableVisits' => $placeableVisits,
            'availableBeds' => $availableBeds,
            'canPlace' => $canPlace,
        ]);
    }

    protected function authorizeCareUnitView(Request $request): void
    {
        $permissions = app(CarePermissions::class);
        $member = $this->member($request);
        abort_unless(
            $permissions->can($member, 'admin.departments.view')
            || $permissions->can($member, 'inpatient.placement.view')
            || $permissions->can($member, 'nursing.station.view'),
            403,
        );
    }

    public function edit(Request $request, CareUnit $careUnit): View
    {
        $this->authorizeAbility($request, 'admin.departments.manage');
        $this->authorizeOwner($request, $careUnit);
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $departments = Department::owned($owner)
            ->whereHas('branch', fn ($q) => $q->where('organization_id', $organization->id))
            ->with('branch')
            ->orderBy('name')
            ->get();

        return view('care.admin.care-units.edit', [
            'unit' => $careUnit,
            'departments' => $departments,
            'kinds' => config('care.care_unit_kinds'),
        ]);
    }

    public function update(Request $request, CareUnit $careUnit): RedirectResponse
    {
        $this->authorizeAbility($request, 'admin.departments.manage');
        $this->authorizeOwner($request, $careUnit);
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);

        $validated = $request->validate([
            'department_id' => ['required', 'integer', 'exists:care_departments,id'],
            'name' => ['required', 'string', 'max:255'],
            'code' => ['nullable', 'string', 'max:50'],
            'kind' => ['required', 'string', Rule::in(array_keys(config('care.care_unit_kinds')))],
            'is_active' => ['boolean'],
        ]);

        $department = Department::owned($owner)->with('branch')->findOrFail($validated['department_id']);
        abort_unless((int) $department->branch?->organization_id === (int) $organization->id, 404);

        $careUnit->update([
            'department_id' => $department->id,
            'name' => $validated['name'],
            'code' => $validated['code'] ?? null,
            'kind' => $validated['kind'],
            'is_active' => $request->boolean('is_active', true),
        ]);

        AuditLogger::record($owner, 'care_unit.updated', $organization->id, $owner, CareUnit::class, $careUnit->id);

        return redirect()->route('care.care-units.show', $careUnit)->with('success', 'Care unit updated.');
    }

    public function destroy(Request $request, CareUnit $careUnit): RedirectResponse
    {
        $this->authorizeAbility($request, 'admin.departments.manage');
        $this->authorizeOwner($request, $careUnit);

        $careUnit->delete();

        AuditLogger::record(
            $this->ownerRef($request),
            'care_unit.deleted',
            $careUnit->organization_id,
            $this->ownerRef($request),
            CareUnit::class,
            $careUnit->id,
        );

        return redirect()->route('care.care-units.index')->with('success', 'Care unit removed.');
    }
}
