<script setup lang="ts">
import { ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { useAdminLocale } from '../../composables/useAdminLocale';
import api from '../../api';
import type { AdminMatchDetail } from '../match-form';
import { defaultSelectionName } from '../../utils/selectionDefaults';
import { adminSelectionLabel } from '../../utils/adminSelectionLabel';

const props = defineProps<{
  matchId: string;
}>();

const { t } = useAdminLocale();

interface SelectionRow {
  id: string;
  selectionCode: string;
  selectionName: string;
  odds: number;
  status: string;
  editOdds: number;
}

interface MarketRow {
  id: string;
  marketType: string;
  period: string;
  lineValue: number | null;
  status: string;
  promoLabel: string;
  editPromoLabel: string;
  editLineValue: number | null;
  selections: SelectionRow[];
}

const DEFAULT_MARKET_TYPES = [
  'FT_1X2',
  'FT_HANDICAP',
  'FT_OVER_UNDER',
  'FT_ODD_EVEN',
  'HT_1X2',
  'HT_HANDICAP',
  'HT_OVER_UNDER',
  'FT_CORRECT_SCORE',
  'HT_CORRECT_SCORE',
  'SH_CORRECT_SCORE',
];

const loading = ref(false);
const savingMarketId = ref<string | null>(null);
const markets = ref<MarketRow[]>([]);

function mapMarkets(detail: AdminMatchDetail) {
  markets.value = (detail.markets ?? []).map((m) => ({
    id: m.id,
    marketType: m.marketType,
    period: m.period,
    lineValue: m.lineValue,
    status: m.status,
    promoLabel: m.promoLabel,
    editPromoLabel: m.promoLabel,
    editLineValue: m.lineValue,
    selections: m.selections.map((s) => ({
      id: s.id,
      selectionCode: s.selectionCode,
      selectionName: s.selectionName,
      odds: s.odds,
      status: s.status,
      editOdds: s.odds,
    })),
  }));
}

async function load() {
  if (!props.matchId) return;
  loading.value = true;
  try {
    const { data } = await api.get(`/admin/matches/${props.matchId}`);
    mapMarkets(data.data as AdminMatchDetail);
  } 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(
  () => props.matchId,
  () => {
    load();
  },
  { immediate: true },
);

function marketLabel(type: string) {
  const key = `matchEditor.market.${type}`;
  const v = t(key);
  return v !== key ? v : type;
}

function selectionCodeLabel(code: string, market?: MarketRow) {
  return adminSelectionLabel(t, code, {
    lineValue: market?.editLineValue ?? market?.lineValue,
    period: market?.period,
  });
}

function hasLine(market: MarketRow) {
  return market.lineValue != null || market.editLineValue != null;
}

const CORRECT_SCORE_TYPES = new Set([
  'FT_CORRECT_SCORE',
  'HT_CORRECT_SCORE',
  'SH_CORRECT_SCORE',
]);

function isMultiRowMarket(market: MarketRow) {
  return CORRECT_SCORE_TYPES.has(market.marketType) || market.selections.length > 6;
}

function normPromo(value: string | null | undefined) {
  return (value ?? '').trim() || null;
}

function normLine(value: number | null | undefined) {
  return value == null ? null : Number(value);
}

function isMarketDirty(market: MarketRow) {
  if (normPromo(market.editPromoLabel) !== normPromo(market.promoLabel)) return true;
  if (normLine(market.editLineValue) !== normLine(market.lineValue)) return true;
  return market.selections.some((s) => Number(s.editOdds) !== Number(s.odds));
}

async function generateTemplates() {
  loading.value = true;
  try {
    await api.post(`/admin/matches/${props.matchId}/markets/templates`, {
      marketTypes: DEFAULT_MARKET_TYPES,
    });
    ElMessage.success(t('matchEditor.templates_generated'));
    await load();
  } catch (e: unknown) {
    const err = e as { response?: { data?: { error?: string } } };
    ElMessage.error(err.response?.data?.error ?? t('msg.save_failed'));
  } finally {
    loading.value = false;
  }
}

async function saveMarket(market: MarketRow) {
  const invalid = market.selections.find((s) => !s.editOdds || s.editOdds <= 1);
  if (invalid) {
    ElMessage.warning(t('outright.err_odds_min'));
    return;
  }

  savingMarketId.value = market.id;
  try {
    await api.patch(`/admin/markets/${market.id}`, {
      promoLabel: market.editPromoLabel.trim() || null,
      lineValue: market.editLineValue,
    });
    await api.put(`/admin/matches/${props.matchId}/odds`, {
      updates: market.selections.map((s) => ({
        selectionId: s.id,
        odds: s.editOdds,
      })),
    });
    for (const s of market.selections) {
      const name = defaultSelectionName(s.selectionCode, {
        lineValue: market.editLineValue,
        period: market.period,
      });
      if (name !== s.selectionName) {
        await api.patch(`/admin/selections/${s.id}`, {
          selectionName: name,
        });
      }
    }
    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 {
    savingMarketId.value = null;
  }
}
</script>

<template>
  <div v-loading="loading" class="match-markets-panel">
    <div class="panel-head">
      <span class="panel-title">{{ t('matchEditor.section_markets') }}</span>
      <el-button size="small" type="primary" plain @click="generateTemplates">
        {{ t('matchEditor.generate_templates') }}
      </el-button>
    </div>

    <p v-if="!markets.length" class="empty-hint">{{ t('matchEditor.no_markets') }}</p>

    <div v-else class="market-lines">
      <div
        v-for="market in markets"
        :key="market.id"
        class="market-line"
        :class="{ 'market-line--wrap': isMultiRowMarket(market) }"
      >
        <label class="field-promo-wrap">
          <span class="promo-label">{{ t('matchEditor.field.promo_label_optional') }}</span>
          <el-input
            v-model="market.editPromoLabel"
            size="small"
            class="field-promo"
            clearable
          />
        </label>

        <div class="market-line-head">
          <span class="market-label" :title="market.marketType">{{ marketLabel(market.marketType) }}</span>

          <el-input-number
            v-if="hasLine(market)"
            v-model="market.editLineValue"
            size="small"
            class="field-line"
            :step="0.25"
            controls-position="right"
          />

          <el-button
            v-if="isMultiRowMarket(market)"
            size="small"
            :type="isMarketDirty(market) ? 'primary' : 'default'"
            class="btn-save"
            :disabled="!isMarketDirty(market)"
            :loading="savingMarketId === market.id"
            @click="saveMarket(market)"
          >
            {{ t('common.save') }}
          </el-button>
        </div>

        <div
          class="selections-wrap"
          :class="isMultiRowMarket(market) ? 'selections-grid' : 'selections-inline'"
        >
          <div v-for="sel in market.selections" :key="sel.id" class="sel-inline">
            <span class="sel-label" :title="sel.selectionCode">{{
              selectionCodeLabel(sel.selectionCode, market)
            }}</span>
            <el-input-number
              v-model="sel.editOdds"
              size="small"
              class="sel-odds"
              :min="1.01"
              :step="0.01"
              controls-position="right"
            />
          </div>
        </div>

        <el-button
          v-if="!isMultiRowMarket(market)"
          size="small"
          :type="isMarketDirty(market) ? 'primary' : 'default'"
          class="btn-save"
          :disabled="!isMarketDirty(market)"
          :loading="savingMarketId === market.id"
          @click="saveMarket(market)"
        >
          {{ t('common.save') }}
        </el-button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.match-markets-panel {
  padding: 10px 12px 12px 16px;
  background: #0a0a0a;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.panel-title {
  font-size: 13px;
  font-weight: 700;
  color: #ccc;
  letter-spacing: 0.04em;
}

.empty-hint {
  color: #888;
  font-size: 13px;
  line-height: 1.5;
  margin: 0;
}

.market-lines {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.market-line {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid #252525;
  border-radius: 6px;
  background: #111;
  min-width: 0;
}

.market-line--wrap {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 8px;
}

.market-line--wrap .field-promo-wrap {
  width: 100%;
  max-width: 280px;
}

.field-promo-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.promo-label {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 600;
  color: #8e8e93;
  white-space: nowrap;
}

.field-promo {
  flex: 0 0 88px;
  min-width: 0;
}

.market-line--wrap .field-promo {
  flex: 1;
  max-width: 160px;
}

.market-line-head {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.market-line:not(.market-line--wrap) .market-line-head {
  flex: 0 1 auto;
}

.market-line--wrap .market-line-head {
  width: 100%;
}

.market-line--wrap .market-line-head .btn-save {
  margin-left: auto;
}

.market-label {
  flex: 0 0 76px;
  font-size: 11px;
  font-weight: 700;
  color: #e8e8e8;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.field-line {
  flex: 0 0 88px;
  min-width: 0;
}

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

.selections-inline {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.selections-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 6px;
  width: 100%;
}

.selections-grid .sel-inline {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 8px;
}

.selections-grid .sel-label {
  min-width: 0;
  max-width: 100%;
  white-space: nowrap;
  line-height: 1.2;
}

.selections-grid .sel-odds {
  width: 100%;
}

.selections-grid .sel-odds :deep(.el-input-number) {
  width: 100%;
}

.sel-inline {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 2px 6px;
  border-radius: 4px;
  background: #0d0d0d;
}

.sel-label {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 700;
  color: var(--green-text);
  min-width: 14px;
  text-align: center;
  white-space: nowrap;
}

.sel-odds {
  width: 88px;
}

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

.btn-save {
  flex-shrink: 0;
  min-width: 52px;
}

.btn-save.is-disabled,
.btn-save:disabled {
  opacity: 0.45;
}
</style>
