<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import api from '../api';
import { useAdminLocale } from '../composables/useAdminLocale';
import MatchesSubNav from '../components/MatchesSubNav.vue';

const { t, locale } = useAdminLocale();

const LOCALES = [
  { code: 'zh-CN', label: '中文' },
  { code: 'en-US', label: 'English' },
  { code: 'ms-MY', label: 'Bahasa Melayu' },
] as const;

const UI_TEXT: Record<string, Record<string, string>> = {
  add: { 'zh-CN': '添加', 'en-US': 'Add', 'ms-MY': 'Tambah' },
  addMarket: { 'zh-CN': '增加盘口', 'en-US': 'Add market', 'ms-MY': 'Tambah pasaran' },
  close: { 'zh-CN': '关闭', 'en-US': 'Close', 'ms-MY': 'Tutup' },
  copyCreated: { 'zh-CN': '已复制盘口线', 'en-US': 'Market line duplicated', 'ms-MY': 'Garisan pasaran disalin' },
  copyMarket: { 'zh-CN': '复制盘口', 'en-US': 'Duplicate market', 'ms-MY': 'Salin pasaran' },
  copyMarketCreated: { 'zh-CN': '已复制盘口', 'en-US': 'Market duplicated', 'ms-MY': 'Pasaran disalin' },
  copyMarketShort: { 'zh-CN': '复制盘口', 'en-US': 'Duplicate', 'ms-MY': 'Salin pasaran' },
  copyLine: { 'zh-CN': '复制盘口线', 'en-US': 'Duplicate line', 'ms-MY': 'Salin garisan' },
  copyLineShort: { 'zh-CN': '复制线', 'en-US': 'Copy', 'ms-MY': 'Salin' },
  createTemplate: { 'zh-CN': '新建模板', 'en-US': 'New template', 'ms-MY': 'Templat baharu' },
  defaultTemplate: { 'zh-CN': '默认', 'en-US': 'Default', 'ms-MY': 'Lalai' },
  duplicateTemplate: { 'zh-CN': '复制模板', 'en-US': 'Duplicate template', 'ms-MY': 'Salin templat' },
  hidden: { 'zh-CN': '玩家端隐藏', 'en-US': 'Hidden on player', 'ms-MY': 'Disembunyikan pemain' },
  lineValue: { 'zh-CN': '盘口线', 'en-US': 'Line', 'ms-MY': 'Garisan' },
  marketDetails: { 'zh-CN': '模板详情', 'en-US': 'Template details', 'ms-MY': 'Butiran templat' },
  marketName: { 'zh-CN': '盘口名称', 'en-US': 'Market name', 'ms-MY': 'Nama pasaran' },
  marketToAdd: { 'zh-CN': '选择要添加的盘口', 'en-US': 'Choose a market to add', 'ms-MY': 'Pilih pasaran untuk ditambah' },
  marketUnavailable: { 'zh-CN': '暂不开放玩家端', 'en-US': 'Not available on player', 'ms-MY': 'Belum tersedia untuk pemain' },
  moveDown: { 'zh-CN': '下移', 'en-US': 'Move down', 'ms-MY': 'Turun' },
  moveUp: { 'zh-CN': '上移', 'en-US': 'Move up', 'ms-MY': 'Naik' },
  odds: { 'zh-CN': '赔率', 'en-US': 'Odds', 'ms-MY': 'Odds' },
  parlay: { 'zh-CN': '串关', 'en-US': 'Parlay', 'ms-MY': 'Parlay' },
  playerVisible: { 'zh-CN': '玩家端显示', 'en-US': 'Show on player', 'ms-MY': 'Papar pemain' },
  promoLabel: { 'zh-CN': '促销标签', 'en-US': 'Promo label', 'ms-MY': 'Label promosi' },
  remove: { 'zh-CN': '移除', 'en-US': 'Remove', 'ms-MY': 'Buang' },
  selectMarket: { 'zh-CN': '从盘口池选择', 'en-US': 'Select from market pool', 'ms-MY': 'Pilih daripada kumpulan pasaran' },
  selectTemplate: { 'zh-CN': '选择模板', 'en-US': 'Select template', 'ms-MY': 'Pilih templat' },
  setDefault: { 'zh-CN': '设为默认', 'en-US': 'Set default', 'ms-MY': 'Jadikan lalai' },
  single: { 'zh-CN': '单关', 'en-US': 'Single', 'ms-MY': 'Tunggal' },
  status: { 'zh-CN': '状态', 'en-US': 'Status', 'ms-MY': 'Status' },
  statusClosed: { 'zh-CN': '已关闭', 'en-US': 'Closed', 'ms-MY': 'Ditutup' },
  statusOpen: { 'zh-CN': '可售', 'en-US': 'Open', 'ms-MY': 'Dibuka' },
  statusSuspended: { 'zh-CN': '暂停', 'en-US': 'Suspended', 'ms-MY': 'Digantung' },
  templateDefaultSet: { 'zh-CN': '已设为默认模板', 'en-US': 'Default template updated', 'ms-MY': 'Templat lalai dikemas kini' },
  templateMarkets: { 'zh-CN': '模板盘口', 'en-US': 'Template markets', 'ms-MY': 'Pasaran templat' },
  templateName: { 'zh-CN': '模板名称', 'en-US': 'Template name', 'ms-MY': 'Nama templat' },
};

type LocalizedText = Record<string, string>;

interface MarketDefinition {
  marketType: string;
  marketKey: string;
  period: string;
  sortOrder: number;
  defaultLineValue: number | null;
  allowSingle: boolean;
  allowParlay: boolean;
  showOnPlayer: boolean;
  settlementSupported: boolean;
  usesLineValue: boolean;
  nameI18n: LocalizedText;
  selectionTemplate: Array<{ code: string; name: string; nameI18n: LocalizedText; odds: number }>;
}

interface SelectionRow {
  id?: string;
  selectionCode: string;
  selectionName: string;
  nameI18n: LocalizedText;
  odds: number;
  status: string;
  sortOrder: number;
}

interface MarketRow {
  id?: string;
  marketType: string;
  marketKey: string;
  period: string;
  lineValue: number | null;
  paramsJson: Record<string, unknown> | null;
  status: string;
  allowSingle: boolean;
  allowParlay: boolean;
  showOnPlayer: boolean;
  sortOrder: number;
  promoLabelI18n: LocalizedText;
  nameI18n: LocalizedText;
  selections: SelectionRow[];
}

interface MarketTemplate {
  id: string;
  name: string;
  nameI18n: LocalizedText;
  isDefault: boolean;
  status: string;
  sortOrder: number;
  items: MarketRow[];
}

const loading = ref(false);
const saving = ref(false);
const definitions = ref<MarketDefinition[]>([]);
const templates = ref<MarketTemplate[]>([]);
const selectedId = ref('');
const selectedIndex = ref(0);
const addMarketVisible = ref(false);
const selectedDefinitionType = ref('');
const current = computed(() => templates.value.find((tpl) => tpl.id === selectedId.value) ?? null);
const selectedItem = computed(() => current.value?.items[selectedIndex.value] ?? null);
const definitionMap = computed(() => new Map(definitions.value.map((d) => [d.marketType, d])));
const definitionOptions = computed(() => [...definitions.value].sort((a, b) => a.sortOrder - b.sortOrder));
const displayLocales = computed(() => {
  const zhLabels: Record<string, string> = {
    'zh-CN': '中文',
    'en-US': '英语',
    'ms-MY': '马来语',
  };
  return LOCALES.map((loc) => ({
    code: loc.code,
    label: locale.value === 'zh-CN' ? zhLabels[loc.code] : loc.label,
  }));
});

function localized(input?: Record<string, string> | null, fallback = ''): LocalizedText {
  const out: LocalizedText = {};
  for (const loc of LOCALES) out[loc.code] = input?.[loc.code]?.trim() || '';
  if (fallback && !out['zh-CN']) out['zh-CN'] = fallback;
  return out;
}

function resolveText(map?: LocalizedText | null, fallback = '') {
  const order = Array.from(new Set([locale.value, 'en-US', 'zh-CN', 'ms-MY']));
  for (const loc of order) {
    const value = map?.[loc]?.trim();
    if (value) return value;
  }
  return Object.values(map ?? {}).find((value) => value?.trim()) || fallback;
}

function ui(key: string) {
  return resolveText(UI_TEXT[key], key);
}

function statusLabel(status: string) {
  if (status === 'OPEN') return ui('statusOpen');
  if (status === 'SUSPENDED') return ui('statusSuspended');
  if (status === 'CLOSED') return ui('statusClosed');
  return status;
}

function selectionTitle(selection: SelectionRow) {
  const score = /^SCORE_(\d+)_(\d+)$/.exec(selection.selectionCode);
  if (score) return `${score[1]}:${score[2]}`;
  return resolveText(selection.nameI18n, selection.selectionName || selection.selectionCode);
}

function isScoreSelection(selection: SelectionRow) {
  return /^SCORE_\d+_\d+$/.test(selection.selectionCode);
}

function marketTitle(market: MarketRow) {
  const line = isLineMarket(market) && market.lineValue != null ? ` ${market.lineValue}` : '';
  return `${resolveText(market.nameI18n, market.marketType)}${line}`;
}

function marketMetaText(market: MarketRow) {
  const parts = [statusLabel(market.status)];
  if (isLineMarket(market) && market.lineValue != null) parts.push(`${ui('lineValue')} ${market.lineValue}`);
  if (!market.showOnPlayer) parts.push(ui('hidden'));
  return parts.join(' · ');
}

function definitionLabel(def: MarketDefinition) {
  const label = resolveText(def.nameI18n, def.marketType);
  return def.settlementSupported ? label : `${label}（${ui('marketUnavailable')}）`;
}

function templateLabel(tpl: MarketTemplate) {
  const label = resolveText(tpl.nameI18n, tpl.name || '');
  return tpl.isDefault ? `${label}（${ui('defaultTemplate')}）` : label;
}

function mapItem(raw: MarketRow, index: number): MarketRow {
  return {
    id: raw.id,
    marketType: raw.marketType,
    marketKey: raw.marketKey || raw.marketType,
    period: raw.period,
    lineValue: raw.lineValue,
    paramsJson: raw.paramsJson ?? null,
    status: raw.status || 'OPEN',
    allowSingle: raw.allowSingle ?? true,
    allowParlay: raw.allowParlay ?? true,
    showOnPlayer: raw.showOnPlayer ?? true,
    sortOrder: raw.sortOrder ?? index,
    promoLabelI18n: localized(raw.promoLabelI18n),
    nameI18n: localized(raw.nameI18n, raw.marketType),
    selections: (raw.selections ?? []).map((s, sIndex) => ({
      id: s.id,
      selectionCode: s.selectionCode,
      selectionName: s.selectionName,
      nameI18n: localized(s.nameI18n, s.selectionName),
      odds: Number(s.odds),
      status: s.status || 'OPEN',
      sortOrder: s.sortOrder ?? sIndex,
    })),
  };
}

function usesLineValue(marketType: string) {
  return definitionMap.value.get(marketType)?.usesLineValue ?? false;
}

function isLineMarket(market: MarketRow) {
  return usesLineValue(market.marketType);
}

async function load() {
  loading.value = true;
  try {
    const [{ data: defRes }, { data: tplRes }] = await Promise.all([
      api.get('/admin/market-definitions'),
      api.get('/admin/market-templates'),
    ]);
    definitions.value = defRes.data ?? [];
    templates.value = (tplRes.data ?? []).map((tpl: MarketTemplate) => ({
      ...tpl,
      nameI18n: localized(tpl.nameI18n, tpl.name),
      items: (tpl.items ?? []).map(mapItem),
    }));
    selectedId.value =
      selectedId.value && templates.value.some((tpl) => tpl.id === selectedId.value)
        ? selectedId.value
        : templates.value.find((tpl) => tpl.isDefault)?.id || templates.value[0]?.id || '';
    selectedIndex.value = 0;
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string } } };
    ElMessage.error(err.response?.data?.error ?? t('msg.load_failed'));
  } finally {
    loading.value = false;
  }
}

watch(selectedId, () => {
  selectedIndex.value = 0;
});

function openAddMarketDialog() {
  selectedDefinitionType.value = definitionOptions.value[0]?.marketType ?? '';
  addMarketVisible.value = true;
}

function addSelectedMarket() {
  const def = definitionMap.value.get(selectedDefinitionType.value);
  if (!def) return;
  addItem(def);
  addMarketVisible.value = false;
  selectedDefinitionType.value = '';
}

function addItem(def: MarketDefinition) {
  if (!current.value) return;
  current.value.items.push({
    marketType: def.marketType,
    marketKey: def.marketKey,
    period: def.period,
    lineValue: def.defaultLineValue,
    paramsJson: null,
    status: 'OPEN',
    allowSingle: def.allowSingle,
    allowParlay: def.allowParlay,
    showOnPlayer: def.showOnPlayer && def.settlementSupported,
    sortOrder: current.value.items.length,
    promoLabelI18n: localized(),
    nameI18n: localized(def.nameI18n, def.marketType),
    selections: def.selectionTemplate.map((s, index) => ({
      selectionCode: s.code,
      selectionName: s.name,
      nameI18n: localized(s.nameI18n, s.name),
      odds: Number(s.odds),
      status: 'OPEN',
      sortOrder: index,
    })),
  });
  selectedIndex.value = current.value.items.length - 1;
}

function copyLocalizedName(map: LocalizedText) {
  const suffix: Record<string, string> = {
    'zh-CN': ' 副本',
    'en-US': ' Copy',
    'ms-MY': ' Salinan',
  };
  const next = localized(map, resolveText(map));
  for (const loc of LOCALES) {
    const base = next[loc.code] || resolveText(next);
    next[loc.code] = `${base}${suffix[loc.code]}`;
  }
  return next;
}

function clonePlain<T>(value: T): T {
  return value == null ? value : JSON.parse(JSON.stringify(value));
}

function nextCopiedLineValue(source: MarketRow) {
  const tpl = current.value;
  const used = new Set(
    (tpl?.items ?? [])
      .filter((item) => item.marketType === source.marketType && item.lineValue != null)
      .map((item) => Number(item.lineValue).toFixed(2)),
  );
  let candidate = Number(((source.lineValue ?? 0) + 0.25).toFixed(2));
  while (used.has(candidate.toFixed(2))) {
    candidate = Number((candidate + 0.25).toFixed(2));
  }
  return candidate;
}

function duplicateItem(index: number) {
  const tpl = current.value;
  const source = tpl?.items[index];
  if (!tpl || !source) return;
  const shouldCopyLine = isLineMarket(source);
  const sourceCopy = clonePlain(source);
  const paramsCopy = clonePlain(source.paramsJson);
  const copy: MarketRow = {
    ...sourceCopy,
    id: undefined,
    lineValue: shouldCopyLine ? nextCopiedLineValue(source) : null,
    paramsJson: shouldCopyLine
      ? paramsCopy
      : { ...(paramsCopy ?? {}), copyId: `copy-${Date.now()}-${index}` },
    nameI18n: copyLocalizedName(source.nameI18n),
    sortOrder: tpl.items.length,
    selections: source.selections.map((selection) => ({ ...clonePlain(selection), id: undefined })),
  };
  tpl.items.splice(index + 1, 0, copy);
  tpl.items.forEach((item, i) => {
    item.sortOrder = i;
  });
  selectedIndex.value = index + 1;
  ElMessage.success(ui(shouldCopyLine ? 'copyCreated' : 'copyMarketCreated'));
}

function moveItem(index: number, direction: -1 | 1) {
  const tpl = current.value;
  if (!tpl) return;
  const target = index + direction;
  if (target < 0 || target >= tpl.items.length) return;
  const [row] = tpl.items.splice(index, 1);
  tpl.items.splice(target, 0, row);
  tpl.items.forEach((item, i) => {
    item.sortOrder = i;
  });
  selectedIndex.value = target;
}

function removeItem(index: number) {
  const tpl = current.value;
  if (!tpl) return;
  tpl.items.splice(index, 1);
  tpl.items.forEach((item, i) => {
    item.sortOrder = i;
  });
  selectedIndex.value = Math.min(selectedIndex.value, Math.max(0, tpl.items.length - 1));
}

function payload(tpl: MarketTemplate) {
  return {
    name: tpl.name,
    nameI18n: localized(tpl.nameI18n, tpl.name),
    isDefault: tpl.isDefault,
    status: tpl.status,
    sortOrder: tpl.sortOrder,
    items: tpl.items.map((m, index) => ({
      id: m.id,
      marketType: m.marketType,
      marketKey: m.marketKey,
      lineKey: null,
      period: m.period,
      lineValue: usesLineValue(m.marketType) ? m.lineValue : null,
      paramsJson: m.paramsJson,
      status: m.status,
      allowSingle: m.allowSingle,
      allowParlay: m.allowParlay,
      showOnPlayer: m.showOnPlayer,
      sortOrder: index,
      promoLabelI18n: localized(m.promoLabelI18n),
      nameI18n: localized(m.nameI18n, m.marketType),
      selections: m.selections.map((s, sIndex) => ({
        id: s.id,
        selectionCode: s.selectionCode,
        selectionName: resolveText(s.nameI18n, s.selectionName),
        nameI18n: localized(s.nameI18n, s.selectionName),
        odds: Number(s.odds),
        status: s.status,
        sortOrder: sIndex,
      })),
    })),
  };
}

async function createTemplate() {
  saving.value = true;
  try {
    const { data } = await api.post('/admin/market-templates', {
      name: '新盘口模板',
      nameI18n: { 'zh-CN': '新盘口模板', 'en-US': 'New Market Template', 'ms-MY': 'Templat Pasaran Baharu' },
      items: [],
    });
    await load();
    selectedId.value = data.data.id;
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string } } };
    ElMessage.error(err.response?.data?.error ?? t('msg.save_failed'));
  } finally {
    saving.value = false;
  }
}

async function duplicateTemplate() {
  if (!current.value) return;
  saving.value = true;
  try {
    const { data } = await api.post(`/admin/market-templates/${current.value.id}/duplicate`);
    await load();
    selectedId.value = data.data.id;
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string } } };
    ElMessage.error(err.response?.data?.error ?? t('msg.save_failed'));
  } finally {
    saving.value = false;
  }
}

async function setDefault() {
  if (!current.value) return;
    saving.value = true;
  try {
    await api.post(`/admin/market-templates/${current.value.id}/set-default`);
    ElMessage.success(ui('templateDefaultSet'));
    await load();
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string } } };
    ElMessage.error(err.response?.data?.error ?? t('msg.save_failed'));
  } finally {
    saving.value = false;
  }
}

async function saveTemplate() {
  if (!current.value) return;
  saving.value = true;
  try {
    await api.put(`/admin/market-templates/${current.value.id}`, payload(current.value));
    ElMessage.success(t('msg.saved'));
    await load();
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string } } };
    ElMessage.error(err.response?.data?.error ?? t('msg.save_failed'));
  } finally {
    saving.value = false;
  }
}

load();
</script>

<template>
  <div v-loading="loading" class="admin-list-page template-page">
    <div class="list-chrome">
      <div class="list-chrome__row">
        <div class="list-chrome__left">
          <MatchesSubNav embedded />
        </div>
      </div>
    </div>
    <div class="template-toolbar">
      <el-select v-model="selectedId" class="template-select" :placeholder="ui('selectTemplate')">
        <el-option
          v-for="tpl in templates"
          :key="tpl.id"
          :label="templateLabel(tpl)"
          :value="tpl.id"
        />
      </el-select>
      <el-button size="small" @click="createTemplate">{{ ui('createTemplate') }}</el-button>
      <el-button size="small" :disabled="!current" @click="duplicateTemplate">{{ ui('duplicateTemplate') }}</el-button>
      <el-button size="small" :disabled="!current?.id || current?.isDefault" @click="setDefault">{{ ui('setDefault') }}</el-button>
      <el-button size="small" :disabled="!current" @click="openAddMarketDialog">{{ ui('addMarket') }}</el-button>
      <el-button size="small" type="primary" :loading="saving" :disabled="!current" @click="saveTemplate">
        {{ t('common.save') }}
      </el-button>
    </div>

    <div v-if="current" class="template-grid">
      <section class="items">
        <div class="section-title">{{ ui('templateMarkets') }}</div>
        <div class="template-name">
          <label v-for="loc in displayLocales" :key="loc.code">
            <span>{{ loc.label }}</span>
            <el-input v-model="current.nameI18n[loc.code]" size="small" />
          </label>
        </div>
        <div
          v-for="(item, index) in current.items"
          :key="item.id || `${item.marketType}-${index}`"
          class="item-card"
          :class="{ active: selectedIndex === index }"
          @click="selectedIndex = index"
        >
          <div class="item-main">
            <strong>{{ marketTitle(item) }}</strong>
            <span>{{ marketMetaText(item) }}</span>
          </div>
          <div class="item-actions" @click.stop>
            <el-button class="item-action-btn" size="small" text :title="ui('moveUp')" :disabled="index === 0" @click="moveItem(index, -1)">↑</el-button>
            <el-button class="item-action-btn" size="small" text :title="ui('moveDown')" :disabled="index === current.items.length - 1" @click="moveItem(index, 1)">↓</el-button>
            <el-button
              class="item-action-btn copy-btn"
              size="small"
              text
              :title="ui(isLineMarket(item) ? 'copyLine' : 'copyMarket')"
              @click="duplicateItem(index)"
            >
              {{ ui(isLineMarket(item) ? 'copyLineShort' : 'copyMarketShort') }}
            </el-button>
            <el-button class="item-action-btn" size="small" text type="danger" :title="ui('remove')" @click="removeItem(index)">{{ ui('remove') }}</el-button>
          </div>
        </div>
      </section>

      <section v-if="selectedItem" class="detail">
        <div class="detail-head">
          <div>
            <div class="section-title">{{ ui('marketDetails') }}</div>
            <strong>{{ marketTitle(selectedItem) }}</strong>
          </div>
          <el-switch v-model="selectedItem.showOnPlayer" :active-text="ui('playerVisible')" />
        </div>
        <div class="form-grid">
          <label>
            <span>{{ ui('status') }}</span>
            <el-select v-model="selectedItem.status" size="small">
              <el-option :label="ui('statusOpen')" value="OPEN" />
              <el-option :label="ui('statusSuspended')" value="SUSPENDED" />
              <el-option :label="ui('statusClosed')" value="CLOSED" />
            </el-select>
          </label>
          <label v-if="isLineMarket(selectedItem)">
            <span>{{ ui('lineValue') }}</span>
            <el-input-number v-model="selectedItem.lineValue" size="small" :step="0.25" controls-position="right" />
          </label>
          <label>
            <span>{{ ui('single') }}</span>
            <el-switch v-model="selectedItem.allowSingle" />
          </label>
          <label>
            <span>{{ ui('parlay') }}</span>
            <el-switch v-model="selectedItem.allowParlay" />
          </label>
        </div>
        <div class="locale-block">
          <div class="block-title">{{ ui('marketName') }}</div>
          <div class="locale-grid">
            <label v-for="loc in displayLocales" :key="loc.code">
              <span>{{ loc.label }}</span>
              <el-input v-model="selectedItem.nameI18n[loc.code]" size="small" />
            </label>
          </div>
        </div>
        <div class="locale-block">
          <div class="block-title">{{ ui('promoLabel') }}</div>
          <div class="locale-grid">
            <label v-for="loc in displayLocales" :key="`promo-${loc.code}`">
              <span>{{ loc.label }}</span>
              <el-input v-model="selectedItem.promoLabelI18n[loc.code]" size="small" clearable />
            </label>
          </div>
        </div>

        <div class="selection-list">
          <div
            v-for="sel in selectedItem.selections"
            :key="sel.selectionCode"
            class="selection-row"
            :class="{ 'selection-row--score': isScoreSelection(sel) }"
          >
            <div class="selection-meta">
              <strong :title="sel.selectionCode">{{ selectionTitle(sel) }}</strong>
              <label class="selection-field selection-field--status">
                <span>{{ ui('status') }}</span>
                <el-select v-model="sel.status" size="small">
                  <el-option :label="ui('statusOpen')" value="OPEN" />
                  <el-option :label="ui('statusSuspended')" value="SUSPENDED" />
                  <el-option :label="ui('statusClosed')" value="CLOSED" />
                </el-select>
              </label>
              <label class="selection-field selection-field--odds">
                <span>{{ ui('odds') }}</span>
                <el-input-number v-model="sel.odds" size="small" :min="1.01" :step="0.01" controls-position="right" />
              </label>
            </div>
            <div v-if="!isScoreSelection(sel)" class="locale-grid compact">
              <label v-for="loc in displayLocales" :key="loc.code">
                <span>{{ loc.label }}</span>
                <el-input v-model="sel.nameI18n[loc.code]" size="small" />
              </label>
            </div>
          </div>
        </div>
      </section>
    </div>

    <el-dialog v-model="addMarketVisible" class="add-market-dialog" :title="ui('addMarket')" width="460px" destroy-on-close>
      <label class="add-market-field">
        <span>{{ ui('marketToAdd') }}</span>
        <el-select
          v-model="selectedDefinitionType"
          class="full-select"
          filterable
          :placeholder="ui('selectMarket')"
        >
          <el-option
            v-for="def in definitionOptions"
            :key="def.marketType"
            :label="definitionLabel(def)"
            :value="def.marketType"
          />
        </el-select>
      </label>
      <template #footer>
        <el-button @click="addMarketVisible = false">{{ t('common.cancel') }}</el-button>
        <el-button type="primary" :disabled="!selectedDefinitionType" @click="addSelectedMarket">
          {{ ui('add') }}
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.template-page {
  height: 100%;
  min-height: 0;
  padding: 0 4px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.template-toolbar {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px 0 12px;
}

.template-select {
  width: 280px;
}

.template-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(320px, 420px) minmax(480px, 1fr);
  align-items: stretch;
  gap: 10px;
  overflow: hidden;
}

.items,
.detail {
  min-width: 0;
  min-height: 0;
  border: 1px solid #262626;
  border-radius: 8px;
  background: #111;
  padding: 10px;
  overflow: auto;
}

.section-title,
.block-title {
  color: #bbb;
  font-size: 12px;
  font-weight: 700;
  margin-bottom: 8px;
}

.item-card {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  border: 1px solid #282828;
  border-radius: 6px;
  background: #151515;
  color: #ddd;
  padding: 8px;
  margin-bottom: 6px;
  text-align: left;
  cursor: pointer;
}

.item-card span {
  display: block;
  margin-top: 3px;
  color: #777;
  font-size: 11px;
}

.item-card.active {
  border-color: #9f853d;
  background: #1a1710;
}

.item-main {
  min-width: 0;
  flex: 1;
}

.item-main strong,
.detail-head strong {
  display: block;
  color: #f0f0f0;
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.item-actions {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 30px 30px 46px 40px;
  gap: 2px;
  justify-content: end;
}

.item-action-btn {
  width: 100%;
  height: 26px;
  padding: 0;
  margin-left: 0 !important;
  font-size: 12px;
}

.copy-btn {
  font-size: 11px;
}

.template-name,
.form-grid,
.locale-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}

.form-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.locale-grid.compact {
  margin-bottom: 0;
}

.locale-block {
  margin-bottom: 12px;
}

label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: #aaa;
  font-size: 12px;
}

.detail-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  color: #eee;
}

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

.selection-row {
  padding: 8px;
  border: 1px solid #262626;
  border-radius: 6px;
  background: #141414;
}

.selection-meta {
  display: grid;
  grid-template-columns: minmax(90px, 1fr) 120px 132px;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}

.selection-row--score .selection-meta {
  margin-bottom: 0;
}

.selection-meta strong {
  color: #ddd;
  font-size: 12px;
}

.selection-field {
  gap: 3px;
}

.selection-field > span {
  color: #f3c969;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
}

.selection-field--status > span {
  color: #7dd3fc;
}

.selection-field--odds :deep(.el-input-number),
.selection-field--odds :deep(.el-input) {
  width: 100%;
}

.add-market-field {
  margin: 0;
}

.full-select {
  width: 100%;
}

@media (max-width: 720px) {
  .template-toolbar,
  .template-grid,
  .template-name,
  .form-grid,
  .locale-grid,
  .selection-meta {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }

  .template-select {
    width: 100%;
  }

  .items,
  .detail {
    min-height: 320px;
  }
}

.template-toolbar {
  padding: 12px 0 14px;
}

.items,
.detail,
.item-card,
.selection-row {
  border-color: var(--border);
  background: #ffffff;
  color: var(--text);
}

.items,
.detail {
  box-shadow: var(--shadow);
}

.section-title,
.block-title,
.item-main strong,
.detail-head strong,
.selection-meta strong {
  color: var(--text);
}

.item-card span,
label,
.selection-field > span {
  color: var(--text-muted);
}

.item-card:hover {
  border-color: #d5cfc3;
  background: var(--accent-hover);
}

.item-card.active {
  border-color: var(--primary);
  background: var(--accent-subtle);
}

.selection-row {
  background: #fbfaf7;
}

.selection-field > span {
  font-weight: 750;
}

.selection-field--status > span {
  color: var(--info-text);
}

@media (max-width: 720px) {
  .item-actions {
    grid-template-columns: repeat(4, minmax(30px, 1fr));
  }
}
</style>
