<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Filament\HostPluginCenter\Concerns;

use App\Exceptions\Plugin\HostPluginInstallException;
use App\Exceptions\Plugin\HostPluginOperationException;
use App\Exceptions\SupportCenter\SupportCenterException;
use App\Filament\Pages\HostPluginCenterPage;
use App\Services\Plugin\HostPluginInstallOrchestrator;
use App\Services\Plugin\HostPluginLifecycleService;
use App\Services\Plugin\HostPluginSettingsAccessResult;
use App\Services\Plugin\HostPluginUpdateOrchestrator;
use App\Support\HostPluginCenterDisplay;
use Filament\Notifications\Notification;
use Throwable;

trait InteractsWithHostPluginOperations
{
    public function installOfficialPlugin(string $pluginCode, ?string $version = null): void
    {
        if (! HostPluginCenterPage::canInstallPlugin()) {
            $this->notifyHostPluginOperationDenied();

            return;
        }

        if (property_exists($this, 'pluginInstallInProgress') && $this->pluginInstallInProgress) {
            return;
        }

        if (property_exists($this, 'pluginInstallInProgress')) {
            $this->pluginInstallInProgress = true;
            $this->installingPluginCode = trim($pluginCode);
        }

        try {
            app(HostPluginInstallOrchestrator::class)->install($pluginCode, $version);
            app(HostPluginCenterDisplay::class)->clearCatalogCache();

            Notification::make()
                ->success()
                ->title(__('dberp.plugin_center.install.success_title'))
                ->body(__('dberp.plugin_center.install.success_body'))
                ->send();

            $this->dispatchHostPluginCenterDataChanged();
        } catch (HostPluginInstallException|SupportCenterException $exception) {
            $message = $exception instanceof HostPluginInstallException
                ? $exception->userFacingMessage()
                : $exception->userFacingMessage();

            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.install.failed_title'),
                $message,
            );
        } catch (Throwable $exception) {
            report($exception);

            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.install.failed_title'),
                (string) __('dberp.plugin_center.install.failed'),
            );
        } finally {
            if (property_exists($this, 'pluginInstallInProgress')) {
                $this->pluginInstallInProgress = false;
                $this->installingPluginCode = null;
            }
        }
    }

    public function enableOfficialPlugin(string $identifier): void
    {
        if (! HostPluginCenterPage::canEnablePlugin()) {
            $this->notifyHostPluginOperationDenied();

            return;
        }

        try {
            app(HostPluginLifecycleService::class)->enable($identifier);
            app(HostPluginCenterDisplay::class)->clearCatalogCache();

            Notification::make()
                ->success()
                ->title(__('dberp.plugin_center.lifecycle.enable_success_title'))
                ->body(__('dberp.plugin_center.lifecycle.enable_success_body'))
                ->send();

            $this->redirect(HostPluginCenterPage::getUrl(), navigate: false);
        } catch (HostPluginOperationException $exception) {
            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.lifecycle.enable_failed_title'),
                $exception->userFacingMessage(),
            );
        } catch (Throwable $exception) {
            report($exception);

            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.lifecycle.enable_failed_title'),
                (string) __('dberp.plugin_center.lifecycle.enable_failed'),
            );
        }
    }

    public function disableOfficialPlugin(string $identifier): void
    {
        if (! HostPluginCenterPage::canDisablePlugin()) {
            $this->notifyHostPluginOperationDenied();

            return;
        }

        try {
            app(HostPluginLifecycleService::class)->disable($identifier);
            app(HostPluginCenterDisplay::class)->clearCatalogCache();

            Notification::make()
                ->success()
                ->title(__('dberp.plugin_center.lifecycle.disable_success_title'))
                ->body(__('dberp.plugin_center.lifecycle.disable_success_body'))
                ->send();

            $this->redirect(HostPluginCenterPage::getUrl(), navigate: false);
        } catch (HostPluginOperationException $exception) {
            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.lifecycle.disable_failed_title'),
                $exception->userFacingMessage(),
            );
        } catch (Throwable $exception) {
            report($exception);

            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.lifecycle.disable_failed_title'),
                (string) __('dberp.plugin_center.lifecycle.disable_failed'),
            );
        }
    }

    public function updateOfficialPlugin(string $pluginCode, ?string $version = null): void
    {
        if (! HostPluginCenterPage::canUpdatePlugin()) {
            $this->notifyHostPluginOperationDenied();

            return;
        }

        if (
            (property_exists($this, 'pluginUpdateInProgress') && $this->pluginUpdateInProgress)
            || (property_exists($this, 'pluginInstallInProgress') && $this->pluginInstallInProgress)
        ) {
            return;
        }

        if (property_exists($this, 'pluginUpdateInProgress')) {
            $this->pluginUpdateInProgress = true;
            $this->updatingPluginCode = trim($pluginCode);
        }

        try {
            app(HostPluginUpdateOrchestrator::class)->update($pluginCode, $version);
            app(HostPluginCenterDisplay::class)->clearCatalogCache();

            Notification::make()
                ->success()
                ->title(__('dberp.plugin_center.update.success_title'))
                ->body(__('dberp.plugin_center.update.success_body'))
                ->send();

            $this->dispatchHostPluginCenterDataChanged();
        } catch (HostPluginOperationException $exception) {
            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.update.failed_title'),
                $exception->userFacingMessage(),
            );
        } catch (HostPluginInstallException|SupportCenterException $exception) {
            $message = $exception instanceof HostPluginInstallException
                ? $exception->userFacingMessage()
                : $exception->userFacingMessage();

            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.update.failed_title'),
                $message,
            );
        } catch (Throwable $exception) {
            report($exception);

            $this->notifyHostPluginOperationFailed(
                (string) __('dberp.plugin_center.update.failed_title'),
                (string) __('dberp.plugin_center.update.failed'),
            );
        } finally {
            if (property_exists($this, 'pluginUpdateInProgress')) {
                $this->pluginUpdateInProgress = false;
                $this->updatingPluginCode = null;
            }
        }
    }

    protected function notifyHostPluginOperationDenied(): void
    {
        Notification::make()
            ->danger()
            ->title(__('dberp.plugin_center.notifications.operation_denied_title'))
            ->body(__('dberp.plugin_center.notifications.operation_denied_body'))
            ->send();
    }

    protected function notifyHostPluginOperationFailed(string $title, string $body): void
    {
        $this->dispatch('plugin-operation-failed');

        Notification::make()
            ->danger()
            ->title($title)
            ->body(trim($body)."\n\n".(string) __('dberp.plugin_center.activity.failure_hint'))
            ->persistent()
            ->send();
    }

    protected function dispatchHostPluginCenterDataChanged(): void
    {
        $this->dispatch('plugin-center-data-changed');
    }

    protected function settingsNotificationTitle(HostPluginSettingsAccessResult $access): string
    {
        return match ($access->state) {
            HostPluginSettingsAccessResult::STATE_NO_CONFIG_ROUTE => (string) __('dberp.plugin_center.settings.no_settings_title'),
            HostPluginSettingsAccessResult::STATE_ROUTE_MISSING => (string) __('dberp.plugin_center.settings.unavailable_title'),
            HostPluginSettingsAccessResult::STATE_PLUGIN_DISABLED => (string) __('dberp.plugin_center.settings.plugin_disabled_title'),
            default => (string) __('dberp.plugin_center.settings.unavailable_title'),
        };
    }
}
