<script setup lang="ts">
import { formatMoney } from '@/api/data'
import { defaultPage, type Page, type PageRequest } from '@/api/pagination'
import { getSelectedProfile } from '@/api/profile'
import {
  TransactionApiClient,
  type TransactionCategoryBalance,
  type TransactionCategory,
  type TransactionsListItem,
} from '@/api/transaction'
import AppBadge from '@/components/common/AppBadge.vue'
import AppPage from '@/components/common/AppPage.vue'
import FormControl from '@/components/common/form/FormControl.vue'
import FormGroup from '@/components/common/form/FormGroup.vue'
import PaginationControls from '@/components/common/PaginationControls.vue'
import TransactionCard from '@/components/TransactionCard.vue'
import { onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'

const route = useRoute()
const router = useRouter()

const category = ref<TransactionCategory | undefined>()
const parentCategory = ref<TransactionCategory | undefined>()
const childCategories = ref<TransactionCategory[]>([])
const relatedTransactionsPage = ref<Page<TransactionsListItem>>(defaultPage())
const balances = ref<TransactionCategoryBalance[]>([])
const balancesIncludeSubcategories = ref(true)

// Watch for changes to the route ID, and reload the category in that case.
watch(
  () => route.params.id,
  (newId) => loadCategory(parseInt(newId as string)),
)
// Watch for updates to balance input fields and refresh.
watch(balancesIncludeSubcategories, async () => {
  if (!category.value) return
  balances.value = await new TransactionApiClient(getSelectedProfile(route)).getCategoryBalances(
    category.value.id,
    balancesIncludeSubcategories.value,
  )
})

onMounted(async () => {
  const categoryId = parseInt(route.params.id as string)
  await loadCategory(categoryId)
})

async function loadCategory(id: number) {
  category.value = undefined
  parentCategory.value = undefined
  childCategories.value = []
  balances.value = []
  balancesIncludeSubcategories.value = true
  relatedTransactionsPage.value = defaultPage()
  try {
    const api = new TransactionApiClient(getSelectedProfile(route))
    category.value = await api.getCategory(id)
    if (category.value.parentId !== null) {
      parentCategory.value = await api.getCategory(category.value.parentId)
    }
    childCategories.value = await api.getChildCategories(category.value.id)
    balances.value = await api.getCategoryBalances(
      category.value.id,
      balancesIncludeSubcategories.value,
    )
    await fetchPage(1)
  } catch (err) {
    console.error(err)
    await router.replace('/')
  }
}

async function fetchPage(pg: number) {
  if (!category.value) return
  const pageRequest: PageRequest = {
    page: pg,
    size: 10,
    sorts: [
      {
        attribute: 'txn.timestamp',
        dir: 'DESC',
      },
    ],
  }
  const params = new URLSearchParams()
  params.append('category', category.value?.id + '')
  const api = new TransactionApiClient(getSelectedProfile(route))
  relatedTransactionsPage.value = await api.searchTransactions(params, pageRequest)
}
</script>
<template>
  <AppPage
    v-if="category"
    :title="'Category - ' + category.name"
  >
    <!-- Initial subtext with color & parent (if available). -->
    <div>
      <span
        class="category-color-indicator"
        :style="{ 'background-color': '#' + category.color }"
      ></span>
      <span
        v-if="parentCategory"
        class="text-muted"
        style="vertical-align: middle"
      >
        A subcategory of
        <RouterLink
          :to="`/profiles/${getSelectedProfile(route)}/categories/${parentCategory.id}`"
          >{{ parentCategory.name }}</RouterLink
        >.
      </span>
      <span
        v-if="!parentCategory"
        class="text-muted"
        style="vertical-align: middle"
      >
        This is a top-level category.
      </span>
    </div>

    <p>
      {{ category.description }}
    </p>

    <div v-if="childCategories.length > 0">
      <h3>Subcategories</h3>
      <ul>
        <li
          v-for="child in childCategories"
          :key="child.id"
        >
          <RouterLink :to="`/profiles/${getSelectedProfile(route)}/categories/${child.id}`"
            >{{ child.name }}
          </RouterLink>
        </li>
      </ul>
    </div>

    <!-- Display total balances. -->
    <div v-if="balances.length > 0">
      <h3>Balances</h3>
      <div
        v-for="balance in balances"
        :key="balance.currency.code"
      >
        USD:
        <AppBadge
          >Debits:
          <span class="text-positive">{{ formatMoney(balance.debits, balance.currency) }}</span>
        </AppBadge>
        <AppBadge
          >Credits:
          <span class="text-negative">{{ formatMoney(balance.credits, balance.currency) }}</span>
        </AppBadge>
        <AppBadge
          >Balance:
          <span
            :class="{ 'text-positive': balance.balance > 0, 'text-negative': balance.balance < 0 }"
            >{{ formatMoney(balance.balance, balance.currency) }}</span
          >
        </AppBadge>
      </div>
      <FormGroup>
        <FormControl
          label="Include Subcategories"
          v-if="childCategories.length > 0"
        >
          <input
            type="checkbox"
            v-model="balancesIncludeSubcategories"
          />
        </FormControl>
        <!--
        <FormControl label="After">
          <input type="date" />
        </FormControl>
        <FormControl label="Before">
          <input type="date" />
        </FormControl>
        -->
      </FormGroup>
    </div>

    <div>
      <h3 class="mb-0">Transactions</h3>
      <p class="text-muted font-size-small mt-0">
        Below is a list of all transactions recorded with this category, or any subcategory.
      </p>
      <PaginationControls
        :page="relatedTransactionsPage"
        @update="(pr) => fetchPage(pr.page)"
        class="align-right"
      />
      <TransactionCard
        v-for="txn in relatedTransactionsPage.items"
        :key="txn.id"
        :tx="txn"
      />
      <p
        v-if="relatedTransactionsPage.totalElements === 0"
        class="text-muted font-italic"
      >
        There are no transactions linked to this category.
      </p>
    </div>
  </AppPage>
</template>
<style lang="css">
.category-color-indicator {
  display: inline-block;
  vertical-align: middle;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 0.2rem solid black;
}
</style>
