import { type FileMimeType, downloadFile } from '@zag-js/file-utils'
import { isFunction } from '@zag-js/utils'
import { useEnvironmentContext } from '../../providers/index.tsx'
import type { MaybeAccessor, MaybePromise } from '../../types.ts'
import { runIfFn } from '../../utils/run-if-fn.ts'

export type DownloadableData = string | Blob | File

export interface UseDownloadProps {
  /**
   * The name of the file to download
   */
  fileName: string
  /**
   * The MIME type of the data to download
   */
  mimeType: FileMimeType
  /**
   * The data to download
   */
  data: DownloadableData | (() => MaybePromise<DownloadableData>)
}

export interface UseDownloadReturn {
  /**
   * Triggers the download, resolving `data` first if it's a function or promise.
   */
  download: () => void
}

export const useDownload = (props: MaybeAccessor<UseDownloadProps>): UseDownloadReturn => {
  const env = useEnvironmentContext()

  const download = () => {
    const { fileName, mimeType, data } = runIfFn(props)
    const saveToDisk = (value: DownloadableData) => {
      downloadFile({ file: value, name: fileName, type: mimeType, win: env().getWindow() })
    }
    if (isFunction(data)) {
      const maybePromise = data()
      if (maybePromise instanceof Promise) {
        maybePromise.then(saveToDisk)
      } else {
        saveToDisk(maybePromise)
      }
    } else {
      saveToDisk(data)
    }
  }

  return { download }
}
