<?php

namespace App\Filament\Resources\RestoreRunResource\Pages;

use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Resources\RestoreRunResource;
use App\Models\BackupSet;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\Auth\CapabilityResolver;
use App\Support\Auth\Capabilities;
use Filament\Actions\Action;
use Filament\Resources\Pages\Concerns\HasWizard;
use Filament\Resources\Pages\CreateRecord;
use Illuminate\Database\Eloquent\Model;
use Livewire\Attributes\On;

class CreateRestoreRun extends CreateRecord
{
    use HasWizard;
    use ResolvesPanelTenantContext;

    protected static string $resource = RestoreRunResource::class;

    protected function authorizeAccess(): void
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        $user = auth()->user();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User) {
            abort(404);
        }

        $capabilityResolver = app(CapabilityResolver::class);

        if (! $capabilityResolver->isMember($user, $tenant)) {
            abort(404);
        }

        if (! $capabilityResolver->can($user, $tenant, Capabilities::TENANT_MANAGE)) {
            abort(403);
        }
    }

    public function getSteps(): array
    {
        return RestoreRunResource::getWizardSteps();
    }

    protected function afterFill(): void
    {
        $backupSetIdRaw = request()->query('backup_set_id');

        if (! is_numeric($backupSetIdRaw)) {
            return;
        }

        $backupSetId = (int) $backupSetIdRaw;

        if ($backupSetId <= 0) {
            return;
        }

        $tenant = static::resolveTenantContextForCurrentPanel();

        if (! $tenant) {
            return;
        }

        $belongsToTenant = BackupSet::query()
            ->where('managed_environment_id', $tenant->id)
            ->whereKey($backupSetId)
            ->exists();

        if (! $belongsToTenant) {
            return;
        }

        $backupItemIds = $this->normalizeBackupItemIds(request()->query('backup_item_ids'));
        $scopeModeRaw = request()->query('scope_mode');
        $scopeMode = in_array($scopeModeRaw, ['all', 'selected'], true)
            ? $scopeModeRaw
            : ($backupItemIds !== [] ? 'selected' : 'all');

        $this->data['backup_set_id'] = $backupSetId;
        $this->form->callAfterStateUpdated('data.backup_set_id');

        $this->data['scope_mode'] = $scopeMode;
        $this->form->callAfterStateUpdated('data.scope_mode');

        if ($scopeMode === 'selected') {
            if ($backupItemIds !== []) {
                $this->data['backup_item_ids'] = $backupItemIds;
            }

            $this->form->callAfterStateUpdated('data.backup_item_ids');
        }

        $this->data = RestoreRunResource::synchronizeRestoreSafetyDraft($this->data);
        $this->form->fill($this->data);
    }

    /**
     * @return array<int>
     */
    private function normalizeBackupItemIds(mixed $raw): array
    {
        if (is_string($raw)) {
            $raw = array_filter(array_map('trim', explode(',', $raw)));
        }

        if (! is_array($raw)) {
            return [];
        }

        $itemIds = [];

        foreach ($raw as $value) {
            if (is_int($value) && $value > 0) {
                $itemIds[] = $value;

                continue;
            }

            if (is_string($value) && ctype_digit($value)) {
                $itemId = (int) $value;

                if ($itemId > 0) {
                    $itemIds[] = $itemId;
                }
            }
        }

        $itemIds = array_values(array_unique($itemIds));
        sort($itemIds);

        return $itemIds;
    }

    protected function getSubmitFormAction(): Action
    {
        return parent::getSubmitFormAction()
            ->label('Create restore run')
            ->icon('heroicon-o-check-circle');
    }

    protected function handleRecordCreation(array $data): Model
    {
        return RestoreRunResource::createRestoreRun($data);
    }

    #[On('entra-group-cache-picked')]
    public function applyEntraGroupCachePick(string $sourceGroupId, string $entraId): void
    {
        data_set($this->data, "group_mapping.{$sourceGroupId}", $entraId);
        $this->data['is_dry_run'] = true;
        $this->data['acknowledged_impact'] = false;
        $this->data['tenant_confirm'] = null;
        $this->data = RestoreRunResource::synchronizeRestoreSafetyDraft($this->data);

        $this->form->fill($this->data);

        if (method_exists($this, 'unmountAction')) {
            $this->unmountAction();
        }
    }
}
