import "@contentstack/venus-components/build/main.css"

import { Suspense, lazy, useEffect, useState } from "react"
import { useScript } from "usehooks-ts"
import useApp from "~/hooks/useApp"

import Disclaimer from "~/components/Disclaimer"
import InvalidConfig from "~/components/InvalidConfig"

import { GenericObjectType } from "@contentstack/app-sdk/dist/src/types/common.types"
import UiLocation from "@contentstack/app-sdk/dist/src/uiLocation"
import type { ImageVaultAsset, InsertResponse } from "~/types/imagevault"
import {
  getImageVaultAssetFromData,
  isImageVaultDAMConfig,
} from "~/utils/imagevault"

const ImageVaultDAM = lazy(() => import("~/components/ImageVaultDAM"))

interface FieldContentProps {
  sdk?: UiLocation
  appConfig?: GenericObjectType
}

function FieldContent({ sdk, appConfig }: FieldContentProps) {
  const ivStatus = useScript(
    "/scripts/imagevault-insert-media/insertmediawindow.min.js"
  )

  const [showDisclaimer, setShowDisclaimer] = useState(false)
  const [fieldData, setFieldData] = useState<
    InsertResponse | ImageVaultAsset | null
  >()
  const [dataIsLoaded, setDataIsLoaded] = useState(false)

  const entry = sdk?.location.CustomField?.entry
  const field = sdk?.location.CustomField?.field

  useEffect(() => {
    // If we can get field data from the SDK that means the entry has been
    // saved at least once. If this is true, we are guaranteed entry UID.
    // Entry that has not been saved does not have a entry UID and therefore
    // cannot be referred to by ImageVault. Entry title is also required by us.
    try {
      if (field && entry) {
        const data = field.getData()
        const title = entry.getField("title").getData().toString()
        if (!title) {
          throw new Error("Missing title for entry")
        }

        if (data) {
          setFieldData(data as InsertResponse)
        }

        setDataIsLoaded(true)
      }
    } catch (e) {
      setShowDisclaimer(true)
      console.log("Unable to get field data from SDK: ", e)
    }
  }, [entry, field])

  if (showDisclaimer) {
    return <Disclaimer />
  }

  const loaded = !!(dataIsLoaded && ivStatus === "ready" && sdk && appConfig)

  const initialData =
    fieldData && Object.keys(fieldData).length > 0 ? fieldData : null

  if (!loaded) {
    return <p style={{ fontFamily: "Inter" }}> Loading dependencies...</p>
  }

  if (!isImageVaultDAMConfig(appConfig)) {
    return <InvalidConfig />
  }

  const fieldConfig = sdk.location.CustomField?.fieldConfig
  const config = { ...appConfig, ...fieldConfig }

  // The existing data might still be in InsertResponse format if the user has not edited it yet.
  // We'll convert it to ImageVaultAsset when the user edits the the entry.
  const imageVaultAsset = getImageVaultAssetFromData(initialData)

  return (
    <Suspense fallback={<p>Loading field...</p>}>
      <ImageVaultDAM
        config={config}
        sdk={sdk}
        imageVaultAsset={imageVaultAsset}
      />
    </Suspense>
  )
}

export default function Field() {
  const { sdk, config, ref } = useApp()

  return (
    <div ref={ref}>
      <FieldContent sdk={sdk} appConfig={config} />
    </div>
  )
}
