<template>
  <div class="h-[100dvh] flex flex-col px-[12px] overflow-hidden bg-white">
    <div class="flex-1 flex flex-col items-center justify-center">
      <div>
        <section>
          <van-cell :title="t('common.login.fields.country')" is-link @click="countryPopupVisible = true">
            <template #value>
              <span class="inline-flex items-center gap-2">
                <img class="w-[20px] h-[15px] object-cover rounded-[2px]"
                  :src="getCountryFlagPngUrl(selectedCountry.iso2)" alt="" loading="lazy" />
                <span>{{ selectedCountry.name }} ({{ selectedCountry.dialCode }})</span>
              </span>
            </template>
          </van-cell>

          <van-field v-model="phone" type="tel" clearable :label="t('common.login.fields.phone')"
            :placeholder="t('common.login.placeholders.phone')" autocomplete="tel" />

          <van-field v-model="code" class="login-code-field" type="digit" clearable maxlength="8"
            :label="t('common.login.fields.code')" :placeholder="t('common.login.placeholders.code')"
            autocomplete="one-time-code">
            <template #button>
              <van-button class="rounded-full" size="small" @click="handleSendCode">
                {{ t('common.login.actions.sendCode') }}
              </van-button>
            </template>
          </van-field>

          <div class="mt-4">
            <van-button class="login-main-btn" type="primary" block :loading="phoneSubmitting"
              :disabled="!canSubmitPhoneLogin" @click="handlePhoneLogin">
              {{ t('common.login.actions.login') }}
            </van-button>
          </div>
        </section>

        <van-divider>{{ t('common.login.dividersText') }}</van-divider>

        <div class="flex flex-col items-center justify-center">
          <div ref="googleButtonEl" id="buttonDiv" class="google-login-btn"></div>
        </div>
      </div>
    </div>

    <!-- 语种切换 -->
    <div class="flex justify-center items-center gap-4 pb-4">
      <Globe :size="16" color="#999" />
      <span v-for="lang in languageOptions" :key="lang.locale"
        class="text-xs transition-colors duration-200 text-[14px]"
        :class="currentLocale === lang.locale ? 'text-[#00C853] font-medium' : 'text-[#999]'"
        @click="switchLanguage(lang.locale)">
        {{ t(lang.labelKey) }}
      </span>
    </div>
  </div>

  <van-popup v-model:show="countryPopupVisible" round position="bottom" class="h-[70vh]">
    <div class="h-full flex flex-col ">
      <div class="border-b border-[#E5E5E5]">
        <van-search v-model="countrySearch" :placeholder="t('common.login.placeholders.selectCountry')" shape="round" />
      </div>
      <div class="flex-1 overflow-y-auto scrollbar-none [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden">
        <van-cell v-for="item in filteredCountries" :key="`${item.iso2}-${item.dialCode}`" :value="item.dialCode"
          @click="handleSelectCountry(item)">
          <template #title>
            <span class="inline-flex items-center gap-2">
              <img class="w-[20px] h-[15px] object-cover rounded-[2px]" :src="getCountryFlagPngUrl(item.iso2)" alt=""
                loading="lazy" />
              <span>{{ item.name }}</span>
            </span>
          </template>
        </van-cell>
      </div>
    </div>
  </van-popup>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import { showToast } from "vant";
import { oauthToken, sendCode } from "@/api/login";
import { NOTICE_EVENT_LOGIN_SUCCESS } from "@/constants/constant";
import { COUNTRY_CALLING_CODES, findCountryCallingCode } from "@/constants/countryCallingCodes";
import { getCurrentLocale, setLocale } from "@/i18n";
import { emitter } from "@/utils/events";
import { Globe } from '@lucide/vue'

const router = useRouter();
const route = useRoute();
const { t } = useI18n();

function resolveLoginRedirect(): string | null {
  const redirect = route.query.redirect;
  const value = Array.isArray(redirect) ? redirect[0] : redirect;

  if (!value || !value.startsWith("/") || value.startsWith("//")) {
    return null;
  }

  if (value.startsWith("/login")) {
    return null;
  }

  return value;
}

function navigateAfterLogin() {
  const redirect = resolveLoginRedirect();
  return router.replace(redirect ?? { name: "home" });
}

const googleButtonEl = ref<HTMLElement | null>(null);
const googleInited = ref(false);
const googleButtonRendered = ref(false);
const countryPopupVisible = ref(false);
const countrySearch = ref("");

const languageOptions = [
  { locale: "zh-CN", labelKey: "common.locales.zhCN" },
  { locale: "en-US", labelKey: "common.locales.enUS" },
  { locale: "th-TH", labelKey: "common.locales.thTH" },
];
const currentLocale = computed(() => getCurrentLocale());
const switchLanguage = (locale: string) => setLocale(locale);

function getCountryFlagPngUrl(iso2: string): string {
  const country = (iso2 ?? "").trim().toLowerCase();
  if (!/^[a-z]{2}$/.test(country)) return "https://flagcdn.com/w40/un.png";
  return `https://flagcdn.com/w40/${country}.png`;
}

const selectedCountry = ref(
  findCountryCallingCode(
    (() => {
      const locale = getCurrentLocale();
      if (locale === "th-TH") return "TH";
      if (locale === "en-US") return "US";
      return "CN";
    })(),
  ) ?? COUNTRY_CALLING_CODES[0],
);

const phone = ref("");
const code = ref("");
const phoneSubmitting = ref(false);

const filteredCountries = computed(() => {
  const q = countrySearch.value.trim().toLowerCase();
  if (!q) {
    return COUNTRY_CALLING_CODES;
  }

  const dialQuery = q.startsWith("+") ? q.slice(1) : q;
  const isDialQuery = /^\d+$/.test(dialQuery);

  return COUNTRY_CALLING_CODES.filter((item) => {
    if (isDialQuery) {
      const dialCode = item.dialCode.replace("+", "");
      return dialCode.startsWith(dialQuery);
    }

    const nameTokens = item.name
      .toLowerCase()
      .replace(/[^a-z\s]/g, " ")
      .split(/\s+/)
      .filter(Boolean);
    return nameTokens.some((token) => token.startsWith(q));
  });
});

const canSubmitPhoneLogin = computed(() => {
  const phoneDigits = phone.value.replace(/\D/g, "");
  return (
    phoneDigits.length >= 6 &&
    code.value.trim().length >= 4 &&
    !phoneSubmitting.value
  );
});

function handleSelectCountry(item: { name: string; iso2: string; dialCode: string }) {
  selectedCountry.value = item;
  countryPopupVisible.value = false;
  countrySearch.value = "";
}

async function handleSendCode() {
  const phoneDigits = phone.value.replace(/\D/g, "");

  if (!phoneDigits) {
    showToast(t("common.login.errors.missingPhone"));
    return;
  }

  try {
    await sendCode(`${selectedCountry.value.dialCode}${phoneDigits}`);
  } catch (e: unknown) {
    console.error(e);
    showToast(t("common.errors.network"));
  }
}

async function waitForGoogleButtonContainer(): Promise<HTMLElement> {
  for (let i = 0; i < 30; i += 1) {
    await nextTick();
    const el = googleButtonEl.value ?? document.getElementById("buttonDiv");
    if (el) {
      return el;
    }
    await new Promise<void>((resolve) => setTimeout(resolve, 50));
  }
  throw new Error("Missing #buttonDiv");
}

async function ensureRenderGoogleButton(): Promise<void> {
  if (!googleInited.value || googleButtonRendered.value) {
    return;
  }
  if (!window.google?.accounts?.id) {
    return;
  }
  const container = await waitForGoogleButtonContainer();
  window.google.accounts.id.renderButton(container, {
    theme: "outline",
    size: "large",
    width: 350,
    shape: "rectangular",
    logo_alignment: "center",
  });
  googleButtonRendered.value = true;
}

async function handlePhoneLogin() {
  const phoneDigits = phone.value.replace(/\D/g, "");
  const codeValue = code.value.trim();

  if (!phoneDigits) {
    showToast(t("common.login.errors.missingPhone"));
    return;
  }

  if (codeValue.length < 4) {
    showToast(t("common.login.errors.missingCode"));
    return;
  }

  phoneSubmitting.value = true;

  try {
    await oauthToken({
      scope: "server",
      mobile: `${selectedCountry.value.dialCode}${phoneDigits}`,
      code: codeValue,
      grant_type: "mobile",
    });
    emitter.emit(NOTICE_EVENT_LOGIN_SUCCESS);
    await navigateAfterLogin();
  } catch (e: unknown) {
    console.error(e);
    showToast(t("common.errors.network"));
  } finally {
    phoneSubmitting.value = false;
  }
}

type GoogleIdentityServices = {
  accounts: {
    id: {
      initialize: (params: Record<string, unknown>) => void;
      renderButton: (el: Element, options: Record<string, unknown>) => void;
    };
  };
};

declare global {
  interface Window {
    google?: GoogleIdentityServices;
  }
}

function loadGoogleIdentityServices(): Promise<void> {
  if (window.google?.accounts?.id) {
    return Promise.resolve();
  }

  return new Promise((resolve, reject) => {
    const src = "https://accounts.google.com/gsi/client";
    const existing = document.querySelector<HTMLScriptElement>(
      `script[src="${src}"]`,
    );

    if (existing) {
      if (window.google?.accounts?.id) {
        resolve();
        return;
      }

      existing.addEventListener("load", () => resolve(), { once: true });
      existing.addEventListener(
        "error",
        () => reject(new Error("GIS load error")),
        { once: true },
      );
      return;
    }

    const script = document.createElement("script");
    script.src = src;
    script.async = true;
    script.defer = true;
    script.onload = () => resolve();
    script.onerror = () => reject(new Error("GIS load error"));
    document.head.appendChild(script);
  });
}

onMounted(() => {
  loadGoogleIdentityServices()
    .then(() => {
      if (!window.google?.accounts?.id) {
        throw new Error("GIS not available");
      }

      window.google.accounts.id.initialize({
        client_id:
          "237078935964-e2pioe5hlfbcd4gaam4m9sn859iihdb9.apps.googleusercontent.com",
        ux_mode: "popup",
        callback: (response: any) => {
          // 这个 credential 就是 JWT (ID Token)
          const idToken = response.credential;

          if (idToken) {
            oauthToken({ idToken: [idToken], grant_type: 'google', scope: 'server' })
              .then(() => {
                emitter.emit(NOTICE_EVENT_LOGIN_SUCCESS);
                return navigateAfterLogin()
              })
              .catch((e) => {
                console.error(e)
              })
          }
        },
        context: "signin",
      });
      googleInited.value = true;
      return ensureRenderGoogleButton();
    })
    .catch((e) => {
      console.error(e);
    });
});
</script>

<style scoped>
:deep(.login-code-field .van-field__body) {
  align-items: center;
}

:deep(.login-code-field .van-field__control) {
  height: 32px;
  line-height: 32px;
  padding-top: 0;
  padding-bottom: 0;
}

:deep(.login-code-field .van-field__button) {
  display: flex;
  align-items: center;
}

:deep(.login-code-field .van-button--small) {
  height: 32px;
  padding-top: 0;
  padding-bottom: 0;
}

:deep(.country-search.van-search) {
  padding-left: 0;
  padding-right: 0;
}

:deep(.van-button) {
  border-radius: 50px !important;
}

:deep(section .van-cell) {
  padding-left: 0;
  padding-right: 0;

  &::after {
    left: 0;
    right: 0;
  }
}

.login-main-btn {
  height: 44px;
}

:deep(#buttonDiv),
:deep(#buttonDiv > div),
:deep(#buttonDiv > div > div),
:deep(#buttonDiv iframe) {
  border-radius: 50px !important;
  height: 44px !important;
}

:deep([class~="nsm7Bb-HzV7m-LgbsSe"]) {
  height: 44px !important;
  border-radius: 50px !important;
  overflow: visible !important;
}

:deep([class*="nsm7Bb-HzV7m-LgbsSe-MJoBVe"]) {
  height: 44px !important;
  border-radius: 50px !important;
  overflow: hidden !important;
}
</style>
