<script setup lang="ts">
import { TransactionApiClient, type TransactionCategory } from '@/api/transaction'
import ModalWrapper from '@/components/common/ModalWrapper.vue'
import { ref, useTemplateRef, type Ref } from 'vue'
import AppForm from '@/components/common/form/AppForm.vue'
import FormGroup from '@/components/common/form/FormGroup.vue'
import FormControl from '@/components/common/form/FormControl.vue'
import AppButton from '@/components/common/AppButton.vue'
import CategorySelect from './CategorySelect.vue'
import { useRoute } from 'vue-router'
import { getSelectedProfile } from '@/api/profile'

const route = useRoute()
const props = defineProps<{
  category?: TransactionCategory
}>()
const emit = defineEmits<{ saved: [TransactionCategory] }>()
const modal = useTemplateRef('modal')

// Form data:
const name = ref('')
const description = ref('')
const color = ref('ffffff')
const parentId: Ref<number | null> = ref(null)

function show(): Promise<string | undefined> {
  if (!modal.value) return Promise.resolve(undefined)
  name.value = props.category?.name ?? ''
  description.value = props.category?.description ?? ''
  if (props.category) {
    name.value = props.category.name
    description.value = props.category.description ?? ''
    color.value = '#' + props.category.color
    parentId.value = props.category.parentId
  } else {
    name.value = ''
    description.value = ''
    color.value = '#ffffff'
    parentId.value = null
  }
  return modal.value.show()
}

function canSave() {
  const inputValid =
    name.value.trim().length > 0 && color.value.match('^#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})$')
  if (!inputValid) return false
  if (props.category) {
    const prevDescription = props.category.description?.trim() ?? ''
    const currentDescription = description.value.trim()
    const descriptionChanged = prevDescription !== currentDescription
    return (
      props.category.name.trim() !== name.value.trim() ||
      descriptionChanged ||
      props.category.color.trim().toLowerCase() !== color.value.trim().toLowerCase() ||
      props.category.parentId !== parentId.value
    )
  }
  return true
}

async function doSave() {
  const api = new TransactionApiClient(getSelectedProfile(route))
  let desc: string | null = description.value.trim()
  if (desc.length === 0) {
    desc = null
  }
  const payload = {
    name: name.value.trim(),
    description: desc,
    color: color.value.trim().substring(1),
    parentId: parentId.value,
  }
  try {
    let savedCategory = null
    if (props.category) {
      savedCategory = await api.updateCategory(props.category.id, payload)
    } else {
      savedCategory = await api.createCategory(payload)
    }
    emit('saved', savedCategory)
    modal.value?.close('saved')
  } catch (err) {
    console.error(err)
    modal.value?.close()
  }
}

defineExpose({ show })
</script>
<template>
  <ModalWrapper ref="modal">
    <template v-slot:default>
      <h2>{{ category ? 'Edit' : 'Add' }} Category</h2>
      <AppForm>
        <FormGroup>
          <FormControl label="Name">
            <input
              type="text"
              v-model="name"
            />
          </FormControl>
          <FormControl label="Color">
            <input
              type="color"
              v-model="color"
            />
          </FormControl>
          <FormControl
            label="Description"
            style="min-width: 300px"
          >
            <textarea v-model="description"></textarea>
          </FormControl>
          <FormControl label="Parent Category">
            <CategorySelect v-model="parentId"></CategorySelect>
          </FormControl>
        </FormGroup>
      </AppForm>
    </template>
    <template v-slot:buttons>
      <AppButton
        :disabled="!canSave()"
        @click="doSave()"
        >Save</AppButton
      >
      <AppButton
        button-style="secondary"
        @click="modal?.close()"
        >Cancel</AppButton
      >
    </template>
  </ModalWrapper>
</template>
