<script setup lang="ts">
import { ApiError } from '@/api/base'
import { formatMoney } from '@/api/data'
import { getSelectedProfile } from '@/api/profile'
import { TransactionApiClient, type TransactionDetail } from '@/api/transaction'
import AppButton from '@/components/common/AppButton.vue'
import AppPage from '@/components/common/AppPage.vue'
import CategoryLabel from '@/components/CategoryLabel.vue'
import PropertiesTable from '@/components/PropertiesTable.vue'
import TagLabel from '@/components/TagLabel.vue'
import { showAlert, showConfirm } from '@/util/alert'
import { onMounted, ref, type Ref } from 'vue'
import AttachmentRow from '@/components/common/AttachmentRow.vue'
import LineItemCard from '@/components/LineItemCard.vue'
import AppBadge from '@/components/common/AppBadge.vue'
import ButtonBar from '@/components/common/ButtonBar.vue'
import { AccountApiClient } from '@/api/account'
import { useRoute, useRouter } from 'vue-router'

interface BalanceDiff {
  before: number
  after: number
}

const route = useRoute()
const router = useRouter()
const transactionApi = new TransactionApiClient(getSelectedProfile(route))

const transaction: Ref<TransactionDetail | undefined> = ref()
const creditedAccountBalanceDiff = ref<BalanceDiff | undefined>()
const debitedAccountBalanceDiff = ref<BalanceDiff | undefined>()

onMounted(async () => {
  const transactionId = parseInt(route.params.id as string)
  try {
    transaction.value = await transactionApi.getTransaction(transactionId)
    fetchBalanceDiffs()
  } catch (err) {
    console.error(err)
    await router.replace('/')
    if (err instanceof ApiError) {
      await showAlert('Failed to fetch transaction: ' + err.message)
    }
  }
})

async function fetchBalanceDiffs() {
  const txn = transaction.value
  if (!txn) return
  const txnTime = new Date(txn.timestamp).getTime()
  const beforeTs = new Date(txnTime - 1000)
  const afterTs = new Date(txnTime + 1000)
  const accountApi = new AccountApiClient(route)
  const p1: Promise<number | undefined> = txn.creditedAccount
    ? accountApi.getBalance(txn.creditedAccount.id, beforeTs)
    : Promise.resolve(undefined)
  const p2: Promise<number | undefined> = txn.creditedAccount
    ? accountApi.getBalance(txn.creditedAccount.id, afterTs)
    : Promise.resolve(undefined)
  const p3: Promise<number | undefined> = txn.debitedAccount
    ? accountApi.getBalance(txn.debitedAccount.id, beforeTs)
    : Promise.resolve(undefined)
  const p4: Promise<number | undefined> = txn.debitedAccount
    ? accountApi.getBalance(txn.debitedAccount.id, afterTs)
    : Promise.resolve(undefined)
  const results = await Promise.all([p1, p2, p3, p4])
  if (results[0] !== undefined && results[1] !== undefined) {
    creditedAccountBalanceDiff.value = { before: results[0], after: results[1] }
  }
  if (results[2] !== undefined && results[3] !== undefined) {
    debitedAccountBalanceDiff.value = { before: results[2], after: results[3] }
  }
}

async function deleteTransaction() {
  if (!transaction.value) return
  const conf = await showConfirm(
    'Are you sure you want to delete this transaction? This will permanently delete all data pertaining to this transaction, and it cannot be recovered.',
  )
  if (!conf) return
  try {
    await transactionApi.deleteTransaction(transaction.value.id)
    await router.replace(`/profiles/${getSelectedProfile(route)}`)
  } catch (err) {
    console.error(err)
  }
}

async function onVendorClicked() {
  if (transaction.value && transaction.value.vendor) {
    await router.push(
      `/profiles/${getSelectedProfile(route)}/vendors/${transaction.value.vendor.id}`,
    )
  }
}
</script>
<template>
  <AppPage
    :title="'Transaction ' + transaction.id"
    v-if="transaction"
  >
    <!-- Top-row with some badges for amount, vendor, and category. -->
    <div>
      <AppBadge
        size="lg"
        class="font-mono"
      >
        {{ transaction.currency.code }} {{ formatMoney(transaction.amount, transaction.currency) }}
      </AppBadge>
      <AppBadge
        size="md"
        v-if="transaction.vendor"
        style="cursor: pointer"
        @click="onVendorClicked()"
      >
        {{ transaction.vendor.name }}
      </AppBadge>
      <CategoryLabel
        v-if="transaction.category"
        :category="transaction.category"
        :clickable="true"
      />
      <AppBadge
        size="sm"
        v-if="transaction.internalTransfer"
      >
        <font-awesome-icon icon="fa-rotate"></font-awesome-icon>
        Internal Transfer
      </AppBadge>
    </div>
    <!-- Second row that lists all tags. -->
    <div
      v-if="transaction.tags.length > 0"
      class="mt-1"
    >
      <TagLabel
        v-for="t in transaction.tags"
        :key="t"
        :tag="t"
      />
    </div>

    <p style="white-space: pre-wrap">{{ transaction.description }}</p>

    <div
      v-if="transaction.creditedAccount"
      class="my-1"
    >
      <strong class="text-negative">Credited</strong> from
      <RouterLink
        :to="`/profiles/${getSelectedProfile(route)}/accounts/${transaction.creditedAccount.id}`"
      >
        {{ transaction.creditedAccount.name }} (#{{ transaction.creditedAccount.numberSuffix }})
      </RouterLink>
      <div
        v-if="creditedAccountBalanceDiff"
        class="font-size-xsmall"
      >
        Balance Before:
        <span class="font-mono">
          {{ formatMoney(creditedAccountBalanceDiff.before, transaction.currency) }}
        </span>
        / After:
        <span class="font-mono">
          {{ formatMoney(creditedAccountBalanceDiff.after, transaction.currency) }}
        </span>
      </div>
    </div>

    <div
      v-if="transaction.debitedAccount"
      class="my-1"
    >
      <strong class="text-positive">Debited</strong> to
      <RouterLink
        :to="`/profiles/${getSelectedProfile(route)}/accounts/${transaction.debitedAccount.id}`"
      >
        {{ transaction.debitedAccount.name }} (#{{ transaction.debitedAccount.numberSuffix }})
      </RouterLink>
      <div
        v-if="debitedAccountBalanceDiff"
        class="font-size-xsmall"
      >
        Balance Before:
        <span class="font-mono">
          {{ formatMoney(debitedAccountBalanceDiff.before, transaction.currency) }}
        </span>
        / After:
        <span class="font-mono">
          {{ formatMoney(debitedAccountBalanceDiff.after, transaction.currency) }}
        </span>
      </div>
    </div>

    <!-- All remaining properties are put in this table. -->
    <PropertiesTable>
      <tr>
        <th>Timestamp</th>
        <td>{{ new Date(transaction.timestamp).toLocaleString() }}</td>
      </tr>
      <tr>
        <th>Added to Finnow</th>
        <td>{{ new Date(transaction.addedAt).toLocaleString() }}</td>
      </tr>
    </PropertiesTable>

    <div v-if="transaction.lineItems.length > 0">
      <h3>Line Items</h3>
      <LineItemCard
        v-for="item of transaction.lineItems"
        :key="item.idx"
        :line-item="item"
        :currency="transaction.currency"
        :total-count="transaction.lineItems.length"
        :editable="false"
      />
    </div>

    <div v-if="transaction.attachments.length > 0">
      <h3>Attachments</h3>
      <AttachmentRow
        v-for="a in transaction.attachments"
        :attachment="a"
        :key="a.id"
        disabled
      />
    </div>
    <ButtonBar>
      <AppButton
        icon="wrench"
        @click="
          router.push(`/profiles/${getSelectedProfile(route)}/transactions/${transaction?.id}/edit`)
        "
      >
        Edit
      </AppButton>
      <AppButton
        icon="trash"
        @click="deleteTransaction()"
        >Delete</AppButton
      >
    </ButtonBar>
  </AppPage>
</template>
