<script setup>
import AstrBotConfig from "@/components/shared/AstrBotConfig.vue";
import ConsoleDisplayer from "@/components/shared/ConsoleDisplayer.vue";
import ReadmeDialog from "@/components/shared/ReadmeDialog.vue";
import ProxySelector from "@/components/shared/ProxySelector.vue";
import UninstallConfirmDialog from "@/components/shared/UninstallConfirmDialog.vue";
import McpServersSection from "@/components/extension/McpServersSection.vue";
import SkillsSection from "@/components/extension/SkillsSection.vue";
import ComponentPanel from "@/components/extension/componentPanel/index.vue";
import InstalledPluginsTab from "./extension/InstalledPluginsTab.vue";
import MarketPluginsTab from "./extension/MarketPluginsTab.vue";
import PluginDetailPage from "./extension/PluginDetailPage.vue";
import { useExtensionPage } from "./extension/useExtensionPage";
import { computed } from "vue";
import defaultPluginIcon from "@/assets/images/plugin_icon.png";
import { usePluginI18n } from "@/utils/pluginI18n";

const pageState = useExtensionPage();
const { pluginName, pluginDesc } = usePluginI18n();

const {
  commonStore,
  t,
  tm,
  router,
  route,
  getSelectedGitHubProxy,
  conflictDialog,
  checkAndPromptConflicts,
  handleConflictConfirm,
  fileInput,
  activeTab,
  validTabs,
  isValidTab,
  getLocationHash,
  extractTabFromHash,
  syncTabFromHash,
  extension_data,
  getInitialShowReserved,
  showReserved,
  snack_message,
  snack_show,
  snack_success,
  configDialog,
  extension_config,
  pluginMarketData,
  loadingDialog,
  curr_namespace,
  updatingAll,
  readmeDialog,
  forceUpdateDialog,
  updateConfirmDialog,
  updateAllConfirmDialog,
  changelogDialog,
  getInitialListViewMode,
  isListView,
  pluginSearch,
  loading_,
  currentPage,
  dangerConfirmDialog,
  selectedDangerPlugin,
  selectedMarketInstallPlugin,
  installSupport,
  versionSupportDialog,
  showUninstallDialog,
  uninstallTarget,
  showSourceDialog,
  showSourceManagerDialog,
  sourceName,
  sourceUrl,
  sourceResolving,
  sourceResolveVisible,
  sourceMarketMeta,
  sourceResolveCurrent,
  customSources,
  selectedSource,
  showRemoveSourceDialog,
  sourceToRemove,
  editingSource,
  originalSourceUrl,
  extension_url,
  dialog,
  upload_file,
  uploadTab,
  showPluginFullName,
  marketSearch,
  debouncedMarketSearch,
  refreshingMarket,
  sortBy,
  sortOrder,
  randomPluginNames,
  normalizeStr,
  toPinyinText,
  toInitials,
  pluginHeaders,
  filteredExtensions,
  filteredPlugins,
  filteredMarketPlugins,
  sortedPlugins,
  RANDOM_PLUGINS_COUNT,
  randomPlugins,
  shufflePlugins,
  refreshRandomPlugins,
  displayItemsPerPage,
  totalPages,
  paginatedPlugins,
  updatableExtensions,
  toggleShowReserved,
  toast,
  resetLoadingDialog,
  onLoadingDialogResult,
  failedPluginsDict,
  getExtensions,
  handleReloadAllFailed,
  checkUpdate,
  uninstallExtension,
  handleUninstallConfirm,
  updateExtension,
  closeUpdateConfirmDialog,
  confirmUpdatePlugin,
  showUpdateAllConfirm,
  confirmUpdateAll,
  cancelUpdateAll,
  confirmForceUpdate,
  updateAllExtensions,
  pluginOn,
  pluginOff,
  openExtensionConfig,
  updateConfig,
  showPluginInfo,
  reloadPlugin,
  viewReadme,
  viewChangelog,
  openInstallDialog,
  closeInstallDialog,
  handleInstallPlugin,
  confirmDangerInstall,
  cancelDangerInstall,
  loadCustomSources,
  saveCustomSources,
  addCustomSource,
  openSourceManagerDialog,
  selectPluginSource,
  editCustomSource,
  removeCustomSource,
  confirmRemoveSource,
  resolveCustomSource,
  saveCustomSource,
  trimExtensionName,
  checkAlreadyInstalled,
  showVersionSupportWarning,
  continueInstallIgnoringVersionWarning,
  cancelInstallOnVersionWarning,
  newExtension,
  normalizePlatformList,
  getPlatformDisplayList,
  resolveSelectedInstallPlugin,
  selectedInstallPlugin,
  selectedInstallDownloadUrl,
  selectedInstallSourceUrl,
  installUsesGithubSource,
  selectedUpdateExtension,
  selectedUpdateMarketPlugin,
  selectedUpdateDownloadUrl,
  selectedUpdateSourceUrl,
  updateUsesGithubSource,
  checkInstallVersionSupport,
  refreshPluginMarket,
  handleLocaleChange,
  searchDebounceTimer,
} = pageState;

const selectedPluginId = computed(() => {
  const pluginId = route.params.pluginId;
  return Array.isArray(pluginId) ? pluginId[0] : pluginId || "";
});

const selectedDetailTab = computed(
  () => extractTabFromHash(route.hash) || "installed",
);

const selectedInstalledPlugin = computed(() => {
  if (!selectedPluginId.value) return null;
  const data = Array.isArray(extension_data?.data) ? extension_data.data : [];
  return data.find((plugin) => plugin.name === selectedPluginId.value) || null;
});

const normalizeRepoUrl = (value) =>
  String(value || "")
    .trim()
    .replace(/\/+$/, "")
    .toLowerCase()
    .replace(/\.git$/, "");

const selectedMarketPlugin = computed(() => {
  const market = Array.isArray(pluginMarketData.value)
    ? pluginMarketData.value
    : [];
  const installedPlugin = selectedInstalledPlugin.value;
  const marketNameMatch =
    market.find((item) => item.name === selectedPluginId.value) || null;

  if (selectedDetailTab.value === "market" || !installedPlugin) {
    return marketNameMatch;
  }

  const repo = normalizeRepoUrl(installedPlugin.repo);
  if (!repo) return null;

  return (
    market.find((item) => normalizeRepoUrl(item?.repo) === repo) || null
  );
});

const selectedDetailPlugin = computed(() => {
  if (selectedDetailTab.value === "market" && selectedMarketPlugin.value) {
    return selectedMarketPlugin.value;
  }
  return selectedInstalledPlugin.value || selectedMarketPlugin.value;
});

const installDialogPluginName = computed(() =>
  selectedInstallPlugin.value ? pluginName(selectedInstallPlugin.value) : "",
);

const installDialogPluginDesc = computed(() =>
  String(
    selectedInstallPlugin.value
      ? pluginDesc(
          selectedInstallPlugin.value,
          selectedInstallPlugin.value.desc ||
            selectedInstallPlugin.value.description ||
            "",
        )
      : "",
  ).trim(),
);

const installDialogPluginAuthor = computed(() => {
  const author = selectedInstallPlugin.value?.author;
  if (Array.isArray(author)) return author.join(", ");
  if (author && typeof author === "object") return author.name || "";
  return typeof author === "string" ? author.trim() : "";
});

const installDialogPluginLogo = computed(() => {
  const logo = selectedInstallPlugin.value?.logo;
  return typeof logo === "string" && logo.trim() ? logo : defaultPluginIcon;
});

const updateDialogPlugin = computed(
  () => selectedUpdateMarketPlugin.value || selectedUpdateExtension.value,
);

const updateDialogPluginName = computed(() =>
  updateDialogPlugin.value ? pluginName(updateDialogPlugin.value) : "",
);

const updateDialogCurrentVersion = computed(() =>
  String(selectedUpdateExtension.value?.version || "").trim(),
);

const updateDialogTargetVersion = computed(() =>
  String(selectedUpdateMarketPlugin.value?.version || "").trim(),
);

const updateDialogPluginLogo = computed(() => {
  const logo =
    selectedUpdateMarketPlugin.value?.logo || selectedUpdateExtension.value?.logo;
  return typeof logo === "string" && logo.trim() ? logo : defaultPluginIcon;
});
</script>

<template>
  <PluginDetailPage
    v-if="selectedPluginId && selectedDetailPlugin"
    :plugin="selectedDetailPlugin"
    :market-plugin="selectedMarketPlugin"
    :source-tab="selectedDetailTab"
    :state="pageState"
  />

  <div v-else-if="selectedPluginId && loading_" class="pa-4">
    <v-progress-linear indeterminate color="primary" />
  </div>

  <div v-else-if="selectedPluginId" class="pa-4">
    <div class="d-flex align-center mb-6">
      <v-btn
        icon="mdi-arrow-left"
        variant="text"
        density="comfortable"
        @click="
          router.push({ name: 'Extensions', hash: `#${selectedDetailTab}` })
        "
      />
      <h2 class="text-h3 mb-0 ml-2">
        {{
          selectedDetailTab === "market"
            ? tm("tabs.market")
            : tm("titles.installedAstrBotPlugins")
        }}
        <v-icon icon="mdi-chevron-right" size="24" class="mx-1" />
        {{ selectedPluginId }}
      </h2>
    </div>
    <v-alert type="warning" variant="tonal">
      {{ tm("detail.notFound") }}
    </v-alert>
  </div>

  <v-row v-else class="extension-page">
    <v-col cols="12" md="12">
      <v-card variant="flat" style="background-color: transparent">
        <!-- 标签页 -->
        <v-card-text style="padding: 0px 12px">
          <!-- 已安装插件标签页内容 -->
          <InstalledPluginsTab :state="pageState" />

          <!-- 指令面板标签页内容 -->
          <v-tab-item v-if="activeTab === 'components'">
            <div class="mb-4 pt-4 pb-4">
              <div class="d-flex align-center flex-wrap" style="gap: 12px">
                <h2 class="text-h2 mb-0">{{ tm("tabs.handlersOperation") }}</h2>
              </div>
            </div>
            <v-card
              class="rounded-lg"
              variant="flat"
              style="background-color: transparent"
            >
              <v-card-text class="pa-0">
                <ComponentPanel :active="activeTab === 'components'" />
              </v-card-text>
            </v-card>
          </v-tab-item>

          <!-- 已安装的 MCP 服务器标签页内容 -->
          <v-tab-item v-if="activeTab === 'mcp'">
            <div class="extension-detail-width">
              <div class="mb-4 pt-4 pb-4">
                <div class="d-flex flex-column" style="gap: 6px">
                  <h2 class="text-h2 mb-0">
                    {{ tm("tabs.installedMcpServers") }}
                  </h2>
                  <div class="text-body-2 text-medium-emphasis">
                    {{ t("features.tooluse.mcpServers.description") }}
                  </div>
                </div>
              </div>
              <v-card
                class="rounded-lg"
                variant="flat"
                style="background-color: transparent"
              >
                <v-card-text class="pa-0">
                  <McpServersSection />
                </v-card-text>
              </v-card>
            </div>
          </v-tab-item>

          <!-- Skills 标签页内容 -->
          <v-tab-item v-if="activeTab === 'skills'">
            <div class="extension-detail-width">
              <div class="mb-4 pt-4 pb-4">
                <div class="d-flex flex-column" style="gap: 6px">
                  <h2 class="text-h2 mb-0">{{ tm("tabs.skills") }}</h2>
                  <div class="text-body-2 text-medium-emphasis">
                    {{ tm("skills.runtimeHint") }}
                  </div>
                </div>
              </div>
              <v-card
                class="rounded-lg"
                variant="flat"
                style="background-color: transparent"
              >
                <v-card-text class="pa-0">
                  <SkillsSection />
                </v-card-text>
              </v-card>
            </div>
          </v-tab-item>

          <!-- 插件市场标签页内容 -->
          <MarketPluginsTab :state="pageState" />
        </v-card-text>
      </v-card>
    </v-col>

    <v-col v-if="activeTab === 'market'" cols="12" md="12">
      <div class="d-flex align-center justify-center mt-4 mb-4 gap-4">
        <v-btn
          variant="text"
          prepend-icon="mdi-book-open-variant"
          href="https://docs.astrbot.app/dev/star/plugin-new.html"
          rel="noopener noreferrer"
          target="_blank"
          color="primary"
          class="text-none"
        >
          {{ tm("market.devDocs") }}
        </v-btn>
        <div
          style="
            height: 24px;
            width: 1px;
            background-color: rgba(var(--v-theme-on-surface), 0.12);
          "
        ></div>
        <v-btn
          variant="text"
          prepend-icon="mdi-github"
          href="https://github.com/AstrBotDevs/AstrBot_Plugins_Collection"
          target="_blank"
          color="primary"
          class="text-none"
        >
          {{ tm("market.submitRepo") }}
        </v-btn>
      </div>
    </v-col>
  </v-row>

  <!-- 配置对话框 -->
  <v-dialog v-model="configDialog" max-width="900">
    <v-card>
      <v-card-title class="text-h2 pa-4 pl-6 pb-0">{{
        tm("dialogs.config.title")
      }}</v-card-title>
      <v-card-text>
        <div style="max-height: 60vh; overflow-y: auto; padding-right: 8px">
          <AstrBotConfig
            v-if="extension_config.metadata"
            :metadata="extension_config.metadata"
            :iterable="extension_config.config"
            :metadataKey="curr_namespace"
            :pluginName="curr_namespace"
            :pluginI18n="extension_config.i18n"
          />
          <p v-else>{{ tm("dialogs.config.noConfig") }}</p>
        </div>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="blue-darken-1" variant="text" @click="updateConfig">{{
          tm("buttons.saveAndClose")
        }}</v-btn>
        <v-btn
          color="blue-darken-1"
          variant="text"
          @click="configDialog = false"
          >{{ tm("buttons.close") }}</v-btn
        >
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 加载对话框 -->
  <v-dialog v-model="loadingDialog.show" width="700" persistent>
    <v-card>
      <v-card-title class="text-h5">{{ loadingDialog.title }}</v-card-title>
      <v-card-text style="max-height: calc(100vh - 200px); overflow-y: auto">
        <v-progress-linear
          v-if="loadingDialog.statusCode === 0"
          indeterminate
          color="primary"
          class="mb-4"
        ></v-progress-linear>

        <div v-if="loadingDialog.statusCode !== 0" class="py-8 text-center">
          <v-icon
            class="mb-6"
            :color="loadingDialog.statusCode === 1 ? 'success' : 'error'"
            :icon="
              loadingDialog.statusCode === 1
                ? 'mdi-check-circle-outline'
                : 'mdi-alert-circle-outline'
            "
            size="128"
          ></v-icon>
          <div class="text-h4 font-weight-bold">{{ loadingDialog.result }}</div>
        </div>

        <div style="margin-top: 32px">
          <h3>{{ tm("dialogs.loading.logs") }}</h3>
          <ConsoleDisplayer
            historyNum="10"
            style="height: 200px; margin-top: 16px; margin-bottom: 24px"
          >
          </ConsoleDisplayer>
        </div>
      </v-card-text>

      <v-divider></v-divider>

      <v-card-actions class="pa-4">
        <v-spacer></v-spacer>
        <v-btn
          color="blue-darken-1"
          variant="text"
          @click="resetLoadingDialog"
          >{{ tm("buttons.close") }}</v-btn
        >
      </v-card-actions>
    </v-card>
  </v-dialog>

  <v-snackbar
    :timeout="2000"
    elevation="24"
    :color="snack_success"
    v-model="snack_show"
    location="bottom center"
  >
    {{ snack_message }}
  </v-snackbar>

  <ReadmeDialog
    v-model:show="readmeDialog.show"
    :plugin-name="readmeDialog.pluginName"
    :repo-url="readmeDialog.repoUrl"
  />

  <!-- 插件更新日志对话框（复用 ReadmeDialog） -->
  <ReadmeDialog
    v-model:show="changelogDialog.show"
    :plugin-name="changelogDialog.pluginName"
    :repo-url="changelogDialog.repoUrl"
    mode="changelog"
  />

  <!-- 卸载插件确认对话框（列表模式用） -->
  <UninstallConfirmDialog
    v-model="showUninstallDialog"
    @confirm="handleUninstallConfirm"
  />

  <!-- 更新全部插件确认对话框 -->
  <v-dialog v-model="updateAllConfirmDialog.show" max-width="420">
    <v-card class="rounded-lg">
      <v-card-title class="d-flex align-center pa-4">
        <v-icon color="warning" class="mr-2">mdi-update</v-icon>
        {{ tm("dialogs.updateAllConfirm.title") }}
      </v-card-title>
      <v-card-text>
        <p class="text-body-1">
          {{
            tm("dialogs.updateAllConfirm.message", {
              count: updatableExtensions.length,
            })
          }}
        </p>
      </v-card-text>
      <v-card-actions class="pa-4">
        <v-spacer></v-spacer>
        <v-btn variant="text" @click="cancelUpdateAll">{{
          tm("buttons.cancel")
        }}</v-btn>
        <v-btn color="warning" variant="flat" @click="confirmUpdateAll">{{
          tm("dialogs.updateAllConfirm.confirm")
        }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 指令冲突提示对话框 -->
  <v-dialog v-model="conflictDialog.show" max-width="420">
    <v-card class="rounded-lg">
      <v-card-title class="d-flex align-center pa-4">
        <v-icon color="warning" class="mr-2">mdi-alert-circle</v-icon>
        {{ tm("conflicts.title") }}
      </v-card-title>
      <v-card-text class="px-4 pb-2">
        <div class="d-flex align-center mb-3">
          <v-chip
            color="warning"
            variant="tonal"
            size="large"
            class="font-weight-bold"
          >
            {{ conflictDialog.count }}
          </v-chip>
          <span class="ml-2 text-body-1">{{ tm("conflicts.pairs") }}</span>
        </div>
        <p
          class="text-body-2"
          style="color: rgba(var(--v-theme-on-surface), 0.7)"
        >
          {{ tm("conflicts.message") }}
        </p>
      </v-card-text>
      <v-card-actions class="pa-4 pt-2">
        <v-spacer></v-spacer>
        <v-btn variant="text" @click="conflictDialog.show = false">{{
          tm("conflicts.later")
        }}</v-btn>
        <v-btn color="warning" variant="flat" @click="handleConflictConfirm">
          {{ tm("conflicts.goToManage") }}
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 危险插件确认对话框 -->
  <v-dialog v-model="dangerConfirmDialog" width="500" persistent>
    <v-card>
      <v-card-title class="text-h5 d-flex align-center">
        <v-icon color="warning" class="mr-2">mdi-alert-circle</v-icon>
        {{ tm("dialogs.danger_warning.title") }}
      </v-card-title>
      <v-card-text>
        <div>{{ tm("dialogs.danger_warning.message") }}</div>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="grey" @click="cancelDangerInstall">
          {{ tm("dialogs.danger_warning.cancel") }}
        </v-btn>
        <v-btn color="warning" @click="confirmDangerInstall">
          {{ tm("dialogs.danger_warning.confirm") }}
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 版本不兼容警告对话框 -->
  <v-dialog v-model="versionSupportDialog.show" width="520" persistent>
    <v-card>
      <v-card-title class="text-h5 d-flex align-center">
        <v-icon color="warning" class="mr-2">mdi-alert</v-icon>
        {{ tm("dialogs.versionSupport.title") }}
      </v-card-title>
      <v-card-text>
        <div class="mb-2">{{ tm("dialogs.versionSupport.message") }}</div>
        <div class="text-medium-emphasis">
          {{ versionSupportDialog.message }}
        </div>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="grey" @click="cancelInstallOnVersionWarning">
          {{ tm("dialogs.versionSupport.cancel") }}
        </v-btn>
        <v-btn color="warning" @click="continueInstallIgnoringVersionWarning">
          {{ tm("dialogs.versionSupport.confirm") }}
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 上传插件对话框 -->
  <v-dialog v-model="dialog" width="500">
    <div
      class="v-card v-card--density-default rounded-lg v-card--variant-elevated"
    >
      <v-card-title class="text-h3 pa-4 pb-0 pl-6">
        {{ tm("dialogs.install.title") }}
      </v-card-title>

      <div class="v-card-text">
        <div v-if="selectedMarketInstallPlugin" class="market-install-confirm">
          <div class="market-install-confirm__header">
            <img
              :src="installDialogPluginLogo"
              :alt="installDialogPluginName"
              class="market-install-confirm__logo"
            />
            <div class="market-install-confirm__meta">
              <div class="market-install-confirm__name">
                {{ installDialogPluginName }}
              </div>
              <div
                v-if="installDialogPluginAuthor"
                class="market-install-confirm__author"
              >
                {{ tm("detail.info.author") }}: {{ installDialogPluginAuthor }}
              </div>
            </div>
          </div>

          <v-divider class="my-4" />

          <div
            v-if="installDialogPluginDesc"
            class="market-install-confirm__section"
          >
            <div class="market-install-confirm__section-title">
              {{ tm("table.headers.description") }}
            </div>
            <div class="market-install-confirm__desc">
              {{ installDialogPluginDesc }}
            </div>
          </div>

          <div v-if="selectedInstallPlugin" class="mt-4">
            <v-chip
              v-if="selectedInstallPlugin.astrbot_version"
              size="small"
              color="secondary"
              variant="outlined"
              class="mr-2 mb-2"
            >
              {{ tm("card.status.astrbotVersion") }}:
              {{ selectedInstallPlugin.astrbot_version }}
            </v-chip>
            <v-chip
              v-if="
                normalizePlatformList(selectedInstallPlugin.support_platforms)
                  .length
              "
              size="small"
              color="info"
              variant="outlined"
              class="mb-2"
            >
              {{ tm("card.status.supportPlatform") }}:
              {{
                getPlatformDisplayList(
                  selectedInstallPlugin.support_platforms,
                ).join(", ")
              }}
            </v-chip>
            <v-alert
              v-if="
                selectedInstallPlugin.astrbot_version &&
                installSupport.checked &&
                !installSupport.supported
              "
              type="warning"
              variant="tonal"
              density="comfortable"
              class="market-install-alert mt-2 mb-3"
            >
              {{ installSupport.message }}
            </v-alert>
          </div>

          <div
            v-if="selectedInstallSourceUrl"
            class="market-install-confirm__section-title mt-4"
          >
            {{ tm("dialogs.install.sectionTitle") }}
          </div>
          <div
            v-if="selectedInstallSourceUrl"
            class="market-install-source text-caption text-medium-emphasis mb-3"
          >
            <div>{{ tm("dialogs.install.downloadSource") }}</div>
            <div class="market-install-source__url">
              {{ selectedInstallSourceUrl }}
            </div>
          </div>

          <v-alert
            v-if="installUsesGithubSource"
            type="warning"
            variant="tonal"
            density="comfortable"
            class="market-install-alert mt-4 mb-4"
          >
            {{ tm("dialogs.install.githubSecurityWarning") }}
          </v-alert>

          <ProxySelector v-if="!selectedInstallDownloadUrl" class="mt-4" />
        </div>

        <template v-else>
          <v-tabs v-model="uploadTab" color="primary">
            <v-tab value="file">{{ tm("dialogs.install.fromFile") }}</v-tab>
            <v-tab value="url">{{ tm("dialogs.install.fromUrl") }}</v-tab>
          </v-tabs>

          <v-window v-model="uploadTab" class="mt-4">
            <v-window-item value="file">
              <div class="d-flex flex-column align-center justify-center pa-4">
                <v-file-input
                  ref="fileInput"
                  v-model="upload_file"
                  :label="tm('upload.selectFile')"
                  accept=".zip"
                  hide-details
                  hide-input
                  class="d-none"
                ></v-file-input>

                <v-btn
                  color="primary"
                  size="large"
                  prepend-icon="mdi-upload"
                  @click="$refs.fileInput.click()"
                  elevation="2"
                >
                  {{ tm("buttons.selectFile") }}
                </v-btn>

                <div class="text-body-2 text-medium-emphasis mt-2">
                  {{ tm("messages.supportedFormats") }}
                </div>

                <div v-if="upload_file" class="mt-4 text-center">
                  <v-chip
                    color="primary"
                    size="large"
                    closable
                    @click:close="upload_file = null"
                  >
                    {{ upload_file.name }}
                    <template v-slot:append>
                      <span class="text-caption ml-2"
                        >({{ (upload_file.size / 1024).toFixed(1) }}KB)</span
                      >
                    </template>
                  </v-chip>
                </div>
              </div>
            </v-window-item>

            <v-window-item value="url">
              <div class="pa-4">
                <v-text-field
                  v-model="extension_url"
                  :label="tm('upload.enterUrl')"
                  variant="outlined"
                  prepend-inner-icon="mdi-link"
                  hide-details
                  class="rounded-lg mb-4"
                  placeholder="https://github.com/username/repo"
                ></v-text-field>

                <div v-if="selectedInstallPlugin" class="mb-3">
                  <v-chip
                    v-if="selectedInstallPlugin.astrbot_version"
                    size="small"
                    color="secondary"
                    variant="outlined"
                    class="mr-2 mb-2"
                  >
                    {{ tm("card.status.astrbotVersion") }}:
                    {{ selectedInstallPlugin.astrbot_version }}
                  </v-chip>
                  <v-chip
                    v-if="
                      normalizePlatformList(
                        selectedInstallPlugin.support_platforms,
                      ).length
                    "
                    size="small"
                    color="info"
                    variant="outlined"
                    class="mb-2"
                  >
                    {{ tm("card.status.supportPlatform") }}:
                    {{
                      getPlatformDisplayList(
                        selectedInstallPlugin.support_platforms,
                      ).join(", ")
                    }}
                  </v-chip>
                  <v-alert
                    v-if="
                      selectedInstallPlugin.astrbot_version &&
                      installSupport.checked &&
                      !installSupport.supported
                    "
                    type="warning"
                    variant="tonal"
                    density="comfortable"
                    class="market-install-alert mt-2 mb-3"
                  >
                    {{ installSupport.message }}
                  </v-alert>
                </div>

                <div
                  v-if="selectedInstallSourceUrl"
                  class="market-install-confirm__section-title mt-4"
                >
                  {{ tm("dialogs.install.sectionTitle") }}
                </div>
                <div
                  v-if="selectedInstallSourceUrl"
                  class="market-install-source text-caption text-medium-emphasis mb-3"
                >
                  <div>{{ tm("dialogs.install.downloadSource") }}</div>
                  <div class="market-install-source__url">
                    {{ selectedInstallSourceUrl }}
                  </div>
                </div>

                <v-alert
                  v-if="installUsesGithubSource"
                  type="warning"
                  variant="tonal"
                  density="comfortable"
                  class="market-install-alert mb-4"
                >
                  {{ tm("dialogs.install.githubSecurityWarning") }}
                </v-alert>

                <ProxySelector
                  v-if="!selectedInstallDownloadUrl"
                ></ProxySelector>
              </div>
            </v-window-item>
          </v-window>
        </template>
      </div>

      <div class="v-card-actions">
        <v-spacer></v-spacer>
        <v-btn color="grey" variant="text" @click="closeInstallDialog">{{
          tm("buttons.cancel")
        }}</v-btn>
        <v-btn
          color="primary"
          variant="text"
          :loading="loading_"
          :disabled="loading_"
          @click="newExtension()"
          >{{ tm("buttons.install") }}</v-btn
        >
      </div>
    </div>
  </v-dialog>

  <!-- 插件源管理对话框 -->
  <v-dialog v-model="showSourceManagerDialog" width="640">
    <v-card>
      <v-card-title class="text-h3 pa-4 pl-6">{{
        tm("market.sourceManagement")
      }}</v-card-title>
      <v-card-text>
        <div class="d-flex align-center justify-space-between mb-2">
          <div class="text-subtitle-2">{{ tm("market.availableSources") }}</div>
          <v-btn
            size="small"
            color="primary"
            variant="tonal"
            prepend-icon="mdi-plus"
            @click="addCustomSource"
          >
            {{ tm("market.addSource") }}
          </v-btn>
        </div>

        <v-list density="compact" nav class="pa-0">
          <v-list-item
            rounded="md"
            color="primary"
            :active="selectedSource === null"
            @click="selectPluginSource(null)"
          >
            <template v-slot:prepend>
              <v-icon
                icon="mdi-shield-check"
                size="small"
                class="mr-2"
              ></v-icon>
            </template>
            <v-list-item-title>{{
              tm("market.defaultSource")
            }}</v-list-item-title>
          </v-list-item>

          <v-list-item
            v-for="source in customSources"
            :key="source.url"
            rounded="md"
            color="primary"
            :active="selectedSource === source.url"
            @click="selectPluginSource(source.url)"
          >
            <template v-slot:prepend>
              <v-icon
                icon="mdi-link-variant"
                size="small"
                class="mr-2"
              ></v-icon>
            </template>
            <v-list-item-title>{{ source.name }}</v-list-item-title>
            <v-list-item-subtitle class="text-caption">{{
              source.url
            }}</v-list-item-subtitle>
            <template v-slot:append>
              <v-btn
                icon="mdi-pencil-outline"
                size="small"
                variant="text"
                color="medium-emphasis"
                @click.stop="editCustomSource(source)"
              ></v-btn>
              <v-btn
                icon="mdi-trash-can-outline"
                size="small"
                variant="text"
                color="error"
                @click.stop="removeCustomSource(source)"
              ></v-btn>
            </template>
          </v-list-item>
        </v-list>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn
          color="primary"
          variant="text"
          @click="showSourceManagerDialog = false"
          >{{ tm("buttons.close") }}</v-btn
        >
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 添加/编辑自定义插件源对话框 -->
  <v-dialog v-model="showSourceDialog" width="500">
    <v-card>
      <v-card-title class="text-h5">{{
        editingSource ? tm("market.editSource") : tm("market.addSource")
      }}</v-card-title>
      <v-card-text>
        <div class="pa-2">
          <v-text-field
            v-model="sourceUrl"
            :label="tm('market.sourceUrl')"
            variant="outlined"
            prepend-inner-icon="mdi-link"
            hide-details
            placeholder="https://example.com/plugins.json"
          ></v-text-field>

          <div class="text-caption text-medium-emphasis mt-2">
            {{ tm("messages.enterJsonUrl") }}
          </div>

          <v-alert
            v-if="sourceResolveVisible && sourceResolveCurrent"
            type="success"
            variant="tonal"
            density="compact"
            class="mt-4"
          >
            <div class="text-body-2">{{ tm("market.sourceResolved") }}</div>
            <div
              v-if="sourceMarketMeta?.name || sourceMarketMeta?.version"
              class="text-caption mt-1"
            >
              <span v-if="sourceMarketMeta?.name">{{
                sourceMarketMeta.name
              }}</span>
              <span v-if="sourceMarketMeta?.version">
                v{{ sourceMarketMeta.version }}
              </span>
            </div>
          </v-alert>

          <v-text-field
            v-if="editingSource || sourceResolveCurrent"
            v-model="sourceName"
            :label="tm('market.sourceName')"
            variant="outlined"
            prepend-inner-icon="mdi-rename-box"
            hide-details
            class="mt-4"
            placeholder="我的插件源"
          ></v-text-field>
        </div>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="grey" variant="text" @click="showSourceDialog = false">{{
          tm("buttons.cancel")
        }}</v-btn>
        <v-btn
          color="primary"
          variant="text"
          :loading="sourceResolving"
          :disabled="
            sourceResolving || (!sourceResolveCurrent && !sourceUrl.trim())
          "
          @click="
            sourceResolveCurrent ? saveCustomSource() : resolveCustomSource()
          "
          >{{
            sourceResolveCurrent ? tm("buttons.save") : tm("buttons.next")
          }}</v-btn
        >
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 删除插件源确认对话框 -->
  <v-dialog v-model="showRemoveSourceDialog" width="400">
    <v-card>
      <v-card-title class="text-h5 d-flex align-center">
        <v-icon color="warning" class="mr-2">mdi-alert-circle</v-icon>
        {{ tm("dialogs.uninstall.title") }}
      </v-card-title>
      <v-card-text>
        <div>{{ tm("market.confirmRemoveSource") }}</div>
        <div v-if="sourceToRemove" class="mt-2">
          <strong>{{ sourceToRemove.name }}</strong>
          <div class="text-caption">{{ sourceToRemove.url }}</div>
        </div>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn
          color="grey"
          variant="text"
          @click="showRemoveSourceDialog = false"
          >{{ tm("buttons.cancel") }}</v-btn
        >
        <v-btn color="error" variant="text" @click="confirmRemoveSource">{{
          tm("buttons.deleteSource")
        }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- Update plugin confirmation dialog -->
  <v-dialog v-model="updateConfirmDialog.show" width="500">
    <v-card class="rounded-lg">
      <v-card-title class="text-h3 pa-4 pb-0 pl-6">
        {{ tm("dialogs.update.title") }}
      </v-card-title>
      <v-card-text>
        <div class="market-install-confirm">
          <div class="market-install-confirm__header">
            <img
              :src="updateDialogPluginLogo"
              :alt="updateDialogPluginName"
              class="market-install-confirm__logo"
            />
            <div class="market-install-confirm__meta">
              <div class="market-install-confirm__name">
                {{ updateDialogPluginName }}
              </div>
              <div
                v-if="updateDialogCurrentVersion || updateDialogTargetVersion"
                class="market-install-confirm__author"
              >
                <template v-if="updateDialogTargetVersion">
                  {{ updateDialogCurrentVersion || tm("status.unknown") }}
                  <v-icon icon="mdi-arrow-right" size="14" class="mx-1" />
                  {{ updateDialogTargetVersion }}
                </template>
                <template v-else>
                  {{ tm("detail.info.version") }}:
                  {{ updateDialogCurrentVersion || tm("status.unknown") }}
                </template>
              </div>
            </div>
          </div>

          <v-divider class="my-4" />

          <div
            v-if="selectedUpdateSourceUrl"
            class="market-install-confirm__section-title"
          >
            {{ tm("dialogs.update.sectionTitle") }}
          </div>
          <div
            v-if="selectedUpdateSourceUrl"
            class="market-install-source text-caption text-medium-emphasis mb-3"
          >
            <div>{{ tm("dialogs.update.downloadSource") }}</div>
            <div class="market-install-source__url">
              {{ selectedUpdateSourceUrl }}
            </div>
          </div>

          <v-alert
            v-if="updateUsesGithubSource"
            type="warning"
            variant="tonal"
            density="comfortable"
            class="market-install-alert mt-4 mb-4"
          >
            {{ tm("dialogs.install.githubSecurityWarning") }}
          </v-alert>

          <ProxySelector v-if="!selectedUpdateDownloadUrl" class="mt-4" />
        </div>
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn color="grey" variant="text" @click="closeUpdateConfirmDialog">
          {{ tm("buttons.cancel") }}
        </v-btn>
        <v-btn color="primary" variant="flat" @click="confirmUpdatePlugin">
          {{ tm("dialogs.update.confirm") }}
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>

  <!-- 强制更新确认对话框 -->
  <v-dialog v-model="forceUpdateDialog.show" max-width="420">
    <v-card class="rounded-lg">
      <v-card-title class="text-h6 d-flex align-center">
        <v-icon color="info" class="mr-2">mdi-information-outline</v-icon>
        {{ tm("dialogs.forceUpdate.title") }}
      </v-card-title>
      <v-card-text>
        {{ tm("dialogs.forceUpdate.message") }}
      </v-card-text>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn variant="text" @click="forceUpdateDialog.show = false">{{
          tm("buttons.cancel")
        }}</v-btn>
        <v-btn color="primary" variant="flat" @click="confirmForceUpdate">{{
          tm("dialogs.forceUpdate.confirm")
        }}</v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<style scoped>
.plugin-handler-item {
  margin-bottom: 10px;
  padding: 5px;
  border-radius: 5px;
  background-color: #f5f5f5;
}

.fab-button {
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.fab-button:hover {
  transform: translateY(-4px) scale(1.05);
  box-shadow: 0 12px 20px rgba(var(--v-theme-primary), 0.4);
}

.extension-detail-width {
  margin: 0 auto;
  max-width: 1040px;
  width: 100%;
}

.market-install-confirm {
  padding: 8px;
}

.market-install-confirm__header {
  align-items: center;
  display: flex;
  gap: 16px;
}

.market-install-confirm__logo {
  border-radius: 14px;
  height: 64px;
  object-fit: cover;
  width: 64px;
}

.market-install-confirm__meta {
  min-width: 0;
}

.market-install-confirm__name {
  color: rgba(var(--v-theme-on-surface), 0.92);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.market-install-confirm__author,
.market-install-confirm__desc {
  color: rgba(var(--v-theme-on-surface), 0.64);
  line-height: 1.55;
  font-size: 0.875rem;
}

.market-install-confirm__section-title {
  color: rgba(var(--v-theme-on-surface), 0.92);
  font-weight: 700;
  margin-bottom: 8px;
}

.market-install-alert {
  font-size: 0.8125rem;
  line-height: 1.45;
}

.market-install-source {
  min-width: 0;
}

.market-install-source__url {
  overflow-x: auto;
  white-space: nowrap;
}
</style>

<style>
.v-theme--PurpleThemeDark .extension-page .plugin-handler-item {
  background-color: rgb(var(--v-theme-mcpCardBg));
}
</style>
