<!-- One marketplace product card — handles per-kind options inline (faithful to shop mockups) -->
<template>
  <div class="card" :class="{ 'card--owned': ownedAlready }">
    <div v-if="product.badge" class="card-badge">{{ product.badge }}</div>

    <div class="card-head">
      <span class="card-icon">{{ icon }}</span>
      <div>
        <RouterLink :to="`/shop/p/${product.id}`" class="card-name">{{ product.name }}</RouterLink>
        <p v-if="product.subtitle" class="card-sub">{{ product.subtitle }}</p>
      </div>
    </div>

    <!-- Aperçu cosmétique : avant / après -->
    <div v-if="product.kind === 'ip-skin' || product.id === 'bundle-cosmetic'" class="preview">
      <span class="prev-ip prev-plain">192.168.1.45</span>
      <span class="prev-arrow">→</span>
      <span class="prev-ip prev-gold">192.168.1.45</span>
    </div>

    <!-- Options : abonnement NoAds -->
    <div v-if="product.kind === 'subscription'" class="opts">
      <label v-for="p in plans" :key="p.id" class="opt-radio" :class="{ active: plan === p.id }">
        <input type="radio" :value="p.id" v-model="plan" />
        <span>{{ p.label }}</span>
        <span class="opt-price">{{ fmt(p.price) }} cr{{ p.id === 'monthly' ? '/mois' : '/an' }}</span>
      </label>
    </div>

    <!-- Options : Cadre de Pub -->
    <div v-if="product.kind === 'ad-frame'" class="opts">
      <div class="opt-row">
        <span class="opt-label">Durée</span>
        <select v-model.number="durationDays" class="opt-select">
          <option v-for="d in durations" :key="d.days" :value="d.days">
            {{ d.days }} j{{ d.extra ? ` (+${fmt(d.extra)})` : '' }}
          </option>
        </select>
      </div>
      <div class="opt-row">
        <span class="opt-label">Format</span>
        <select v-model="format" class="opt-select">
          <option v-for="f in formats" :key="f.id" :value="f.id">
            {{ f.label }}{{ f.extra ? ` (+${fmt(f.extra)})` : '' }}
          </option>
        </select>
      </div>
      <input v-model="url" class="opt-input" type="text" placeholder="URL de destination (optionnel)" />
    </div>

    <!-- Options : Pet (grille des designs non encore possédés) -->
    <div v-if="product.kind === 'pet'" class="opts">
      <div class="pet-grid">
        <button
          v-for="d in availableDesigns"
          :key="d.id"
          class="pet-cell"
          :class="{ active: petDesign === d.id }"
          @click="petDesign = d.id"
          type="button"
        >{{ d.char }}</button>
      </div>
    </div>

    <!-- Preview : Skin de bouton -->
    <div v-if="product.kind === 'send-skin'" class="send-skin-preview">
      <div class="skin-btn-demo">{{ meta.char }}</div>
    </div>

    <!-- Stock limité -->
    <div v-if="product.stockLimit" class="stock">
      <div class="stock-bar"><div class="stock-fill" :style="{ width: stockPct + '%' }" /></div>
      <span class="stock-txt">{{ product.stockSold }} / {{ product.stockLimit }} vendus</span>
    </div>

    <!-- Prix + CTA -->
    <div class="card-foot">
      <div class="price">
        <span v-if="product.promoPrice != null" class="price-old">{{ fmt(product.basePrice) }}</span>
        <span class="price-now">{{ fmt(effectivePrice) }}</span>
        <span class="price-unit">cr</span>
      </div>
      <!-- Pets: bouton acheter + lien Mes Persos -->
      <template v-if="product.kind === 'pet'">
        <button
          class="buy"
          :disabled="disabled"
          @click="onBuy"
          type="button"
        >{{ buyLabel }}</button>
        <button
          class="buy buy--perso"
          @click="$emit('goPerso')"
          type="button"
        >✨ Mes Persos</button>
      </template>
      <button
        v-else
        class="buy"
        :disabled="disabled"
        @click="onBuy"
        type="button"
      >{{ buyLabel }}</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import type { Product, PurchaseOptions } from '@/composables/useShop';
import { parseMeta, type ProductMeta } from '@/composables/useMeta';

const props = defineProps<{
  product: Product;
  buying: boolean;
  owns: (kind: string) => boolean;
  ownedPetChars: string[];
  petCount: number;
  freeMode: boolean;
}>();

const emit = defineEmits<{
  buy: [productId: string, options: PurchaseOptions];
  goPerso: [];
}>();

const meta = computed(() => parseMeta<ProductMeta>(props.product.metaJson));

// Subscription
const plans = computed(() => meta.value.plans ?? []);
const plan = ref<'monthly' | 'annual'>('monthly');

// Ad-frame
const durations = computed(() => meta.value.durations ?? []);
const formats = computed(() => meta.value.formats ?? []);
const durationDays = ref<number>(7);
const format = ref<'static' | 'gif'>('static');
const url = ref('');

// Pet
const designs = computed(() => meta.value.designs ?? []);
const petDesign = ref<string>('');
const availableDesigns = computed(() =>
  designs.value.filter((d) => !props.ownedPetChars.includes(d.char))
);
watch(availableDesigns, (ds) => {
  if (ds.length > 0 && !ds.find((d) => d.id === petDesign.value)) {
    petDesign.value = ds[0].id;
  }
}, { immediate: true });

const icon = computed(() => {
  if (props.product.id === 'ip-colors') return '🎨';
  if (props.product.kind === 'send-skin') return meta.value.char ?? '🖱️';
  switch (props.product.kind) {
    case 'ad-frame': return '📣';
    case 'subscription': return '🚫';
    case 'ip-skin': return '👑';
    case 'pet': return '✨';
    case 'bundle': return '🎁';
    case 'rich': return props.product.id === 'rich-js' ? '⚡' : '🎨';
    case 'consumable': return '🔊';
    default: return '🛍️';
  }
});

const effectivePrice = computed(() => {
  let price = props.product.promoPrice ?? props.product.basePrice;
  if (props.product.kind === 'subscription') {
    const p = plans.value.find((x) => x.id === plan.value);
    if (p) price = p.price;
  }
  if (props.product.kind === 'ad-frame') {
    const d = durations.value.find((x) => x.days === durationDays.value);
    const f = formats.value.find((x) => x.id === format.value);
    price += (d?.extra ?? 0) + (f?.extra ?? 0);
  }
  return price;
});

// Ownership / limits → disable & label.
const ownedAlready = computed(() => {
  const k = props.product.kind;
  if (k === 'ip-skin') return props.owns('style-dore');
  if (k === 'subscription') return props.owns('noads');
  if (k === 'rich') return props.owns(props.product.id);
  if (k === 'unlock') return props.owns(props.product.id);
  if (k === 'ad-frame') return props.owns('ad-frame');
  if (k === 'send-skin') return props.owns(props.product.id);
  return false;
});

const soldOut = computed(() => props.product.stockLimit != null && props.product.stockSold >= props.product.stockLimit);

const disabled = computed(() => props.buying || ownedAlready.value || soldOut.value);

const buyLabel = computed(() => {
  if (props.buying) return '...';
  if (soldOut.value) return 'Épuisé';
  if (ownedAlready.value) return 'Possédé ✓';
  return props.freeMode ? 'Obtenir (gratuit)' : 'Acheter';
});

const stockPct = computed(() =>
  props.product.stockLimit ? Math.round((props.product.stockSold / props.product.stockLimit) * 100) : 0
);

function fmt(centi: number): string {
  return (centi / 100).toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

function onBuy(): void {
  const options: PurchaseOptions = {};
  if (props.product.kind === 'subscription') options.plan = plan.value;
  if (props.product.kind === 'ad-frame') {
    options.durationDays = durationDays.value;
    options.format = format.value;
    options.url = url.value || undefined;
  }
  if (props.product.kind === 'pet' || props.product.id === 'bundle-cosmetic') {
    const d = availableDesigns.value.find((x) => x.id === petDesign.value) ?? availableDesigns.value[0];
    if (d) { options.petDesign = d.id; options.petChar = d.char; }
  }
  emit('buy', props.product.id, options);
}
</script>

<style scoped>
.card {
  position: relative;
  background: #101018;
  border: 1px solid #20203a;
  border-radius: 10px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: Arial, sans-serif;
}
.card--owned { opacity: 0.7; }

.card-badge {
  position: absolute;
  top: -9px;
  right: 12px;
  background: #ff2266;
  color: #fff;
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 0.5px;
  padding: 3px 9px;
  border-radius: 8px;
  box-shadow: none;
}

.card-head { display: flex; gap: 12px; align-items: flex-start; }
.card-icon { font-size: 28px; }
.card-name { font-size: 15px; font-weight: bold; color: #d8d8ee; margin: 0; text-decoration: none; display: inline-block; }
.card-name:hover { color: #00ddff; }
.card-sub { font-size: 11px; color: #6a6a90; margin: 3px 0 0; line-height: 1.4; }

.preview {
  display: flex; align-items: center; gap: 10px;
  background: #0a0a12; border-radius: 6px; padding: 10px; justify-content: center;
}
.prev-ip { font-family: 'Courier New', monospace; font-size: 12px; font-weight: bold; }
.prev-plain { color: #666688; }
.prev-gold { color: #aa8833; }
.prev-arrow { color: #444466; }

.opts { display: flex; flex-direction: column; gap: 8px; }
.opt-radio {
  display: flex; align-items: center; gap: 8px;
  background: #0c0c16; border: 1px solid #20203a; border-radius: 6px;
  padding: 8px 10px; font-size: 12px; color: #aaaacc; cursor: pointer;
}
.opt-radio.active { border-color: #00aaff; background: #0a1622; }
.opt-radio input { accent-color: #00ccff; }
.opt-radio--sm { padding: 5px 8px; font-size: 11px; flex: 1; justify-content: center; }
.opt-price { margin-left: auto; color: #ffdd66; font-family: 'Courier New', monospace; }
.opt-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.opt-label { font-size: 11px; color: #8888aa; }
.opt-select, .opt-input {
  background: #0c0c16; border: 1px solid #20203a; border-radius: 6px;
  color: #ccccdd; font-size: 12px; padding: 6px 8px; outline: none;
}
.opt-select { flex: 1; }
.opt-input { width: 100%; }

.pet-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.pet-cell {
  aspect-ratio: 1; background: #0c0c16; border: 1px solid #20203a; border-radius: 6px;
  font-size: 18px; color: #ccccee; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.pet-cell.active { border-color: #8844aa; }
.pet-pos { display: flex; gap: 6px; }

.send-skin-preview { display: flex; justify-content: center; padding: 8px 0; }
.skin-btn-demo {
  width: 52px; height: 52px; border-radius: 50%;
  background: #151525; border: 1px solid #30306a;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px;
}

.stock { display: flex; flex-direction: column; gap: 4px; }
.stock-bar { height: 6px; background: #1a1a2a; border-radius: 3px; overflow: hidden; }
.stock-fill { height: 100%; background: linear-gradient(90deg, #ffaa00, #ff4444); }
.stock-txt { font-size: 10px; color: #886644; }

.card-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px; margin-top: auto; padding-top: 6px; }
.price { display: flex; align-items: baseline; gap: 6px; }
.price-old { font-size: 12px; color: #555; text-decoration: line-through; }
.price-now { font-size: 20px; font-weight: bold; color: #ccaa44; font-family: 'Courier New', monospace; }
.price-unit { font-size: 11px; color: #886633; }

.buy {
  background: #004488; border: 1px solid #0066aa; color: #00ddff;
  font-size: 13px; font-weight: bold; padding: 9px 18px; border-radius: 20px; cursor: pointer;
  transition: background 0.15s;
}
.buy:hover:not(:disabled) { background: #1a4466; }
.buy:disabled { opacity: 0.4; cursor: not-allowed; box-shadow: none; }

.buy--perso {
  background: #1a1030; border: 1px solid #8844cc; color: #cc88ff;
  font-size: 13px; font-weight: bold; padding: 9px 18px; border-radius: 20px; cursor: pointer;
  transition: background 0.15s;
}
.buy--perso:hover { background: #261844; }
</style>
