<template>
  <v-card class="fc-ext-card">
    <CardHeading icon="mdi-puzzle" title="Browser extension">
      <span v-if="manifest?.installed" class="text-caption fc-muted">
        · Firefox · v{{ manifest.version }}
      </span>
      <!-- Which channel this instance serves, so it is visible without
           installing anything. Rendered only when the image declares one: a
           locally-built image, or one predating the field, says nothing rather
           than guessing. Never merged into the version string beside it — see
           the endpoint's note on why a `-dev` suffix breaks the comparator. -->
      <v-chip
        v-if="manifest?.channel"
        size="x-small" variant="tonal" class="ml-2"
        :color="manifest.channel === 'dev' ? 'warning' : 'info'"
      >{{ manifest.channel }}</v-chip>
    </CardHeading>

    <v-card-text>
      <p class="fc-muted text-body-2">
        Pushes session cookies from supported platforms
        (patreon, subscribestar, hentaifoundry, discord, pixiv)
        into FabledCurator, and lets you add a creator as a source from
        their page in one click.
      </p>

      <v-alert
        v-if="manifestError"
        type="warning" variant="tonal" density="compact" class="mt-3"
      >
        Could not load extension manifest: {{ manifestError }}
      </v-alert>

      <v-alert
        v-else-if="manifest && !manifest.installed"
        type="warning" variant="tonal" density="compact" class="mt-3"
      >
        No bundled extension found in this image. Push a release that
        runs the extension CI workflow, or grab the XPI from the
        FabledCurator Forgejo releases page.
      </v-alert>

      <template v-else-if="manifest?.installed">
        <div class="fc-ext-install mt-3">
          <!-- Install button: direct :href anchor click (no programmatic
               window.location.assign). Firefox's XPI-install gesture
               requires a user-clicked anchor pointing at an
               application/x-xpinstall response; programmatic navigation
               sometimes triggered nothing instead of the install dialog
               (operator-flagged 2026-05-26). No `download` attribute —
               that would force a save dialog instead of install. -->
          <v-btn
            v-if="isFirefox"
            color="accent" variant="flat" rounded="pill"
            prepend-icon="mdi-firefox"
            :href="manifest.latest_url"
          >Install Firefox extension</v-btn>

          <v-btn
            variant="outlined" rounded="pill"
            :href="manifest.latest_url" download
            prepend-icon="mdi-download"
          >Download XPI</v-btn>

          <v-alert
            v-if="!isFirefox"
            type="info" variant="tonal" density="compact" class="mt-3"
          >
            Open this page in Firefox to install in one click, or use
            "Download XPI" to install manually.
          </v-alert>
        </div>

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

        <div class="fc-muted text-body-2 mb-3">
          After installing, open the extension's options page
          (about:addons → FabledCurator → Preferences) and paste these:
        </div>

        <v-text-field
          label="FC base URL" :model-value="apiUrl"
          readonly density="compact" hide-details
          append-inner-icon="mdi-content-copy"
          @click:append-inner="copy(apiUrl, 'URL')"
        />

        <v-text-field
          label="Extension API key"
          :model-value="apiKey"
          :type="keyShown ? 'text' : 'password'"
          readonly density="compact" hide-details class="mt-3"
        >
          <template #append-inner>
            <v-btn
              variant="text" density="compact" size="small"
              :icon="keyShown ? 'mdi-eye-off' : 'mdi-eye'"
              @click="keyShown = !keyShown"
            />
            <v-btn
              variant="text" density="compact" size="small"
              icon="mdi-content-copy"
              @click="copy(apiKey, 'API key')"
            />
            <v-btn
              variant="text" density="compact" size="small"
              icon="mdi-refresh" color="warning"
              :loading="rotating"
              @click="rotateKey"
            />
          </template>
        </v-text-field>
      </template>
    </v-card-text>
  </v-card>
</template>

<script setup>
import { toast } from '../../utils/toast.js'
import { computed, onMounted, ref } from 'vue'
import { useApi } from '../../composables/useApi.js'
import { copyText } from '../../utils/clipboard.js'
import CardHeading from '../common/CardHeading.vue'

const api = useApi()

const manifest = ref(null)
const manifestError = ref(null)
const apiKey = ref('')
const keyShown = ref(false)
const rotating = ref(false)

const apiUrl = computed(() => `${window.location.origin}/api`)
const isFirefox = computed(() => navigator.userAgent.includes('Firefox'))

onMounted(async () => {
  await Promise.all([loadManifest(), loadKey()])
})

async function loadManifest() {
  try {
    manifest.value = await api.get('/api/extension/manifest')
  } catch (e) {
    if (e.status === 404) {
      // Backend says no XPI is bundled — surface the not-installed
      // state, not an error.
      manifest.value = { installed: false }
    } else {
      manifestError.value = e.message
    }
  }
}

async function loadKey() {
  try {
    const { key } = await api.get('/api/settings/extension_api_key')
    apiKey.value = key
  } catch (e) {
    apiKey.value = ''
    toast({
      text: `Failed to load extension API key: ${e.message}`,
      type: 'error',
    })
  }
}

async function rotateKey() {
  rotating.value = true
  try {
    const { key } = await api.post('/api/settings/extension_api_key/rotate')
    apiKey.value = key
    keyShown.value = true
    toast({ text: 'Extension API key rotated.', type: 'success' })
  } catch (e) {
    toast({
      text: `Rotate failed: ${e.message}`,
      type: 'error',
    })
  } finally {
    rotating.value = false
  }
}

async function copy(text, label) {
  try {
    await copyText(text)
    toast({ text: `${label} copied.`, type: 'success' })
  } catch (e) {
    toast({ text: `Copy failed: ${e.message}`, type: 'error' })
  }
}
</script>

<style scoped>
.fc-ext-card { border-radius: 8px; }
.fc-ext-install {
  display: flex; flex-wrap: wrap; gap: 8px;
}
</style>
