<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { ElMessage } from 'element-plus';
import api from '../api';
import { useAdminLocale } from '../composables/useAdminLocale';
import { buildPlayerRegisterUrl, copyText } from '../utils/invite-link';
import { useAuthStore } from '../stores/auth';
import RatePercentInput from './RatePercentInput.vue';
import { decimalRateToPercent, formatRatePercent, percentToDecimalRate } from '../utils/rate-percent';

const props = defineProps<{
  inviteCode?: string | null;
  compact?: boolean;
  readonly?: boolean;
  embedded?: boolean;
  hideHistory?: boolean;
  /** When true, code/link only appear after clicking generate (not from session/props). */
  requireGenerate?: boolean;
}>();

const emit = defineEmits<{
  generated: [];
}>();

const { t } = useAdminLocale();
const auth = useAuthStore();
const loadedCode = ref<string | null>(null);
const loadedCashbackRate = ref<string | null>(null);
const generating = ref(false);
const cashbackPercent = ref(0);
const defaultCashbackLoaded = ref(false);

const isAdmin = computed(() => auth.isAdmin.value);
const showCashbackField = computed(() => isAdmin.value && !props.readonly);

const effectiveCode = computed(() => {
  if (props.readonly) return props.inviteCode ?? null;
  if (props.requireGenerate) return loadedCode.value;
  return props.inviteCode ?? loadedCode.value;
});

const registerUrl = computed(() =>
  effectiveCode.value ? buildPlayerRegisterUrl(effectiveCode.value) : '',
);

const displayedCashbackRate = computed(() => {
  if (loadedCashbackRate.value != null) return loadedCashbackRate.value;
  if (showCashbackField.value) return percentToDecimalRate(cashbackPercent.value).toString();
  return null;
});

async function loadDefaultCashbackRate() {
  if (!showCashbackField.value) return;
  try {
    const { data } = await api.get('/admin/settings/cashback/platform-direct');
    const payload = data.data as { adminInviteRate?: number | string; platformDirectRate?: number | string };
    cashbackPercent.value = decimalRateToPercent(
      payload?.adminInviteRate ?? payload?.platformDirectRate ?? 0,
    );
  } catch {
    cashbackPercent.value = 0;
  } finally {
    defaultCashbackLoaded.value = true;
  }
}

async function generateInvite() {
  generating.value = true;
  try {
    const body = showCashbackField.value
      ? { cashbackRate: percentToDecimalRate(cashbackPercent.value) }
      : undefined;
    const { data } = await api.post('/manage/invite/generate', body);
    const payload = data.data as { inviteCode?: string | null; cashbackRate?: string | null };
    const code = payload.inviteCode ?? null;
    loadedCode.value = code;
    loadedCashbackRate.value = payload.cashbackRate ?? null;
    if (auth.user.value && code) {
      auth.setSession(auth.token.value, { ...auth.user.value, inviteCode: code });
    }
    ElMessage.success(t('invite.generate_ok'));
    emit('generated');
  } catch {
    ElMessage.error(t('invite.generate_failed'));
  } finally {
    generating.value = false;
  }
}

async function copyCode() {
  if (!effectiveCode.value) return;
  const ok = await copyText(effectiveCode.value);
  ElMessage[ok ? 'success' : 'error'](ok ? t('invite.copy_code_ok') : t('invite.copy_failed'));
}

async function copyLink() {
  if (!registerUrl.value) return;
  const ok = await copyText(registerUrl.value);
  ElMessage[ok ? 'success' : 'error'](ok ? t('invite.copy_link_ok') : t('invite.copy_failed'));
}

onMounted(() => {
  void loadDefaultCashbackRate();
});
</script>

<template>
  <div class="invite-panel" :class="{ compact, embedded }">
    <div v-if="!embedded" class="invite-head">
      <span class="invite-title">{{ t('invite.title') }}</span>
      <span class="invite-hint">{{ t('invite.hint') }}</span>
    </div>
    <div v-if="showCashbackField && defaultCashbackLoaded" class="invite-cashback-field">
      <label class="invite-label">{{ t('invite.cashback_rate') }}</label>
      <RatePercentInput v-model="cashbackPercent" />
      <p class="invite-cashback-hint">{{ t('invite.cashback_rate_hint') }}</p>
    </div>
    <div v-if="!readonly" class="invite-actions">
      <el-button type="primary" :loading="generating" @click="generateInvite">
        {{ effectiveCode ? t('invite.regenerate_btn') : t('invite.generate_btn') }}
      </el-button>
    </div>
    <div v-if="effectiveCode" class="invite-body">
      <div v-if="displayedCashbackRate != null" class="invite-row">
        <span class="invite-label">{{ t('invite.cashback_rate') }}</span>
        <span class="invite-rate">{{ formatRatePercent(displayedCashbackRate) }}</span>
      </div>
      <div class="invite-row">
        <span class="invite-label">{{ t('invite.code') }}</span>
        <code class="invite-code">{{ effectiveCode }}</code>
        <el-button size="small" @click="copyCode">{{ t('invite.copy_code') }}</el-button>
      </div>
      <div class="invite-row">
        <span class="invite-label">{{ t('invite.link') }}</span>
        <span class="invite-link">{{ registerUrl }}</span>
        <el-button type="primary" size="small" @click="copyLink">{{ t('invite.copy_link') }}</el-button>
      </div>
    </div>
    <p v-else-if="readonly" class="invite-empty">{{ t('invite.not_generated') }}</p>
  </div>
</template>

<style scoped>
.invite-panel {
  border: 1px solid var(--el-border-color-light);
  border-radius: 8px;
  padding: 14px 16px;
  background: var(--el-fill-color-blank);
}

.invite-panel.compact {
  padding: 10px 12px;
}

.invite-panel.embedded {
  border: none;
  padding: 0;
  background: transparent;
}

.invite-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
}

.invite-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--el-text-color-primary);
}

.invite-hint {
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.invite-cashback-field {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  margin-bottom: 12px;
  width: 100%;
}

.invite-cashback-hint {
  margin: 0;
  font-size: 11px;
  color: var(--el-text-color-secondary);
  line-height: 1.45;
}

.invite-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.invite-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.invite-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.invite-label {
  min-width: 72px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.invite-rate {
  font-size: 14px;
  font-weight: 600;
  color: var(--el-color-success);
}

.invite-code {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--el-color-primary);
}

.invite-link {
  flex: 1;
  min-width: 180px;
  font-size: 12px;
  color: var(--el-text-color-regular);
  word-break: break-all;
}

.invite-empty {
  margin: 0;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}
</style>
