<template>
  <Card class="md:w-2/3 w-full">
    <template #title>
      <span v-if="route.params.id">Edit Load</span>
      <span v-else>Add New Load</span>
    </template>
    <template #content>
      <div class="grid grid-cols-1">
        <div>
          Cartridge
        </div>
        <div class="flex flex-row items-center">
          <div class="grow mr-3">
            <Select v-model="load.cartridge" :options="cartridges" optionLabel="label" optionValue="value"
                    class="w-full" />
            <Message v-if="v$.$dirty && v$.cartridge.$invalid" :value="false" size="small" severity="error"
                     variant="simple">Cartridge Required
            </Message>
          </div>
          <div class="cursor-pointer" @click="addCartridgeDialog = true">
            <i :class="icons.add" class="fa-2x" />
          </div>
        </div>

        <div class="mt-3 mr-3">
          Bullet
        </div>
        <div class="w-full mt-3">
          <Select v-model="load.bullet" :invalid="v$.$dirty && v$.bullet.$invalid" :options="bullets"
                  optionLabel="label" optionValue="value" class="w-full" />
          <Message v-if="v$.$dirty && v$.bullet.$invalid" :value="false" size="small" severity="error" variant="simple">
            Bullet Required
          </Message>
        </div>

        <div class="mt-3 mr-3">
          Powder
        </div>
        <div class="flex flex-row">
          <div class="grow mr-3">
            <Select v-model="load.powder" :options="powders" optionLabel="label" optionValue="value" class="w-full" />
            <Message v-if="v$.$dirty && v$.powder.$invalid" :value="false" size="small" severity="error"
                     variant="simple">Powder Required
            </Message>
          </div>
          <div>
            <InputNumber v-model="load.powderGrs" placeholder="00.0 gr" suffix=" gr" :minFractionDigits="1"
                         :maxFractionDigits="1" :min="0"
                         :max="1000" class="w-full" />
            <Message v-if="v$.$dirty && v$.powderGrs.$invalid" :value="false" size="small" severity="error"
                     variant="simple">Grains Required
            </Message>
          </div>
        </div>

        <div class="mt-3 mr-3">
          Primer
        </div>
        <div class="w-full mt-3">
          <Select v-model="load.primer" :options="primers" optionLabel="label" optionValue="value" class="w-full" />
          <Message v-if="v$.$dirty && v$.primer.$invalid" :value="false" size="small" severity="error"
                   variant="simple">Primer Required
          </Message>
        </div>

        <div class="mt-3 mr-3">
          COL
        </div>
        <div class="w-full mt-3">
          <InputMask :unmask="loading" :value="load.col" placeholder="0.000" v-model="load.col" mask="9.999" class="w-full" />
          <Message v-if="v$.$dirty && v$.col.$invalid" :value="false" size="small" severity="error"
                   variant="simple">COL Required
          </Message>
        </div>

        <div class="w-full mt-5">
          <label>Picture</label>
          <Message v-if="v$.$dirty && (!route.params.id && !file)" :value="false" size="small" severity="error"
                   variant="simple">Picture Required
          </Message>
          <div class="w-1/2">
            <img v-if="pictureUrl && route.params.id && !loading" :src="pictureUrl" alt="picture" />
          </div>
          <FileUpload v-model="file" mode="basic" @select="fileSelected" customUpload />
        </div>
      </div>
    </template>
    <template #footer>
      <Button v-if="!route.params.id" label="Add" :icon="icons.add" @click="add" />
      <Button v-else label="Save" :icon="icons.edit" @click="add" />
      <Button class="ml-3" severity="danger" v-if="route.params.id" label="Delete" :icon="icons.delete" @click="deleteLoad" />
    </template>
  </Card>

  <Dialog @update:visible="addCartridgeDialog = false" modal :visible="addCartridgeDialog" :style="{ width: '35rem' }">
    <template #header>
      Add Cartridge
    </template>
    <div class="grid grid-cols-1">
      <div>
        Name
      </div>
      <div class="w-full">
        <InputText :invalid="cartridgeName === ''" v-model="cartridgeName" class="w-full" />
      </div>
    </div>
    <template #footer>
      <Button :disabled="cartridgeName === ''" label="Add" :icon="icons.add" @click="addCartridgeName" />
    </template>
  </Dialog>

  <FullScreenLoader :loading="loading" />
</template>
<script lang="ts">
interface Select {
  label: string
  value: string
}

interface Cartridge {
  id: string
  name: string
}
</script>
<script lang="ts" setup>
import { Bullet } from '../../types/bullet'
import { defineAsyncComponent, onMounted, ref } from 'vue'
import { Primers } from '../../types/primers'
import { Powder } from '../../types/powder'
import axios from 'axios'
import { Load, Response } from '../../types/Response'
import { icons } from '../../lib/icons.ts'
import { FileUploadSelectEvent } from 'primevue/fileupload'
import useVuelidate from '@vuelidate/core'
import { required } from '@vuelidate/validators'
import { useToast } from 'primevue/usetoast'
import { useRoute, useRouter } from 'vue-router'

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

const Card = defineAsyncComponent(() => import('primevue/card'))
const Select = defineAsyncComponent(() => import('primevue/select'))
const Button = defineAsyncComponent(() => import('primevue/button'))
const InputNumber = defineAsyncComponent(() => import('primevue/inputnumber'))
const InputText = defineAsyncComponent(() => import('primevue/inputtext'))
const InputMask = defineAsyncComponent(() => import('primevue/inputmask'))
const FileUpload = defineAsyncComponent(() => import('primevue/fileupload'))
const Dialog = defineAsyncComponent(() => import('primevue/dialog'))
const Message = defineAsyncComponent(() => import('primevue/message'))
const FullScreenLoader = defineAsyncComponent(() => import('../../components/FullScreenLoader.vue'))

const toast = useToast()

const bullets = ref<Select[]>([])
const primers = ref<Select[]>([])
const powders = ref<Select[]>([])
const cartridges = ref<Select[]>([])
const loading = ref(false)

const cartridgeName = ref('')
const addCartridgeDialog = ref(false)

const file = ref<File | null>(null)
const fileSelected = (e: FileUploadSelectEvent) => {
  file.value = e.files[0]
}

const pictureUrl = ref<string | null>(null)
const calcUrl = () => {
  const cache = new Date().getMilliseconds()
  pictureUrl.value =  import.meta.env.VITE_API + `/load/${route.params.id}/photo?cache=${cache}`
}

const load = ref({
  bullet: '',
  cartridge: '',
  powder: '',
  powderGrs: 0,
  primer: '',
  col: '',
})

const v$ = useVuelidate({
  bullet: { required },
  cartridge: { required },
  powder: { required },
  powderGrs: {
    required, min: function (val: number | null) {
      if (!val) return false

      return val > 0
    },
  },
  primer: { required },
  col: {
    required, min: function (val: string | null) {
      if (!val) return false

      // regex to validate COL does not container _
      return !val.includes('_')
    },
  },
}, load.value)

const fetchBullets = async () => {
  const response = await axios.get<any, Response<Bullet[]>>(`${import.meta.env.VITE_API}/bullet`)
  response.data.payload.forEach((bullet: Bullet) => {
    bullets.value.push({ label: `${bullet.manufacturer.name} ${bullet.weight}gr ${bullet.name}`, value: bullet.id })
  })
}
const fetchPrimers = async () => {
  const response = await axios.get<any, Response<Primers[]>>(`${import.meta.env.VITE_API}/primer`)
  response.data.payload.forEach((primer: Primers) => {
    primers.value.push({ label: `${primer.manufacturer.name} ${primer.name}`, value: primer.id })
  })
}
const fetchPowders = async () => {
  const response = await axios.get<any, Response<Powder[]>>(`${import.meta.env.VITE_API}/powder`)
  response.data.payload.forEach((powder: Powder) => {
    powders.value.push({ label: `${powder.manufacturer.name} ${powder.name}`, value: powder.id })
  })
}
const fetchCartridges = async () => {
  cartridges.value = []

  const response = await axios.get<any, Response<Cartridge[]>>(`${import.meta.env.VITE_API}/cartridge`)
  response.data.payload.forEach((cartridge: Cartridge) => {
    cartridges.value.push({ label: `${cartridge.name}`, value: cartridge.id })
  })
}
const addCartridgeName = async () => {
  if (cartridgeName.value === '') {
    return
  }

  try {
    await axios.post<any, Response<Cartridge>>(`${import.meta.env.VITE_API}/cartridge`, {
      name: cartridgeName.value,
    })
  } catch (error) {
    toast.add({
      severity: 'error',
      summary: 'Error',
      detail: 'Error adding cartridge',
    })
  }

  await fetchCartridges()

  cartridgeName.value = ''
  addCartridgeDialog.value = false
}
const add = async () => {
  v$.value.$touch()

  if (v$.value.$invalid || (!route.params.id && !file.value)) {
    toast.add({
      severity: 'error',
      summary: 'Error',
      detail: 'Please correct all fields',
      life: 3000,
    })

    return
  }

  let id = ""

  if (route.params.id) {
    id = "/" + route.params.id.toString()
  }

  const formData = new FormData()
  formData.append('bullet_id', load.value.bullet)
  formData.append('cartridge_id', load.value.cartridge)
  formData.append('powder_id', load.value.powder)
  formData.append('powder_gr', load.value.powderGrs.toString())
  formData.append('primer_id', load.value.primer)
  formData.append('col', load.value.col)
  if (file.value) {
    formData.append('photo', file.value)
  }

  try {
    const response = await axios.post<any, Response<string>>(`${import.meta.env.VITE_API}/load${id}`, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    })

    const message = route.params.id ? 'Load updated' : 'Load added'

    toast.add({
      severity: 'success',
      summary: 'Success',
      detail: message,
      life: 3000,
    })

    if (route.params.id) {
      load.value = {
        bullet: '',
        cartridge: '',
        powder: '',
        powderGrs: 0,
        primer: '',
        col: '',
      }
      file.value = null

      v$.value.$reset()
      await fetchLoad()

      return
    }

    await router.push(`/loads/edit/${response.data.payload}`)
  } catch (error) {
    toast.add({
      severity: 'error',
      summary: 'Error',
      detail: 'Error adding load',
      life: 3000,
    })
  }
}
const deleteLoad = async () => {
  if (!route.params.id) {
    return
  }

  try {
    await axios.delete(`${import.meta.env.VITE_API}/load/${route.params.id}`)

    toast.add({
      severity: 'success',
      summary: 'Success',
      detail: 'Load deleted',
      life: 3000,
    })

    await router.push('/loads/search')
  } catch (error) {
    toast.add({
      severity: 'error',
      summary: 'Error',
      detail: 'Error deleting load',
      life: 3000,
    })
  }
}

const fetchLoad = async () => {
  if (!route.params.id) {
    return
  }

  loading.value = true
  const response = await axios.get<any, Response<Load>>(`${import.meta.env.VITE_API}/load/${route.params.id}`)

  if (response.data.payload) {
    load.value.cartridge = response.data.payload.cartridge_id
    load.value.bullet = response.data.payload.bullet.id
    load.value.powder = response.data.payload.powder.id
    load.value.powderGrs = response.data.payload.powder_gr
    load.value.primer = response.data.payload.primer.id
    load.value.col = response.data.payload.col.toString()

    if (!load.value.col.includes('.')) {
      load.value.col = `${load.value.col}.000`
    } else {
      const parts = load.value.col.split('.')
      if (parts[1].length < 3) {
        load.value.col = `${parts[0]}.${parts[1].padEnd(3, '0')}`
      }
    }

    calcUrl()
  } else {
    toast.add({
      severity: 'error',
      summary: 'Error',
      detail: 'Load not found',
      life: 3000,
    })

    await router.push('/loads')
  }

  loading.value = false
}


onMounted(() => {
  fetchBullets()
  fetchPrimers()
  fetchPowders()
  fetchCartridges()

  if (route.params.id) {
    setTimeout(() => {
      fetchLoad()
    }, 100)
  }
})

</script>