<?php

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Routing\Route as RouteElement;
use Illuminate\Support\Facades\Route;
use Illuminate\Translation\PotentiallyTranslatedString;

class TeamName implements ValidationRule
{
    /**
     * Run the validation rule.
     *
     * @param  Closure(string, ?string=): PotentiallyTranslatedString  $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $name = strtolower(trim($value));

        if (in_array($name, $this->reservedNames(), true)) {
            $fail(__('This team name is reserved and cannot be used.'));
        }
    }

    /**
     * Get a list of all reserved names.
     *
     * @return array<int, string>
     */
    protected function reservedNames(): array
    {
        return once(fn () => collect($this->routesPrefixes())
            ->merge([
                '300',
                '302',
                '400',
                '401',
                '402',
                '403',
                '404',
                '405',
                '406',
                '407',
                '408',
                '409',
                '410',
                '411',
                '412',
                '413',
                '414',
                '415',
                '416',
                '417',
                '418',
                '419',
                '420',
                '421',
                '422',
                '423',
                '424',
                '425',
                '426',
                '427',
                '428',
                '429',
                '430',
                '431',
                '500',
                '501',
                '502',
                '503',
                '504',
                '505',
                '506',
                '507',
                '508',
                '509',
                '510',
                '511',
                '693',
                '694',
                '695',
                '900',
                'about',
                'account',
                'accounts',
                'accountspayable',
                'accounts-payable',
                'accountsreceivable',
                'accounts-receivable',
                'admin',
                'advisories',
                'anonymous',
                'any',
                'api',
                'app',
                'apps',
                'attributes',
                'auth',
                'billing',
                'bills',
                'blob',
                'blog',
                'bounty',
                'branches',
                'business',
                'businesses',
                'cache',
                'careers',
                'case-studies',
                'categories',
                'central',
                'certification',
                'changelog',
                'chat',
                'cla',
                'claim',
                'claims',
                'cloud',
                'codereview',
                'code-review',
                'code-reviews',
                'collection',
                'collections',
                'comments',
                'commit',
                'commits',
                'companies',
                'compare',
                'contact',
                'contributing',
                'cookbook',
                'copilot',
                'coupons',
                'customer',
                'customer-stories',
                'customers',
                'dashboard',
                'dashboard-feed',
                'dashboards',
                'delete',
                'deploy',
                'design',
                'develop',
                'developer',
                'diff',
                'discover',
                'discussions',
                'downloads',
                'downtime',
                'editor',
                'editors',
                'edu',
                'education',
                'enterprise',
                'events',
                'explore',
                'featured',
                'features',
                'files',
                'fixtures',
                'forked',
                'fraud',
                'garage',
                'gist',
                'gists',
                'graphs',
                'groups',
                'guide',
                'guides',
                'help',
                'help-wanted',
                'home',
                'hooks',
                'hosting',
                'hovercards',
                'identity',
                'images',
                'inbox',
                'index',
                'individual',
                'info',
                'integration',
                'interfaces',
                'introduction',
                'invalid-email-address',
                'investors',
                'invoice',
                'invoices',
                'issues',
                'jobs',
                'join',
                'journal',
                'journals',
                'lab',
                'labs',
                'languages',
                'launch',
                'layouts',
                'learn',
                'legal',
                'library',
                'linux',
                'listings',
                'lists',
                'livewire',
                'login',
                'logos',
                'logout',
                'mac',
                'maintenance',
                'malware',
                'man',
                'mariadb',
                'marketing',
                'marketplace',
                'mention',
                'mentioned',
                'mentioning',
                'mentions',
                'migrating',
                'milestones',
                'mine',
                'mirrors',
                'mobile',
                'mysql',
                'n8n',
                'navigation',
                'network',
                'network-rules',
                'new',
                'news',
                'none',
                'nonprofit',
                'nonprofits',
                'notices',
                'notifications',
                'oauth',
                'offer',
                'open-source',
                'org',
                'organisations',
                'organizations',
                'orgs',
                'pages',
                'partners',
                'pay',
                'payable',
                'payments',
                'percona',
                'personal',
                'plans',
                'plugins',
                'popular',
                'popularity',
                'posts',
                'postgres',
                'postgresql',
                'press',
                'preview',
                'pricing',
                'professional',
                'projects',
                'pulls',
                'raw',
                'readme',
                'recommendations',
                'receivable',
                'redeem',
                'register',
                'releases',
                'render',
                'reply',
                'repositories',
                'resources',
                'restore',
                'revert',
                'review',
                'reviews',
                'save-net-neutrality',
                'saved',
                'scraping',
                'search',
                'security',
                'services',
                'sessions',
                'settings',
                'shareholders',
                'shop',
                'showcases',
                'signin',
                'sign-in',
                'signup',
                'sign-up',
                'site',
                'socials',
                'spam',
                'sponsors',
                'ssh',
                'staff',
                'starred',
                'stars',
                'start',
                'static',
                'status',
                'statuses',
                'storage',
                'store',
                'stories',
                'stripe',
                'styleguide',
                'subscriptions',
                'suggest',
                'suggestion',
                'suggestions',
                'support',
                'suspended',
                'suspension',
                'talks',
                'teach',
                'teacher',
                'teachers',
                'teaching',
                'team',
                'teams',
                'ten',
                'terms',
                'timeline',
                'topic',
                'topics',
                'tos',
                'tour',
                'train',
                'training',
                'translations',
                'tree',
                'trending',
                'undefined',
                'update',
                'updates',
                'upstash',
                'username',
                'users',
                'visualization',
                'watching',
                'wiki',
                'wikis',
                'windows',
                'works-with',
                'www',
                'www0',
                'www1',
                'www2',
                'www3',
                'www4',
                'www5',
                'www6',
                'www7',
                'www8',
                'www9',
                'zones',
            ])
            ->unique()
            ->sort()
            ->values()
            ->toArray());
    }

    /**
     * Get a list of reserved names from the application's route prefixes.
     *
     * @return array<int, string>
     */
    protected function routesPrefixes(): array
    {
        return collect(Route::getRoutes()->getRoutes())
            ->map(fn (RouteElement $route) => $route->uri)
            ->map(fn (string $uri) => explode('/', $uri)[0])
            ->reject(fn (string $uri) => str_contains($uri, '{'))
            ->filter(fn (string $uri) => $uri !== '')
            ->unique()
            ->sort()
            ->values()
            ->toArray();
    }
}
