<template>
  <section class="page-card">
    <div class="hero">
      <div>
        <h2>管理员后台</h2>
        <p class="tag">共 {{ products.length }} 件商品</p>
      </div>
      <div class="hero-actions">
        <button class="ghost" @click="refresh">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/></svg>
          刷新
        </button>
        <button class="primary" @click="openCreate">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
          添加商品
        </button>
      </div>
    </div>

    <div class="token-row" v-if="!token || message">
      <div class="form-field token-field">
        <label>管理 Token</label>
        <div class="token-input-wrap">
          <input v-model="token" placeholder="粘贴 token 后自动加载…" />
          <button class="ghost small" @click="autoGetToken">自动获取</button>
        </div>
      </div>
      <p class="msg-tag" :class="{ error: message.includes('失败') || message.includes('错误') }" v-if="message">{{ message }}</p>
    </div>
    <p v-if="message && token" class="msg-inline" :class="{ error: message.includes('失败') || message.includes('错误') }">{{ message }}</p>

    <div class="table-wrap">
      <table class="table">
        <thead>
          <tr>
            <th>商品</th>
            <th>价格</th>
            <th class="col-num">库存</th>
            <th class="col-num">浏览量</th>
            <th>状态</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in products" :key="item.id" :class="{ 'row-inactive': !item.active }">
            <td>
              <div class="admin-product-cell">
                <img class="admin-product-thumb" :src="item.coverUrl" :alt="item.name" />
                <div class="admin-product-info">
                  <span class="product-name">{{ item.name }}</span>
                  <span class="product-id">{{ item.id }}</span>
                </div>
              </div>
            </td>
            <td>
              <div v-if="item.price === 0" class="price-cell">
                <span class="price-free">免费</span>
              </div>
              <div
                v-else-if="item.discountPrice > 0 && item.discountPrice < item.price"
                class="price-cell"
              >
                <span class="price-original">¥{{ item.price.toFixed(2) }}</span>
                <span class="price-discount">¥{{ item.discountPrice.toFixed(2) }}</span>
              </div>
              <span v-else class="price-normal">¥{{ item.price.toFixed(2) }}</span>
            </td>
            <td class="col-num">
              <span :class="['stock-badge', item.quantity === 0 ? 'stock-empty' : 'stock-ok']">
                {{ item.quantity }}
              </span>
            </td>
            <td class="col-num">
              <span class="view-count">{{ item.viewCount || 0 }}</span>
            </td>
            <td>
              <span :class="['status-badge', item.active ? 'status-on' : 'status-off']">
                {{ item.active ? '上架' : '下架' }}
              </span>
            </td>
            <td>
              <div class="row-actions">
                <button class="act-edit" @click="openEdit(item)">编辑</button>
                <button class="act-toggle" @click="toggle(item)">
                  {{ item.active ? '下架' : '上架' }}
                </button>
                <button class="act-delete" @click="remove(item)">删除</button>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </section>

  <div v-if="editorOpen" class="modal-mask" @click.self="closeEditor">
    <section class="modal-card">
      <div class="modal-header">
        <div>
          <h3>{{ form.id ? '编辑商品' : '添加新商品' }}</h3>
          <p class="tag">封面图和最多 5 张商品截图共用这一套编辑表单。</p>
        </div>
        <button class="ghost" @click="closeEditor">关闭</button>
      </div>

      <div class="modal-body">
        <div class="form-field">
          <label>商品名称</label>
          <input v-model="form.name" placeholder="商品名称" />
        </div>
        <div class="form-row">
          <div class="form-field">
            <label>原价（元）</label>
            <input v-model.number="form.price" type="number" step="0.01" />
          </div>
          <div class="form-field">
            <label>折扣价（元，可选）</label>
            <input v-model.number="form.discountPrice" type="number" step="0.01" />
            <p class="tag">留空或不小于原价时，将不启用折扣。</p>
          </div>
        </div>
        <div class="form-field">
          <label>封面链接（http）</label>
          <input v-model="form.coverUrl" placeholder="http://..." />
        </div>
        <div class="form-field">
          <div class="field-head">
            <label>商品库存</label>
            <span class="tag">共 {{ form.inventoryItems.length }} 条</span>
            <button class="ghost small" type="button" @click="addInventoryItem">添加商品库存</button>
          </div>
          <p class="tag">每个输入框保存一条可发放内容，购买后会直接展示给用户。</p>
          <div class="inventory-list">
            <div v-for="(item, index) in form.inventoryItems" :key="index" class="inventory-row">
              <input
                :ref="(el) => setInventoryInputRef(el, index)"
                v-model="form.inventoryItems[index]"
                placeholder="库存内容，可填卡密、下载链接等"
              />
              <button
                v-if="form.inventoryItems.length > 1"
                class="ghost small"
                type="button"
                @click="removeInventoryItem(index)"
              >
                删除
              </button>
            </div>
          </div>
        </div>
        <div class="form-field">
          <label>商品截图链接（最多 5 个）</label>
          <div class="screenshot-grid">
            <input
              v-for="(_, index) in screenshotInputSlots"
              :key="index"
              v-model="form.screenshotUrls[index]"
              :placeholder="`截图链接 ${index + 1}（http://...）`"
            />
          </div>
        </div>
        <div class="form-field">
          <label>商品介绍（Markdown）</label>
          <textarea v-model="form.description"></textarea>
        </div>
        <div class="form-field">
          <label>商品标签（英文逗号分隔）</label>
          <input v-model="form.tagsText" placeholder="例如: chatgpt, linux, 域名" />
          <p class="tag">用于前端搜索与筛选，多个标签用英文逗号分开</p>
        </div>
        <div class="form-field">
          <label>是否上架</label>
          <select v-model="form.active">
            <option :value="true">上架</option>
            <option :value="false">下架</option>
          </select>
        </div>
      </div>

      <div class="modal-actions">
        <button class="primary" @click="submit">{{ form.id ? '更新商品' : '新增商品' }}</button>
        <button class="ghost" @click="reset">重置表单</button>
      </div>
    </section>
  </div>
</template>

<script setup>
import { nextTick, onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import {
  fetchAdminProducts,
  fetchAdminToken,
  createProduct,
  updateProduct,
  toggleProduct,
  deleteProduct
} from '../shared/api'

const route = useRoute()
const router = useRouter()
const token = ref(route.query.token || '')
const products = ref([])
const message = ref('')
const editorOpen = ref(false)
const inventoryInputRefs = ref([])
const MAX_SCREENSHOT_URLS = 5
const screenshotInputSlots = Array.from({ length: MAX_SCREENSHOT_URLS })
const MAX_INVENTORY_ITEMS = 500

const createScreenshotSlots = (values = []) =>
  Array.from({ length: MAX_SCREENSHOT_URLS }, (_, index) => values[index] || '')

const createInventoryItems = (values = []) => {
  const items = values
    .map((value) => (value || '').trim())
    .filter((value) => value)
    .slice(0, MAX_INVENTORY_ITEMS)
  return items.length ? items : ['']
}

const normalizeInventoryItems = (values = []) =>
  values
    .map((item) => (item || '').trim())
    .filter((item) => item)
    .slice(0, MAX_INVENTORY_ITEMS)

const normalizeScreenshotUrls = (values = []) =>
  values.map((item) => item.trim()).filter(Boolean).slice(0, MAX_SCREENSHOT_URLS)

const emptyForm = () => ({
  id: '',
  name: '',
  price: 0,
  discountPrice: 0,
  tagsText: '',
  coverUrl: '',
  screenshotUrls: createScreenshotSlots(),
  inventoryItems: createInventoryItems(),
  description: '',
  active: true
})

const form = reactive(emptyForm())

const syncQuery = () => {
  if (token.value) {
    router.replace({ query: { token: token.value } })
  }
}

const refresh = async () => {
  if (!token.value) {
    message.value = '请先输入 token'
    return
  }
  try {
    products.value = await fetchAdminProducts(token.value)
    message.value = '数据已更新'
  } catch (error) {
    message.value = '获取失败，请检查 token'
  }
}

const autoGetToken = async () => {
  const fetched = await fetchAdminToken()
  token.value = fetched
  syncQuery()
  await refresh()
}

const submit = async () => {
  if (!token.value) {
    message.value = '请先输入 token'
    return
  }
  try {
    if (form.id) {
      await updateProduct(token.value, form.id, {
        name: form.name,
        price: form.price,
        discountPrice: form.discountPrice || 0,
        tags: form.tagsText,
        coverUrl: form.coverUrl,
        codes: normalizeInventoryItems(form.inventoryItems),
        screenshotUrls: normalizeScreenshotUrls(form.screenshotUrls),
        description: form.description,
        active: form.active
      })
      message.value = '已更新商品'
    } else {
      await createProduct(token.value, {
        name: form.name,
        price: form.price,
        discountPrice: form.discountPrice || 0,
        tags: form.tagsText,
        coverUrl: form.coverUrl,
        codes: normalizeInventoryItems(form.inventoryItems),
        screenshotUrls: normalizeScreenshotUrls(form.screenshotUrls),
        description: form.description,
        active: form.active
      })
      message.value = '已新增商品'
    }
    reset()
    closeEditor()
    await refresh()
  } catch (error) {
    message.value = '操作失败，请检查输入'
  }
}

const fillForm = (item) => {
  Object.assign(form, {
    id: item?.id || '',
    name: item?.name || '',
    price: item?.price || 0,
    discountPrice: item?.discountPrice || 0,
    tagsText: (item?.tags || []).join(','),
    coverUrl: item?.coverUrl || '',
    screenshotUrls: createScreenshotSlots(item?.screenshotUrls || []),
    inventoryItems: createInventoryItems(item?.codes || []),
    description: item?.description || '',
    active: item?.active ?? true
  })
}

const openCreate = () => {
  reset()
  editorOpen.value = true
}

const openEdit = (item) => {
  fillForm(item)
  editorOpen.value = true
}

const closeEditor = () => {
  editorOpen.value = false
}

const setInventoryInputRef = (el, index) => {
  if (!el) {
    return
  }
  inventoryInputRefs.value[index] = el
}

const addInventoryItem = async () => {
  form.inventoryItems.push('')
  await nextTick()
  const lastIndex = form.inventoryItems.length - 1
  const input = inventoryInputRefs.value[lastIndex]
  if (input?.focus) {
    input.focus()
  }
  if (input?.scrollIntoView) {
    input.scrollIntoView({ block: 'center', behavior: 'smooth' })
  }
}

const removeInventoryItem = async (index) => {
  if (form.inventoryItems.length <= 1) {
    form.inventoryItems[0] = ''
    return
  }
  form.inventoryItems.splice(index, 1)
  inventoryInputRefs.value.splice(index, 1)
  await nextTick()
  const targetIndex = Math.min(index, form.inventoryItems.length - 1)
  const input = inventoryInputRefs.value[targetIndex]
  if (input?.focus) {
    input.focus()
  }
}

const toggle = async (item) => {
  if (!token.value) {
    message.value = '请先输入 token'
    return
  }
  await toggleProduct(token.value, item.id, !item.active)
  await refresh()
}

const remove = async (item) => {
  if (!token.value) {
    message.value = '请先输入 token'
    return
  }
  await deleteProduct(token.value, item.id)
  await refresh()
}

const reset = () => {
  fillForm()
}

watch(token, () => {
  syncQuery()
})

onMounted(async () => {
  if (token.value) {
    await refresh()
  }
})
</script>

<style scoped>
/* ── Header ── */
.hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}

.hero-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

.hero-actions button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
}

/* ── Token row ── */
.token-row {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  margin-bottom: 16px;
  padding: 16px 18px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.token-field {
  flex: 1;
  max-width: 460px;
  margin-bottom: 0;
}

.token-input-wrap {
  display: flex;
  gap: 8px;
  align-items: center;
}

.token-input-wrap input {
  flex: 1;
}

.msg-tag {
  font-size: 13px;
  color: var(--accent-2);
  padding: 4px 10px;
  border-radius: 8px;
  background: rgba(145, 168, 208, 0.1);
  white-space: nowrap;
}

.msg-inline {
  font-size: 13px;
  color: var(--accent-2);
  margin-bottom: 12px;
}

.msg-tag.error,
.msg-inline.error {
  color: #c95a6a;
  background: rgba(201, 90, 106, 0.08);
}

/* ── Table ── */
.table-wrap {
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--line);
}

.table {
  width: 100%;
  border-collapse: collapse;
  background: rgba(255, 255, 255, 0.45);
}

.table thead tr {
  background: rgba(255, 255, 255, 0.7);
  border-bottom: 2px solid var(--line);
}

.table th {
  padding: 12px 16px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
}

.table td {
  padding: 14px 16px;
  font-size: 14px;
  vertical-align: middle;
}

.table tbody tr {
  border-bottom: 1px solid var(--line);
  transition: background 0.15s ease;
}

.table tbody tr:last-child {
  border-bottom: none;
}

.table tbody tr:hover {
  background: rgba(255, 255, 255, 0.7);
}

.table tbody tr.row-inactive {
  opacity: 0.55;
}

.col-num {
  text-align: center;
}

/* ── Product cell ── */
.admin-product-cell {
  display: flex;
  align-items: center;
  gap: 12px;
}

.admin-product-thumb {
  width: 48px;
  height: 48px;
  border-radius: 10px;
  object-fit: cover;
  border: 1px solid var(--line);
  flex-shrink: 0;
  box-shadow: 0 4px 10px rgba(33, 33, 40, 0.1);
}

.admin-product-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.product-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.product-id {
  font-size: 11px;
  color: var(--muted);
  font-family: monospace;
}

/* ── Price ── */
.price-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.price-original {
  text-decoration: line-through;
  color: var(--muted);
  font-size: 12px;
}

.price-discount {
  font-weight: 700;
  color: #e8826a;
  font-size: 15px;
}

.price-free {
  font-weight: 900;
  color: #3a9a68;
  font-size: 15px;
}

.price-normal {
  font-weight: 600;
  color: var(--text);
}

/* ── Stock badge ── */
.stock-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
}

.stock-ok {
  background: rgba(100, 185, 140, 0.15);
  color: #3a9a68;
}

.stock-empty {
  background: rgba(201, 90, 106, 0.12);
  color: #c95a6a;
}

/* ── View count ── */
.view-count {
  color: var(--muted);
  font-size: 13px;
}

/* ── Status badge ── */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
}

.status-on {
  background: rgba(100, 185, 140, 0.15);
  color: #3a9a68;
}

.status-off {
  background: rgba(140, 140, 145, 0.12);
  color: var(--muted);
}

/* ── Row action buttons ── */
.row-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}

.act-edit,
.act-toggle,
.act-delete {
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: opacity 0.15s ease, transform 0.15s ease;
  font-family: 'Source Sans 3', sans-serif;
}

.act-edit {
  background: rgba(145, 168, 208, 0.15);
  color: var(--accent-2);
}

.act-edit:hover {
  background: rgba(145, 168, 208, 0.28);
}

.act-toggle {
  background: rgba(180, 154, 203, 0.12);
  color: var(--accent);
}

.act-toggle:hover {
  background: rgba(180, 154, 203, 0.24);
}

.act-delete {
  background: rgba(201, 90, 106, 0.1);
  color: #c95a6a;
}

.act-delete:hover {
  background: rgba(201, 90, 106, 0.2);
}

/* ── Form / Modal ── */
select {
  border-radius: 14px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.7);
  padding: 10px 12px;
  font-family: 'Source Sans 3', sans-serif;
  font-size: 14px;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.field-head {
  display: flex;
  align-items: center;
  gap: 12px;
}

.small {
  padding: 7px 13px;
  font-size: 13px;
  border-radius: 999px;
}

.inventory-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.inventory-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.inventory-row input {
  flex: 1;
}

.screenshot-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* ── Modal ── */
.modal-mask {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(30, 28, 32, 0.35);
  backdrop-filter: blur(8px);
}

.modal-card {
  width: min(920px, 100%);
  max-height: calc(100vh - 48px);
  overflow: auto;
  padding: 28px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.95);
  border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(33, 33, 40, 0.2);
}

.modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 22px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.modal-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

/* ── Responsive ── */
@media (max-width: 900px) {
  .hero,
  .modal-header {
    flex-direction: column;
    align-items: stretch;
  }

  .token-row {
    flex-direction: column;
    align-items: stretch;
  }

  .token-input-wrap {
    flex-direction: column;
  }

  .form-row,
  .screenshot-grid {
    grid-template-columns: 1fr;
  }

  .field-head {
    flex-wrap: wrap;
  }

  .inventory-row {
    flex-direction: column;
    align-items: stretch;
  }

  .modal-mask {
    padding: 12px;
  }

  .modal-card {
    padding: 18px;
    max-height: calc(100vh - 24px);
  }

  .row-actions {
    flex-direction: column;
    gap: 4px;
  }
}
</style>
