<script lang='ts' setup>
import type { GenericObject } from "vee-validate";
import type { FormInstance } from "@/utils";
import { loadingController, modalController, toastController } from "@ionic/vue";
import { toTypedSchema } from "@vee-validate/zod";
import { swapVerticalOutline } from "ionicons/icons";
import { ErrorMessage, Field, Form } from "vee-validate";
import { z } from "zod";
import { client, safeClient } from "@/api";
import { AssetCodeEnum } from "@/api/enum";
import { getCryptoIcon } from "@/config/crypto";
import SelectCurrency from "../withdraw/components/select-currency.vue";

const { t } = useI18n();
const router = useRouter();
const walletStore = useWalletStore();
const formRef = useTemplateRef<FormInstance>("formRef");

type AccountType = "funding" | "trading";

interface TransferForm {
  assetCode: AssetCodeEnum;
  amount: string;
  fromAccount: AccountType;
  toAccount: AccountType;
}

const initialValues: TransferForm = {
  assetCode: AssetCodeEnum.USDT,
  amount: "",
  fromAccount: "funding",
  toAccount: "trading",
};
const availableBalance = ref("0");

// 验证规则
const schema = computed(() => toTypedSchema(z.object({
  assetCode: z.string({ message: t("transfer.assetCodeRequired") }).min(1, t("transfer.assetCodeRequired")),
  amount: z
    .union([z.string(), z.number()])
    .refine(value => !Number.isNaN(Number(value)) && Number(value) > 0, { message: t("transfer.amountMinError") })
    .refine(value => Number(value) <= Number(availableBalance.value || 0), { message: t("transfer.amountMaxError", { amount: availableBalance.value }) }),
  fromAccount: z.string({ message: t("transfer.fromAccountRequired") }).min(1, t("transfer.fromAccountRequired")),
  toAccount: z.string({ message: t("transfer.toAccountRequired") }).min(1, t("transfer.toAccountRequired")),
})));

// 监听表单字段变化，自动更新可用余额
watch(() => formRef.value?.getValues(), (values) => {
  if (values?.assetCode && values?.fromAccount) {
    syncAvailableBalance();
  }
}, { deep: true });

async function openSelectCurrency() {
  const modal = await modalController.create({
    component: SelectCurrency,
    componentProps: {
      onSelect: (code: string) => {
        formRef.value?.setFieldValue("assetCode", code);
        syncAvailableBalance();
      },
    },
    breakpoints: [0, 0.8],
    initialBreakpoint: 0.8,
    handle: true,
  });
  await modal.present();
}

// 交换账户
function swapAccounts() {
  const form = formRef.value as any;
  if (!form)
    return;

  const currentFrom = form.values.fromAccount;
  const currentTo = form.values.toAccount;

  form.setFieldValue("fromAccount", currentTo);
  form.setFieldValue("toAccount", currentFrom);

  // 交换账户后重新获取余额
  syncAvailableBalance();
}

// 设置全部金额
function setMaxAmount() {
  const form = formRef.value as any;
  if (!form)
    return;

  form.setFieldValue("amount", availableBalance.value || "0");
}

async function syncAvailableBalance() {
  const values = formRef.value?.getValues();
  if (!values || !values.assetCode || !values.fromAccount)
    return;
  const { data } = await safeClient(client.api.wallet.balance({ assetCode: values.assetCode }).get({
    query: { accountType: values.fromAccount },
  }));
  if (data.value) {
    availableBalance.value = data.value.available;
  }
}

// 提交划转
async function onSubmit(values: GenericObject) {
  const loading = await loadingController.create({
    message: t("transfer.submitting"),
  });
  await loading.present();

  const transferData = values as TransferForm;
  const { error } = await safeClient(() => client.api.account_transfer.post({
    assetCode: transferData.assetCode,
    amount: String(transferData.amount),
    fromAccountType: transferData.fromAccount,
    toAccountType: transferData.toAccount,
  }));

  await loading.dismiss();

  if (!error.value) {
    const toast = await toastController.create({
      message: t("transfer.successMessage"),
      duration: 2000,
      position: "bottom",
      color: "success",
    });

    await toast.present();

    // 刷新余额
    walletStore.syncBalances();

    router.back();
  }
}

// 账户类型显示名称
function getAccountTypeName(type: AccountType) {
  return type === "funding" ? t("transfer.fundingAccount") : t("transfer.tradingAccount");
}
</script>

<template>
  <ion-page>
    <ion-header>
      <ion-toolbar class="ion-toolbar">
        <ion-buttons slot="start">
          <ui-back-button default-href="/wallet/index" />
        </ion-buttons>
        <ion-title>{{ t("transfer.title") }}</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true" class="ion-padding">
      <Form
        ref="formRef"
        :validation-schema="schema"
        :initial-values="initialValues"
        @submit="onSubmit"
      >
        <div class="flex flex-col gap-5">
          <!-- 币种选择 -->
          <div>
            <Field name="assetCode">
              <template #default="{ value }">
                <ion-label class="block text-sm font-medium mb-2">
                  选择币种
                </ion-label>
                <div
                  class="flex items-center justify-between bg-text-900 rounded-2xl p-4 cursor-pointer"
                  @click="openSelectCurrency"
                >
                  <div class="flex items-center gap-3">
                    <component :is="getCryptoIcon(value)" class="w-8 h-8" />
                    <span class="text-base font-medium">{{ value }}</span>
                  </div>
                  <ion-icon name="chevron-forward-outline" class="text-text-400" />
                </div>
              </template>
            </Field>
            <ErrorMessage name="assetCode" class="text-red-500 text-xs mt-1" />
          </div>

          <!-- 划转账户 -->
          <div class="relative flex flex-col gap-3">
            <Field name="fromAccount">
              <template #default="{ value }">
                <div class="flex flex-col bg-text-900 rounded-2xl p-3">
                  <span class="text-xs text-text-500">{{ t('transfer.from') }}</span>
                  <div class="pt-2">
                    <span class="text-base font-medium">{{ getAccountTypeName(value) }}</span>
                  </div>
                </div>
              </template>
            </Field>

            <div class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10">
              <ion-button
                fill="solid"
                color="primary"
                class="swap-btn"
                @click="swapAccounts"
              >
                <ion-icon slot="icon-only" :icon="swapVerticalOutline" class="text-xl" />
              </ion-button>
            </div>

            <Field name="toAccount">
              <template #default="{ value }">
                <div class="flex flex-col bg-text-900 rounded-2xl p-3">
                  <span class="text-xs text-text-500">{{ t('transfer.to') }}</span>
                  <div class="pt-2">
                    <span class="text-base font-medium">{{ getAccountTypeName(value) }}</span>
                  </div>
                </div>
              </template>
            </Field>
          </div>

          <!-- 划转数量 -->
          <div>
            <Field name="amount">
              <template #default="{ field }">
                <div class="relative">
                  <ui-input-label
                    v-bind="field"
                    :label="t('transfer.amount')"
                    :placeholder="t('transfer.enterAmount')"
                    type="number"
                    inputmode="decimal"
                  />
                  <ion-button
                    fill="clear"
                    size="small"
                    class="absolute right-0 top-10.5 text-sm font-semibold z-10"
                    @click="setMaxAmount"
                  >
                    全部
                  </ion-button>
                </div>
              </template>
            </Field>
            <ErrorMessage name="amount" class="text-red-500 text-xs mt-1" />
          </div>

          <!-- 可用余额 -->
          <div class="flex items-center gap-2">
            <span class="text-sm text-(--ion-color-medium)">{{ t("transfer.available") }}</span>
            <span class="text-sm font-medium">{{ Number(availableBalance).toFixed(2) }}</span>
          </div>

          <!-- 提交按钮 -->
          <ion-button
            expand="block"
            type="submit"
            shape="round"
            class="mt-4 h-12 font-semibold"
          >
            {{ t("transfer.submit") }}
          </ion-button>
        </div>
      </Form>
    </ion-content>
  </ion-page>
</template>

<style lang="css" scoped>
.swap-btn {
  --border-radius: 100%;
}
</style>
