<script setup lang="ts">
import { ref, computed, onUnmounted, PropType } from 'vue'
import { __, sprintf } from '@wordpress/i18n'
import { Key, Mail, CheckCircle2, XCircle, Loader2 } from 'lucide-vue-next'
import { getI18n, safeUrl } from '@/helper'
import restApi from '@/api/restApi'
import type { LicenseTab } from './license.types'

const props = defineProps({
  tab: {
    type: Object as PropType<LicenseTab>,
    required: true,
  },
})

const accountEmail = ref(props.tab.accountEmail || '')
// Treat the license as active when the server flags it active AND actually
// hands over a (masked) key to display, OR when it was just saved this session.
// The key guard stops a stale `licenseIsActive` with no key from rendering the
// "active" state — disabled fields and a "Remove License" button — for a
// license that isn't really stored; `licenseSavedThisSession` covers the
// just-saved case, where no masked key is available client-side.
const hasStoredLicense = props.tab.licenseSavedThisSession === true ||
  (props.tab.licenseIsActive && Boolean((props.tab.licenseKey || '').trim()))
// Prefill the key only from a stored (masked) value supplied by PHP. `licenseKey`
// is contractually a masked/display value (see the `stwlite_license_tabs` filter
// docs) — the true key never crosses the PHP→JS boundary, and we never write the
// user-typed key back into it, so this only ever echoes the masked value. After
// a same-session save there is no masked key, so the disabled field stays empty.
const apiKey = ref(hasStoredLicense ? (props.tab.licenseKey || '') : '')
const isSaving = ref(false)
const licenseStatus = ref<'active' | 'inactive'>(hasStoredLicense ? 'active' : 'inactive')
// A mutable ref (not a computed): `handleRemove` resets it to `license_data` so
// the status message reflects the just-removed license, not the original state.
const licenseCheckType = ref(props.tab.checkType || 'license_data')

const notice = ref('')
const noticeType = ref<'success' | 'error'>('success')

// Route through the shared client so per-add-on saves honour the request
// throttle and consistent error interceptor. `restActionUrl` comes from the
// server-side filter, but scheme-guard it (as with the dashboard link) so an
// untrusted scheme is never used as the request base URL.
const client = restApi({ baseURL: safeUrl(props.tab.restActionUrl) || undefined })

// Guard the dashboard URL once so both the `v-if` and `:href` reuse it.
const dashboardUrl = computed(() => safeUrl(props.tab.accountDashboardUrl))

const statusHeading = computed(() =>
  sprintf(
    /* translators: %s: premium add-on product name */
    getI18n('license_status_for_product', __('%s — License Status', 'saveto-wishlist-lite-for-woocommerce')),
    props.tab.productName,
  ),
)

const statusMessage = computed(() => {
  if (licenseStatus.value === 'active') {
    return getI18n('license_active', __('Your license is active', 'saveto-wishlist-lite-for-woocommerce'))
  }
  if (licenseCheckType.value === 'license_status') {
    return getI18n('license_not_active_title', __('License Not Active', 'saveto-wishlist-lite-for-woocommerce'))
  }
  if (licenseCheckType.value === 'license_expiration') {
    return getI18n('license_expired_title', __('License Expired', 'saveto-wishlist-lite-for-woocommerce'))
  }
  return getI18n('license_not_provided_title', __('License Not Provided', 'saveto-wishlist-lite-for-woocommerce'))
})

let flashTimer: ReturnType<typeof setTimeout> | undefined

const flash = (message: string, type: 'success' | 'error') => {
  notice.value = message
  noticeType.value = type
  if (flashTimer) clearTimeout(flashTimer)
  flashTimer = setTimeout(() => { notice.value = '' }, 5000)
}

onUnmounted(() => {
  if (flashTimer) clearTimeout(flashTimer)
})

const handleSave = async () => {
  if (!accountEmail.value.trim()) {
    flash(getI18n('account_email_required', __('Account email is required.', 'saveto-wishlist-lite-for-woocommerce')), 'error')
    return
  }
  if (!apiKey.value.trim()) {
    flash(getI18n('license_key_required', __('License key is required.', 'saveto-wishlist-lite-for-woocommerce')), 'error')
    return
  }

  isSaving.value = true
  try {
    const { data } = await client.post('/save-license', {
      account_email: accountEmail.value.trim(),
      license_key: apiKey.value.trim(),
    })

    if (data && data.status === 'success') {
      flash(data.message || getI18n('license_saved', __('License saved successfully!', 'saveto-wishlist-lite-for-woocommerce')), 'success')
      licenseStatus.value = 'active'
      // Sync the shared tab object so the state survives a tab switch, which
      // remounts this component (License.vue keys it by tab id) and re-seeds
      // its refs from `props.tab`. Flag the save with a session-only boolean
      // rather than writing the user-typed key into `licenseKey`, keeping that
      // field's masked/display-only contract intact.
      props.tab.licenseIsActive = true
      props.tab.accountEmail = accountEmail.value.trim()
      props.tab.licenseSavedThisSession = true
    } else {
      flash(data?.message || getI18n('license_save_failed', __('Failed to save license. Please try again.', 'saveto-wishlist-lite-for-woocommerce')), 'error')
      licenseStatus.value = 'inactive'
    }
  } catch (error: unknown) {
    const message = (error as { error?: { message?: string } })?.error?.message
    flash(message || getI18n('license_save_failed', __('Failed to save license. Please try again.', 'saveto-wishlist-lite-for-woocommerce')), 'error')
    licenseStatus.value = 'inactive'
  } finally {
    isSaving.value = false
  }
}

const handleRemove = async () => {
  isSaving.value = true
  try {
    const { data } = await client.post('/remove-license', {})
    if (data && data.status === 'success') {
      flash(getI18n('license_removed', __('License removed successfully!', 'saveto-wishlist-lite-for-woocommerce')), 'success')
      accountEmail.value = ''
      apiKey.value = ''
      licenseStatus.value = 'inactive'
      licenseCheckType.value = 'license_data'
      // Sync the shared tab object so the removal survives a tab switch, which
      // remounts this component (License.vue keys it by tab id) and re-seeds
      // its refs from `props.tab`. Clear the session-saved flag; `licenseIsActive`
      // false already gates the re-seed, so we leave the masked `licenseKey`
      // (PHP's display value) untouched.
      props.tab.licenseIsActive = false
      props.tab.accountEmail = ''
      props.tab.licenseSavedThisSession = false
      props.tab.checkType = 'license_data'
    } else {
      flash(data?.message || getI18n('license_remove_failed', __('Failed to remove license. Please try again.', 'saveto-wishlist-lite-for-woocommerce')), 'error')
    }
  } catch (error: unknown) {
    const message = (error as { error?: { message?: string } })?.error?.message
    flash(message || getI18n('license_remove_failed', __('Failed to remove license. Please try again.', 'saveto-wishlist-lite-for-woocommerce')), 'error')
  } finally {
    isSaving.value = false
  }
}
</script>

<template>
  <div class="stwlite-tw-space-y-6">
    <!-- Status card -->
    <div class="stwlite-tw-bg-white stwlite-tw-rounded-lg stwlite-tw-shadow-sm stwlite-tw-border stwlite-tw-border-solid stwlite-tw-border-gray-200 stwlite-tw-p-6">
      <div class="stwlite-tw-flex stwlite-tw-items-center stwlite-tw-space-x-3">
        <CheckCircle2 v-if="licenseStatus === 'active'" aria-hidden="true" class="stwlite-tw-w-5 stwlite-tw-h-5 stwlite-tw-text-green-500" />
        <XCircle v-else aria-hidden="true" class="stwlite-tw-w-5 stwlite-tw-h-5 stwlite-tw-text-red-500" />
        <div>
          <h3 class="stwlite-tw-text-lg stwlite-tw-font-semibold stwlite-tw-text-gray-900 stwlite-tw-mb-0">
            {{ statusHeading }}
          </h3>
          <p class="stwlite-tw-text-sm stwlite-tw-text-gray-500 stwlite-tw-mt-0">{{ statusMessage }}</p>
        </div>
      </div>
    </div>

    <!-- Form -->
    <div class="stwlite-tw-bg-white stwlite-tw-rounded-lg stwlite-tw-shadow-sm stwlite-tw-border stwlite-tw-border-solid stwlite-tw-border-gray-200 stwlite-tw-p-6">
      <h2 class="stwlite-tw-text-xl stwlite-tw-font-semibold stwlite-tw-text-gray-900 stwlite-tw-mb-6 stwlite-tw-mt-0">
        {{ getI18n('license_information', __('License Information', 'saveto-wishlist-lite-for-woocommerce')) }}
      </h2>

      <div class="stwlite-tw-space-y-6">
        <div>
          <label :for="`stwlite-account-email-${tab.id}`" class="stwlite-tw-block stwlite-tw-text-sm stwlite-tw-font-medium stwlite-tw-text-gray-700 stwlite-tw-mb-2">
            <span class="stwlite-tw-inline-flex stwlite-tw-items-center stwlite-tw-space-x-2">
              <Mail aria-hidden="true" class="stwlite-tw-w-4 stwlite-tw-h-4" />
              <span>{{ getI18n('account_email', __('Account Email', 'saveto-wishlist-lite-for-woocommerce')) }}</span>
            </span>
          </label>
          <input
            :id="`stwlite-account-email-${tab.id}`"
            v-model="accountEmail"
            type="email"
            :placeholder="getI18n('account_email_placeholder', __('Enter your account email', 'saveto-wishlist-lite-for-woocommerce'))"
            class="stwlite-tw-mt-1 stwlite-tw-block stwlite-tw-w-full stwlite-tw-rounded-md stwlite-tw-border stwlite-tw-border-solid stwlite-tw-border-gray-300 stwlite-tw-shadow-sm stwlite-tw-px-4 stwlite-tw-py-2"
            :disabled="licenseStatus === 'active' || isSaving"
          >
          <p class="stwlite-tw-mt-2 stwlite-tw-text-sm stwlite-tw-text-gray-500">
            {{ getI18n('account_email_description', __('The email address associated with your SaveTo Wishlist account.', 'saveto-wishlist-lite-for-woocommerce')) }}
          </p>
        </div>

        <div>
          <label :for="`stwlite-license-key-${tab.id}`" class="stwlite-tw-block stwlite-tw-text-sm stwlite-tw-font-medium stwlite-tw-text-gray-700 stwlite-tw-mb-2">
            <span class="stwlite-tw-inline-flex stwlite-tw-items-center stwlite-tw-space-x-2">
              <Key aria-hidden="true" class="stwlite-tw-w-4 stwlite-tw-h-4" />
              <span>{{ getI18n('license_key', __('License Key', 'saveto-wishlist-lite-for-woocommerce')) }}</span>
            </span>
          </label>
          <input
            :id="`stwlite-license-key-${tab.id}`"
            v-model="apiKey"
            type="password"
            :placeholder="getI18n('license_key_placeholder', __('Enter your license key', 'saveto-wishlist-lite-for-woocommerce'))"
            class="stwlite-tw-mt-1 stwlite-tw-block stwlite-tw-w-full stwlite-tw-rounded-md stwlite-tw-border stwlite-tw-border-solid stwlite-tw-border-gray-300 stwlite-tw-shadow-sm stwlite-tw-px-4 stwlite-tw-py-2"
            :disabled="licenseStatus === 'active' || isSaving"
          >
          <p class="stwlite-tw-mt-2 stwlite-tw-text-sm stwlite-tw-text-gray-500">
            {{ getI18n('license_key_description', __('Your unique license key from your SaveTo Wishlist account dashboard.', 'saveto-wishlist-lite-for-woocommerce')) }}
          </p>
        </div>
      </div>

      <div class="stwlite-tw-mt-6 stwlite-tw-flex stwlite-tw-items-center stwlite-tw-justify-between">
        <p class="stwlite-tw-text-sm stwlite-tw-text-gray-500 stwlite-tw-m-0">
          {{ getI18n('license_help_text_prefix', __('You can find your license key in', 'saveto-wishlist-lite-for-woocommerce')) }}
          <a
            v-if="dashboardUrl"
            :href="dashboardUrl"
            target="_blank"
            rel="noopener noreferrer"
            class="stwlite-tw-text-blue-600 stwlite-tw-underline stwlite-tw-font-medium"
          >
            {{ getI18n('account_dashboard_link', __('your account dashboard', 'saveto-wishlist-lite-for-woocommerce')) }}
            <span class="stwlite-tw-sr-only">{{ getI18n('opens_in_new_tab', __('(opens in a new tab)', 'saveto-wishlist-lite-for-woocommerce')) }}</span>
          </a>
          <span v-else>{{ getI18n('account_dashboard_link', __('your account dashboard', 'saveto-wishlist-lite-for-woocommerce')) }}</span>.
        </p>
        <button
          type="button"
          :disabled="isSaving"
          class="stwlite-tw-inline-flex stwlite-tw-items-center stwlite-tw-px-6 stwlite-tw-py-2 stwlite-tw-rounded-lg stwlite-tw-font-semibold stwlite-tw-text-white stwlite-tw-border-0 stwlite-tw-cursor-pointer stwlite-tw-transition-colors"
          :class="licenseStatus === 'active'
            ? 'stwlite-tw-bg-red-600 hover:stwlite-tw-bg-red-700'
            : 'stwlite-tw-bg-blue-600 hover:stwlite-tw-bg-blue-700'"
          @click="licenseStatus === 'active' ? handleRemove() : handleSave()"
        >
          <Loader2
            v-if="isSaving"
            role="status"
            :aria-label="getI18n('saving', __('Saving…', 'saveto-wishlist-lite-for-woocommerce'))"
            class="stwlite-tw-w-4 stwlite-tw-h-4 stwlite-tw-mr-2 stwlite-tw-animate-spin"
          />
          {{ licenseStatus === 'active'
            ? getI18n('remove_license', __('Remove License', 'saveto-wishlist-lite-for-woocommerce'))
            : getI18n('save_license', __('Save License', 'saveto-wishlist-lite-for-woocommerce')) }}
        </button>
      </div>
    </div>

    <!-- Notice -->
    <div
      v-if="notice"
      aria-live="assertive"
      aria-atomic="true"
      :class="[
        'stwlite-tw-p-4 stwlite-tw-rounded-md stwlite-tw-text-sm stwlite-tw-border stwlite-tw-border-solid',
        noticeType === 'success'
          ? 'stwlite-tw-bg-green-50 stwlite-tw-border-green-200 stwlite-tw-text-green-800'
          : 'stwlite-tw-bg-red-50 stwlite-tw-border-red-200 stwlite-tw-text-red-800',
      ]"
    >
      {{ notice }}
    </div>
  </div>
</template>

<style scoped lang="scss">
input:disabled {
  background-color: #f3f4f6;
  cursor: not-allowed;
}
</style>
