<?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\Member;
use App\Models\RosterEntry;
use App\Models\Shift;
use App\Services\Care\CarePermissions;
use App\Services\Care\RosterService;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class RosterController extends Controller
{
    use ScopesToAccount;

    public function show(Request $request, CareUnit $careUnit, RosterService $roster): View
    {
        $this->authorizeAbility($request, 'nursing.roster.view');
        $this->authorizeOwner($request, $careUnit);
        abort_unless((int) $careUnit->organization_id === (int) $this->organization($request)->id, 404);

        $weekStart = $request->filled('week')
            ? Carbon::parse($request->input('week'))->startOfWeek(Carbon::MONDAY)
            : now()->startOfWeek(Carbon::MONDAY);

        $grid = $roster->unitWeekGrid($careUnit, $this->ownerRef($request), $weekStart);
        $canManage = app(CarePermissions::class)->can($this->member($request), 'nursing.roster.manage');

        return view('care.nursing.roster', [
            'unit' => $careUnit->load('department.branch'),
            'weekStart' => $grid['week_start'],
            'days' => $grid['days'],
            'shifts' => $grid['shifts'],
            'cells' => $grid['cells'],
            'members' => $grid['members'],
            'memberLabels' => $grid['member_labels'],
            'canManage' => $canManage,
            'statuses' => config('care.roster_entry_statuses'),
            'prevWeek' => $grid['week_start']->copy()->subWeek()->toDateString(),
            'nextWeek' => $grid['week_start']->copy()->addWeek()->toDateString(),
        ]);
    }

    public function store(Request $request, CareUnit $careUnit, RosterService $roster): RedirectResponse
    {
        $this->authorizeAbility($request, 'nursing.roster.manage');
        $this->authorizeOwner($request, $careUnit);
        $organization = $this->organization($request);
        abort_unless((int) $careUnit->organization_id === (int) $organization->id, 404);

        $validated = $request->validate([
            'shift_id' => ['required', 'integer', 'exists:care_shifts,id'],
            'member_id' => ['required', 'integer', 'exists:care_members,id'],
            'duty_date' => ['required', 'date'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $shift = Shift::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->findOrFail($validated['shift_id']);
        $member = Member::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->findOrFail($validated['member_id']);

        $roster->assign(
            $careUnit,
            $shift,
            $member,
            $validated['duty_date'],
            $this->ownerRef($request),
            $this->actorRef($request),
            $validated['notes'] ?? null,
        );

        return redirect()
            ->route('care.care-units.roster', [
                'careUnit' => $careUnit,
                'week' => Carbon::parse($validated['duty_date'])->startOfWeek(Carbon::MONDAY)->toDateString(),
            ])
            ->with('success', 'Staff added to roster.');
    }

    public function destroy(Request $request, CareUnit $careUnit, RosterEntry $rosterEntry, RosterService $roster): RedirectResponse
    {
        $this->authorizeAbility($request, 'nursing.roster.manage');
        $this->authorizeOwner($request, $careUnit);
        $this->authorizeOwner($request, $rosterEntry);
        abort_unless((int) $rosterEntry->care_unit_id === (int) $careUnit->id, 404);

        $week = $rosterEntry->duty_date->copy()->startOfWeek(Carbon::MONDAY)->toDateString();
        $roster->cancel($rosterEntry, $this->ownerRef($request), $this->actorRef($request));

        return redirect()
            ->route('care.care-units.roster', ['careUnit' => $careUnit, 'week' => $week])
            ->with('success', 'Roster entry cancelled.');
    }
}
