<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Http\Controllers\Controller;
use App\Models\Branch;
use App\Models\CareDisplayScreen;
use App\Models\CareServiceQueue;
use App\Services\Care\CarePermissions;
use App\Services\Care\OrganizationResolver;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class DisplayScreenController extends Controller
{
    use ScopesToAccount;

    public function index(Request $request): View
    {
        $this->authorizeAbility($request, 'displays.view');
        $owner = $this->ownerRef($request);
        $organization = $this->organization($request);

        $member = $this->member($request);
        $permissions = app(CarePermissions::class);
        $branchScope = app(OrganizationResolver::class)->branchScope($member);

        $screens = CareDisplayScreen::owned($owner)
            ->where('organization_id', $organization->id)
            ->with('branch')
            ->when($branchScope, fn ($q) => $q->where('branch_id', $branchScope))
            ->orderBy('name')
            ->paginate(20);

        $screenStats = CareDisplayScreen::owned($owner)
            ->where('organization_id', $organization->id)
            ->when($branchScope, fn ($q) => $q->where('branch_id', $branchScope))
            ->get();

        $heroStats = [
            'total' => $screenStats->count(),
            'active' => $screenStats->where('is_active', true)->count(),
            'branches' => $screenStats->pluck('branch_id')->filter()->unique()->count(),
        ];

        return view('care.displays.index', [
            'screens' => $screens,
            'organization' => $organization,
            'canManage' => $permissions->can($member, 'displays.manage'),
            'heroStats' => $heroStats,
        ]);
    }

    public function show(Request $request, CareDisplayScreen $display): View
    {
        $this->authorizeAbility($request, 'displays.view');
        $this->authorizeOwner($request, $display);
        abort_unless($display->organization_id === $this->organization($request)->id, 404);
        $display->load(['branch', 'organization']);

        $member = $this->member($request);
        $permissions = app(CarePermissions::class);

        $queueIds = array_map('intval', $display->service_queue_ids ?? []);
        $queues = CareServiceQueue::query()
            ->whereIn('id', $queueIds)
            ->orderBy('name')
            ->get();

        return view('care.displays.show', [
            'display' => $display,
            'queues' => $queues,
            'publicUrl' => route('care.display.public', $display->access_token),
            'canManage' => $permissions->can($member, 'displays.manage'),
        ]);
    }

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

        return view('care.displays.create', [
            'organization' => $organization,
            'branches' => $this->branches($request, $organization->id),
            'queues' => CareServiceQueue::owned($owner)
                ->where('organization_id', $organization->id)
                ->orderBy('name')
                ->get(),
            'layouts' => config('care.display_layouts'),
        ]);
    }

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

        $validated = $this->validatedDisplay($request, $organization);

        $screen = CareDisplayScreen::create([
            'owner_ref' => $owner,
            'organization_id' => $organization->id,
            'branch_id' => $validated['branch_id'],
            'name' => $validated['name'],
            'layout' => $validated['layout'],
            'service_queue_ids' => $validated['queue_ids'] ?? [],
            'is_active' => true,
        ]);

        return redirect()->route('care.displays.show', $screen)
            ->with('success', 'Display created. URL: '.route('care.display.public', $screen->access_token));
    }

    public function edit(Request $request, CareDisplayScreen $display): View
    {
        $this->authorizeAbility($request, 'displays.manage');
        $this->authorizeOwner($request, $display);
        abort_unless($display->organization_id === $this->organization($request)->id, 404);
        $owner = $this->ownerRef($request);

        return view('care.displays.edit', [
            'display' => $display,
            'branches' => $this->branches($request, $display->organization_id),
            'queues' => CareServiceQueue::owned($owner)
                ->where('organization_id', $display->organization_id)
                ->orderBy('name')
                ->get(),
            'layouts' => config('care.display_layouts'),
        ]);
    }

    public function update(Request $request, CareDisplayScreen $display): RedirectResponse
    {
        $this->authorizeAbility($request, 'displays.manage');
        $this->authorizeOwner($request, $display);
        abort_unless($display->organization_id === $this->organization($request)->id, 404);

        $validated = $this->validatedDisplay($request, $this->organization($request));
        $display->update([
            'name' => $validated['name'],
            'branch_id' => $validated['branch_id'],
            'layout' => $validated['layout'],
            'service_queue_ids' => $validated['queue_ids'] ?? [],
            'is_active' => $request->boolean('is_active', $display->is_active),
        ]);

        return redirect()->route('care.displays.show', $display)->with('success', 'Display updated.');
    }

    /**
     * @return array<string, mixed>
     */
    protected function validatedDisplay(Request $request, $organization): array
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'branch_id' => ['required', 'integer', 'exists:care_branches,id'],
            'layout' => ['required', 'string', 'in:'.implode(',', array_keys(config('care.display_layouts')))],
            'queue_ids' => ['nullable', 'array'],
            'queue_ids.*' => ['integer', 'exists:care_service_queues,id'],
        ]);

        $ok = Branch::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->where('id', $validated['branch_id'])
            ->exists();
        abort_unless($ok, 422);

        if (! empty($validated['queue_ids'])) {
            $count = CareServiceQueue::owned($this->ownerRef($request))
                ->where('organization_id', $organization->id)
                ->whereIn('id', $validated['queue_ids'])
                ->count();
            abort_unless($count === count($validated['queue_ids']), 422);
        }

        return $validated;
    }

    /** @return \Illuminate\Database\Eloquent\Collection<int, Branch> */
    protected function branches(Request $request, int $organizationId)
    {
        $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));

        return Branch::owned($this->ownerRef($request))
            ->where('organization_id', $organizationId)
            ->where('is_active', true)
            ->when($branchScope, fn ($q) => $q->where('id', $branchScope))
            ->orderBy('name')
            ->get();
    }
}
