<?php

declare(strict_types=1);

namespace App\Filament\Pages;

use App\Domain\Plugin\PluginManager;
use App\Models\Plugin;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\Width;
use Filament\Support\Icons\Heroicon;
use Illuminate\Contracts\View\View;

class ManagePlugins extends Page
{
    protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedPuzzlePiece;

    protected static ?int $navigationSort = 81;

    protected string $view = 'filament.pages.manage-plugins';

    /** @var array<int, array<string, mixed>> */
    public array $plugins = [];

    public static function getNavigationGroup(): ?string
    {
        return __('admin.groups.system');
    }

    public static function getNavigationLabel(): string
    {
        return __('admin.nav.plugins');
    }

    public function getTitle(): string
    {
        return __('admin.pages.plugins_title');
    }

    public function mount(PluginManager $manager): void
    {
        $manager->syncDiscoveredPlugins();
        $this->reload($manager);
    }

    public function enable(string $name, PluginManager $manager): void
    {
        try {
            $manager->enable($name);
            $this->reload($manager);
            Notification::make()->title(__('admin.pages.enable').'：'.$name)->success()->send();
        } catch (\Throwable $e) {
            Notification::make()->title($e->getMessage())->danger()->send();
        }
    }

    public function disable(string $name, PluginManager $manager): void
    {
        try {
            $manager->disable($name);
            $this->reload($manager);
            Notification::make()->title(__('admin.pages.disable').'：'.$name)->success()->send();
        } catch (\Throwable $e) {
            Notification::make()->title($e->getMessage())->danger()->send();
        }
    }

    public function showDocs(string $name, PluginManager $manager): void
    {
        if ($manager->readDocs($name) === null) {
            Notification::make()->title(__('admin.messages.plugin_docs_missing'))->warning()->send();

            return;
        }

        $this->mountAction('viewDocs', ['name' => $name]);
    }

    public function viewDocsAction(): Action
    {
        return Action::make('viewDocs')
            ->label(__('admin.pages.plugin_docs'))
            ->modalHeading(function (array $arguments): string {
                $name = (string) ($arguments['name'] ?? '');
                $plugin = collect($this->plugins)->firstWhere('name', $name);
                $title = is_array($plugin) ? (string) ($plugin['title'] ?? $name) : $name;

                return __('admin.pages.plugin_docs').($title !== '' ? ' · '.$title : '');
            })
            ->modalContent(function (array $arguments): View {
                return view('filament.partials.plugin-docs', [
                    'html' => app(PluginManager::class)->readDocsHtml((string) ($arguments['name'] ?? '')) ?? '',
                ]);
            })
            ->modalAlignment(Alignment::Center)
            ->modalWidth(Width::FiveExtraLarge)
            ->modalSubmitAction(false)
            ->modalCancelAction(fn (Action $action): Action => $action
                ->label(__('admin.actions.close'))
                ->color('primary')
                ->close()
            )
            ->modalFooterActionsAlignment(Alignment::End)
            ->closeModalByClickingAway()
            ->closeModalByEscaping()
            ->stickyModalHeader()
            ->stickyModalFooter()
            ->extraModalWindowAttributes(['class' => 'lb-plugin-docs-modal']);
    }

    protected function reload(PluginManager $manager): void
    {
        $discovered = $manager->discover();
        $records = Plugin::query()->get()->keyBy('name');
        $accents = ['#0f8a7a', '#c45c26', '#2563eb', '#7c3aed', '#db2777', '#0891b2'];

        $this->plugins = $discovered->values()->map(function (array $manifest, int $index) use ($records, $accents, $manager) {
            $name = (string) $manifest['name'];
            $titleKey = 'admin.plugins.'.$name.'.title';
            $descKey = 'admin.plugins.'.$name.'.description';
            $record = $records->get($name);
            $requires = (array) ($manifest['requires'] ?? []);

            return [
                'name' => $name,
                'title' => __($titleKey) !== $titleKey ? __($titleKey) : ($manifest['title'] ?? $name),
                'version' => $manifest['version'] ?? '1.0.0',
                'description' => __($descKey) !== $descKey ? __($descKey) : ($manifest['description'] ?? ''),
                'enabled' => (bool) ($record?->enabled),
                'requires' => $requires,
                'has_docs' => $manager->docsPath($name) !== null,
                'accent' => $accents[$index % count($accents)],
            ];
        })->all();
    }

    protected function getHeaderActions(): array
    {
        return [
            Action::make('sync')
                ->label(__('admin.pages.plugins_sync'))
                ->action(function (PluginManager $manager): void {
                    $manager->syncDiscoveredPlugins();
                    $this->reload($manager);
                    Notification::make()->title(__('admin.pages.plugins_sync'))->success()->send();
                }),
        ];
    }
}
