<script setup lang="ts">
import { computed, onActivated, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { formatLocalMatchDateTime } from '@thebet365/shared';
import GoldSpinner from './GoldSpinner.vue';
import ConfirmDialog from './ConfirmDialog.vue';
import { useAuthStore } from '../stores/auth';
import { usePlayerMessages, type DepositMessagePayload, type PlayerMessage } from '../composables/usePlayerMessages';
import { stripHtml } from '../utils/html';

const router = useRouter();
const { t, locale } = useI18n();
const auth = useAuthStore();
const {
  messages,
  loading,
  listLoaded,
  loadMessages,
  refreshUnreadCount,
  deleteMessage,
} = usePlayerMessages();

const page = ref(1);
const total = ref(0);
const deletingId = ref<string | null>(null);
const deleteConfirmVisible = ref(false);
const pendingDeleteId = ref<string | null>(null);

const hasMore = computed(() => messages.value.length < total.value);

function formatDate(createdAt?: string) {
  if (!createdAt) return '';
  return formatLocalMatchDateTime(createdAt, locale.value, { variant: 'full' });
}

function messageTitle(item: PlayerMessage) {
  if (item.type === 'DEPOSIT_APPROVED') return t('messages.deposit_approved_title');
  if (item.type === 'DEPOSIT_REJECTED') return t('messages.deposit_rejected_title');
  return item.title;
}

function messagePreview(item: PlayerMessage) {
  if (item.type === 'DEPOSIT_APPROVED' || item.type === 'DEPOSIT_REJECTED') {
    const deposit = item.payload as DepositMessagePayload | null;
    if (deposit?.orderNo) return deposit.orderNo;
  }
  const plain = stripHtml(item.body);
  return plain.length > 80 ? `${plain.slice(0, 80)}…` : plain;
}

function openDetail(id: string) {
  router.push(`/messages/${id}`);
}

async function fetchPage(nextPage: number, append = false) {
  const result = await loadMessages(nextPage, append);
  if (result) {
    page.value = result.page;
    total.value = result.total;
  }
}

function tryLoad() {
  if (!auth.token) return;
  void fetchPage(1);
  void refreshUnreadCount();
}

function goLogin() {
  auth.showLoginPrompt('/messages');
}

function onDelete(id: string, event: Event) {
  event.stopPropagation();
  if (deletingId.value) return;
  pendingDeleteId.value = id;
  deleteConfirmVisible.value = true;
}

function onDeleteCancel() {
  pendingDeleteId.value = null;
}

async function confirmDelete() {
  const id = pendingDeleteId.value;
  if (!id || deletingId.value) return;
  deletingId.value = id;
  try {
    await deleteMessage(id);
    total.value = Math.max(0, total.value - 1);
    deleteConfirmVisible.value = false;
    pendingDeleteId.value = null;
  } finally {
    deletingId.value = null;
  }
}

onMounted(tryLoad);
onActivated(tryLoad);
</script>

<template>
  <div class="message-list-panel">
    <div v-if="!auth.token" class="guest-hint">
      <p>{{ t('auth.login_required') }}</p>
      <button type="button" class="login-link" @click="goLogin">{{ t('auth.go_login') }}</button>
    </div>

    <template v-else>
      <div v-if="loading && !listLoaded" class="state">
        <GoldSpinner :size="36" />
      </div>

      <div v-else-if="!messages.length" class="empty">
        <p>{{ t('messages.empty') }}</p>
      </div>

      <div v-else class="list">
        <div
          v-for="item in messages"
          :key="item.id"
          class="list-row"
          :class="{ unread: !item.isRead }"
        >
          <button type="button" class="row-body" @click="openDetail(item.id)">
            <span class="row-dot" aria-hidden="true" />
            <span class="row-main">
              <span class="title-row">
                <span class="title">{{ messageTitle(item) }}</span>
                <span class="status-badge" :class="{ unread: !item.isRead }">
                  {{ item.isRead ? t('messages.status_read') : t('messages.status_unread') }}
                </span>
              </span>
              <span class="preview">{{ messagePreview(item) }}</span>
              <span v-if="item.createdAt" class="date">{{ formatDate(item.createdAt) }}</span>
            </span>
            <span class="chevron" aria-hidden="true">›</span>
          </button>
          <button
            type="button"
            class="delete-btn"
            :aria-label="t('messages.delete')"
            :disabled="deletingId === item.id"
            @click="onDelete(item.id, $event)"
          >
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <path
                d="M6 7h12M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2m2 0v12a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V7h12Z"
                fill="none"
                stroke="currentColor"
                stroke-width="1.6"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
            </svg>
          </button>
        </div>

        <button v-if="hasMore" type="button" class="load-more" :disabled="loading" @click="fetchPage(page + 1, true)">
          {{ loading ? t('common.loading_more') : t('messages.load_more') }}
        </button>
      </div>
    </template>

    <ConfirmDialog
      v-model:visible="deleteConfirmVisible"
      :title="t('messages.delete')"
      :message="t('messages.delete_confirm')"
      :confirm-text="t('messages.delete')"
      danger
      :loading="!!deletingId"
      @confirm="confirmDelete"
      @cancel="onDeleteCancel"
    />
  </div>
</template>

<style scoped>
.message-list-panel {
  flex: 1;
  min-height: 0;
}

.guest-hint,
.state,
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 48px 16px;
  color: var(--text-muted);
}

.login-link {
  border: 1px solid var(--border-gold-soft);
  border-radius: 8px;
  padding: 8px 14px;
  background: rgba(212, 175, 55, 0.1);
  color: var(--gold);
  font-size: 13px;
  font-weight: 600;
}

.list {
  display: flex;
  flex-direction: column;
}

.list-row {
  display: flex;
  align-items: stretch;
  gap: 0;
  border-bottom: 1px solid var(--border);
}

.row-body {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 14px 0;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
}

.list-row.unread .title {
  color: #fff;
  font-weight: 700;
}

.row-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: transparent;
  flex-shrink: 0;
}

.list-row.unread .row-dot {
  background: var(--gold);
  box-shadow: 0 0 8px rgba(212, 175, 55, 0.45);
}

.row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.title {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  color: #d8d8d8;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.status-badge {
  flex-shrink: 0;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 600;
  color: #888;
  background: rgba(255, 255, 255, 0.06);
}

.status-badge.unread {
  color: var(--gold);
  background: rgba(212, 175, 55, 0.12);
}

.preview {
  font-size: 13px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.date {
  font-size: 12px;
  color: #777;
}

.chevron {
  color: var(--text-muted);
  font-size: 20px;
  flex-shrink: 0;
}

.delete-btn {
  flex-shrink: 0;
  align-self: center;
  width: 36px;
  height: 36px;
  margin-left: 4px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: #666;
  cursor: pointer;
}

.delete-btn:active:not(:disabled) {
  background: rgba(255, 80, 80, 0.12);
  color: #f66;
}

.delete-btn svg {
  width: 18px;
  height: 18px;
}

.delete-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.load-more {
  margin-top: 12px;
  width: 100%;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #141414;
  color: var(--gold);
  font-size: 13px;
}
</style>
