<?php

declare(strict_types=1);

namespace Builder\Seo\Resources;

use Builder\Core\Foundation\Definition\Field;
use Builder\Core\Foundation\Definition\FieldBuilder;
use Builder\Core\Foundation\Definition\Section;
use Builder\Core\Foundation\Resources\Resource;
use Builder\Core\Foundation\Tables\BulkAction;
use Builder\Core\Foundation\Tables\Column;
use Builder\Seo\Models\Redirect;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\Rule;

final class RedirectResource extends Resource
{
    public static function getSlug(): string
    {
        return 'redirects';
    }

    public static function getLabel(): string
    {
        return (string) __('seo::seo.redirects.label');
    }

    public static function getSingularLabel(): string
    {
        return (string) __('seo::seo.redirects.singular');
    }

    /** @return class-string<Model> */
    public static function getModel(): string
    {
        return Redirect::class;
    }

    public function getPermission(): string
    {
        return 'read:redirects';
    }

    /** @return list<string> */
    public function getPermissionSet(): array
    {
        return ['read:redirects', 'create:redirects', 'update:redirects', 'delete:redirects'];
    }

    /** @return array<string, mixed> */
    public function rules(string $action): array
    {
        $fromUnique = $action === 'update'
            ? Rule::unique('redirects', 'from')->ignore(request()->route('id'))
            : Rule::unique('redirects', 'from');

        return [
            // 'from' must be a single-slash path on this site. Protocol-relative
            // values like "//evil.com/x" must not normalise into a valid match.
            'from' => ['required', 'string', 'max:2048', 'regex:/^\/(?!\/)/', $fromUnique],
            // 'to' is the redirect target. Block javascript:/data:/vbscript:
            // schemes which some browsers still execute when sent via Location.
            'to' => ['required', 'string', 'max:2048', 'regex:/^(\/|https?:\/\/)/i'],
            'type' => ['required', 'in:permanent,temporary'],
        ];
    }

    public function fields(): FieldBuilder
    {
        return FieldBuilder::make()->add(
            Section::make('general')
                ->label((string) __('builder::builder.sections.general'))
                ->priority(10)
                ->fields([
                    Field::text('from')
                        ->label((string) __('seo::seo.redirects.fields.from'))
                        ->rules(['required', 'string', 'max:2048']),
                    Field::text('to')
                        ->label((string) __('seo::seo.redirects.fields.to'))
                        ->rules(['required', 'string', 'max:2048']),
                    Field::select('type')
                        ->label((string) __('seo::seo.redirects.fields.type'))
                        ->options([
                            'permanent' => (string) __('seo::seo.redirects.type_permanent'),
                            'temporary' => (string) __('seo::seo.redirects.type_temporary'),
                        ])
                        ->default('permanent')
                        ->rules(['required', 'in:permanent,temporary']),
                ]),
        );
    }

    /** @return list<Column> */
    public function columns(): array
    {
        return [
            Column::make('from')
                ->label((string) __('seo::seo.redirects.fields.from'))
                ->sortable()
                ->searchable(),
            Column::make('to')
                ->label((string) __('seo::seo.redirects.fields.to'))
                ->sortable(),
            Column::make('type')
                ->label((string) __('seo::seo.redirects.fields.type'))
                ->badge([
                    'permanent' => [
                        'label' => (string) __('seo::seo.redirects.type_permanent'),
                        'color' => 'blue',
                    ],
                    'temporary' => [
                        'label' => (string) __('seo::seo.redirects.type_temporary'),
                        'color' => 'yellow',
                    ],
                ]),
        ];
    }

    /** @return list<BulkAction> */
    public function bulkActions(): array
    {
        return [
            BulkAction::make('delete')
                ->label((string) __('seo::seo.redirects.bulk.delete'))
                ->confirm((string) __('seo::seo.redirects.bulk.delete_confirm'))
                ->permission('delete:redirects')
                ->handle(function (Collection $records): void {
                    $records->each->delete(); // @codeCoverageIgnore
                }),
        ];
    }

    /** @return list<string> */
    public function searchable(): array
    {
        return ['from', 'to'];
    }
}
