<script lang="ts" setup>
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import useStorage from '@/stores/storage'
import FileForm from './FileForm.vue'
import UploadExistDialog from './UploadExistDialog.vue'

const storageStore = useStorage()
const { file, currentInfo } = storeToRefs(storageStore)
const { createFile, updateFile, goto } = storageStore

const fileFormState = ref<boolean>(false)
const fileFormPath = ref<string>('')
const fileFormData = ref<{
  file?: File
  title?: string
  description?: string
  keyword?: string[]
  category?: string[]
  author?: string
  metadata?: Record<string, unknown>
}>({})
const fileFormType = ref<'edit' | 'create'>('create')
const fileFormError = ref<{
  externalFileExist?: boolean
  fileExist?: boolean
  fileName2Long?: boolean
}>({})
const fileExistNotification = ref<boolean>(false)
const errorState = ref<'fileExist' | 'externalFileExist'>('fileExist')
const fileFormComponent = ref<InstanceType<typeof FileForm>>()
const fileNameLabel = ref<string>()

function triggerFileCreate() {
  fileFormType.value = 'create'
  fileFormData.value = {}
  fileFormState.value = !fileFormState.value
}

function triggerFileEdit(
  value: {
    title: string
    description: string
    keyword: string[]
    category: string[]
    author: string
    metadata?: Record<string, unknown>
  },
  pathname: string,
  file?: string,
) {
  fileFormState.value = true
  fileFormType.value = 'edit'
  fileFormPath.value = pathname
  fileFormData.value = {
    title: (value.metadata?.subject as string) ?? value.title,
    description: value.description,
    keyword: value.keyword,
    category: value.category,
    author: (value.metadata?.author as string) ?? value.author,
    metadata: value.metadata,
  }
  fileNameLabel.value = file

  const arr = pathname.split('/')
  arr[arr.length - 1] = ''
  goto(arr.join('/'))
}

defineExpose({
  triggerFileCreate,
  triggerFileEdit,
})

const currentParam = ref<Parameters<typeof submitFileForm>[0]>()

function checkFileExistMetadata(name: string) {
  const fileInfo = file.value[currentInfo.value.path].find(
    (v) => v.fileName === name,
  )

  if (fileInfo?.metadata && Object.keys(fileInfo?.metadata).length > 0) {
    return Boolean(true)
  }

  return Boolean(false)
}

function checkFileExist(name: string, except?: string) {
  return Boolean(
    file.value[currentInfo.value.path].find(
      (v) => v.fileName === name && v.fileName !== except,
    ),
  )
}

function checkFileName2Long(name: string, except?: string) {
  return name !== except && Boolean(name.length > 85)
}

async function submitFileForm(
  value: {
    mode: 'create' | 'edit'
    file?: File
    title: string
    description: string
    keyword: string[]
    category: string[]
    author: string
  },
  force = false,
) {
  currentParam.value = value

  const fileInfo = file.value[currentInfo.value.path]?.find(
    (v) => v.fileName === value.file?.name,
  )

  if (fileInfo?.metadata && Object.keys(fileInfo.metadata).length > 0) {
    fileExistNotification.value = true
    errorState.value = 'externalFileExist'
    return
  }

  if (
    value.file &&
    file.value[currentInfo.value.path].find(
      (v) => v.fileName === value.file?.name,
    ) &&
    !force
  ) {
    fileExistNotification.value = true
    errorState.value = 'fileExist'
    return
  }

  if (value.mode === 'create' && value.file) {
    await createFile(value.file, {
      title: value.title,
      description: value.description,
      keyword: value.keyword,
      category: value.category,
      author: value.author,
    })
  } else {
    await updateFile(
      fileFormPath.value,
      {
        title: value.title,
        description: value.description,
        keyword: value.keyword,
        category: value.category,
        author: value.author,
      },
      value.file,
    )
  }
  fileFormData.value = {}
  fileFormState.value = false
  currentParam.value = undefined
  fileFormComponent.value?.reset()
}
</script>

<template>
  <file-form
    ref="fileFormComponent"
    :mode="fileFormType"
    :error="fileFormError"
    :fileNameLabel="fileNameLabel"
    :disableFields="
      fileFormData.metadata && Object.keys(fileFormData.metadata).length > 0
        ? ['file', 'title', 'author']
        : []
    "
    v-model:open="fileFormState"
    v-model:title="fileFormData.title"
    v-model:description="fileFormData.description"
    v-model:keyword="fileFormData.keyword"
    v-model:category="fileFormData.category"
    v-model:author="fileFormData.author"
    @reset="() => (fileFormError = {})"
    @filechange="
      (name: string) => {
        fileFormError.externalFileExist = checkFileExistMetadata(name)
        ;(fileFormError.fileExist = checkFileExist(name, fileNameLabel)),
          (fileFormError.fileName2Long = checkFileName2Long(
            name,
            fileNameLabel,
          ))
      }
    "
    @submit="submitFileForm"
  />
  <upload-exist-dialog
    v-model:notification="fileExistNotification"
    v-model:errorState="errorState"
    @confirm="() => currentParam && submitFileForm(currentParam, true)"
    @cancel="() => (currentParam = undefined)"
  />
</template>
