<template>
  <div class="invoice-form">
    <div class="invoice-form__header">
      <div>
        <h2>Payment details</h2>

        <p class="invoice-form__order-id">
          # {{ invoice.orderId }}
        </p>
      </div>

      <InvoiceFormTimer
        :expiration-time="expirationTime"
      />
    </div>

    <div class="invoice-form__body">
      <Transition
        name="shift"
        mode="out-in"
      >
        <Component :is="stepComponent" />
      </Transition>
    </div>

    <p class="invoice-form__network-alert">
      Адрес работает только для получения Tether (USDT) в сети TRC20
    </p>
  </div>
</template>

<script setup lang="ts">
import { useSessionStorage } from '@vueuse/core'
import {
  InvoiceFormStepExpired,
  InvoiceFormStepPending,
  InvoiceFormStepRequisites,
  InvoiceFormStepSuccess,
  InvoiceFormStepUnderpaid,
  InvoiceFormStepWaitingRequisites,
} from '#components'

definePageMeta({
  validate: async (route) => {
    try {
      await $api(`/payments/${route.params.invoiceId}`, {
        method: 'get',
      })

      return true
    }
    catch {
      return false
    }
  },
})

const route = useRoute()
const payedFlag = useSessionStorage(`invoice-${route.params.invoiceId}`, false, { initOnMounted: true })

interface InvoiceTransfer {
  txID: string
  recipient: string
  sender: string
  blockchainCode: string
}

interface PublicInvoice {
  id: string
  orderId: string
  amount: number | string
  collectedAmount: number | string
  currencyCode: string
  expiresAt: string
  blockchainCode?: string
  availableBlockchains: string[]
  walletAddress?: string
  transfers?: InvoiceTransfer[]
}

const { data: invoice, refresh } = await useAsyncData<PublicInvoice>('public-invoice', async () => {
  const nuxtApp = useNuxtApp()

  const invoice = await $api<PublicInvoice>(`/payments/${route.params.invoiceId}`, {
    method: 'get',
  })

  if (new Date(invoice.expiresAt) < new Date() || invoice.walletAddress)
    return invoice

  try {
    const selectedBlockchain = await nuxtApp.runWithContext(async () => {
      return $api<Pick<PublicInvoice, 'expiresAt' | 'walletAddress'>>(`/payments/${route.params.invoiceId}`, {
        method: 'put',
        body: {
          blockchainCode: invoice!.availableBlockchains[0],
        },
      })
    })

    return {
      ...invoice,
      ...selectedBlockchain,
    }
  }
  catch (e) {
    console.error(e)

    return invoice
  }
})

const expirationTime = computed(() => {
  return new Date(invoice.value?.expiresAt ?? 0).getTime()
})

const { isPassed } = useTimer(expirationTime)

const stepComponent = computed(() => {
  const status = invoice.value?.status

  switch (status) {
    case 'pending':
      return InvoiceFormStepWaitingRequisites

    case 'awaiting_payment':
      if (!isPassed.value)
        return InvoiceFormStepRequisites
      else
        return InvoiceFormStepPending

    case 'completed':
      return InvoiceFormStepSuccess

    case 'underpaid':
      return InvoiceFormStepUnderpaid

    case 'overpaid':
      return InvoiceFormStepSuccess
      // return InvoiceFormStepOverpaid

    default:
      return InvoiceFormStepExpired
  }
})

const intervalId = setInterval(refresh, 5000)

watch(payedFlag, () => {
  refresh()
})

onUnmounted(() => {
  clearInterval(intervalId)
})

provide('public-invoice', { invoice, expirationTime, payedFlag })
</script>

<style lang="scss">
.invoice-form {
  width: 532px;
  margin: 0 auto;

  &__header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    padding: 0 16px;
    margin-bottom: 16px;
  }

  &__order-id {
    @include txt-r-sb;

    color: $clr-grey-500;
    margin-top: 4px;
  }

  &__body {
    background: $clr-white;
    border-radius: 12px;
    padding: 16px;
    text-align: center;
  }

  &__network-alert {
    @include txt-i-m;

    text-align: center;
    color: $clr-grey-400;
    padding: 8px 24px;
    margin-top: 10px;
  }

  [data-status-illustration] {
    animation: rotate .8s cubic-bezier(.25,.75,.5,1.25);
  }

  @keyframes rotate {
    from {
      transform: rotateZ(0deg);
    }

    to {
      transform: rotateZ(360deg);
    }
  }
}
</style>
