<?php

namespace App\Policies;

use App\Models\BackupSchedule;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Auth\Capabilities;
use App\Support\OperateHub\OperateHubShell;
use Filament\Facades\Filament;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;

class BackupSchedulePolicy
{
    use HandlesAuthorization;

    protected function isTenantMember(User $user, ?ManagedEnvironment $tenant = null): bool
    {
        $tenant ??= $this->resolvedTenant();

        return $tenant instanceof ManagedEnvironment
            && Gate::forUser($user)->allows(Capabilities::TENANT_VIEW, $tenant);
    }

    public function viewAny(User $user): bool
    {
        return $this->isTenantMember($user);
    }

    public function view(User $user, BackupSchedule $schedule): Response|bool
    {
        $tenant = $this->resolvedTenant();

        if (! $this->isTenantMember($user, $tenant)) {
            return Response::denyAsNotFound();
        }

        return (int) $schedule->managed_environment_id === (int) $tenant->getKey()
            ? true
            : Response::denyAsNotFound();
    }

    public function create(User $user): bool
    {
        $tenant = $this->resolvedTenant();

        return $tenant instanceof ManagedEnvironment
            && Gate::forUser($user)->allows(Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE, $tenant);
    }

    public function update(User $user, BackupSchedule $schedule): Response|bool
    {
        return $this->authorizeScheduleAction($user, $schedule, Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE);
    }

    public function delete(User $user, BackupSchedule $schedule): Response|bool
    {
        return $this->authorizeScheduleAction($user, $schedule, Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE);
    }

    public function restore(User $user, BackupSchedule $schedule): Response|bool
    {
        return $this->authorizeScheduleAction($user, $schedule, Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE);
    }

    public function forceDelete(User $user, BackupSchedule $schedule): Response|bool
    {
        return $this->authorizeScheduleAction($user, $schedule, Capabilities::TENANT_DELETE);
    }

    protected function authorizeScheduleAction(User $user, BackupSchedule $schedule, string $capability): Response|bool
    {
        $tenant = $this->resolvedTenant();

        if (! $this->isTenantMember($user, $tenant)) {
            return Response::denyAsNotFound();
        }

        if (! $tenant instanceof ManagedEnvironment || (int) $schedule->managed_environment_id !== (int) $tenant->getKey()) {
            return Response::denyAsNotFound();
        }

        return Gate::forUser($user)->allows($capability, $tenant)
            ? true
            : Response::deny();
    }

    protected function resolvedTenant(): ?ManagedEnvironment
    {
        if (Filament::getCurrentPanel()?->getId() === 'admin') {
            $tenant = app(OperateHubShell::class)->tenantOwnedPanelContext(request());

            return $tenant instanceof ManagedEnvironment ? $tenant : null;
        }

        $tenant = ManagedEnvironment::current();

        return $tenant instanceof ManagedEnvironment ? $tenant : null;
    }
}
