import { useCallback, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { ROUTE_PATHS } from '../app/route-paths'
import { UploadBundleCard } from '../features/upload/UploadBundleCard'
import { UploadDropZone } from '../features/upload/UploadDropZone'
import { buildCustomSongMeta } from '../features/upload/buildCustomSongMeta'
import { placeholderImageFile } from '../features/upload/file-utils'
import { useUploadBundles } from '../features/upload/useUploadBundles'
import { useCustomSongsStore } from '../stores/custom-songs/store'
import styles from './UploadPage.module.css'

export function UploadPage() {
  const navigate = useNavigate()
  const addSong = useCustomSongsStore((s) => s.addSong)

  const {
    bundles,
    error,
    processing,
    dragOver,
    setDragOver,
    setError,
    setProcessing,
    handleFiles,
    updateBundle,
    removeBundle,
  } = useUploadBundles()

  const [storeInBrowser, setStoreInBrowser] = useState(true)

  const fileInputRef = useRef<HTMLInputElement>(null)

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault()
      setDragOver(false)
      const files = Array.from(e.dataTransfer.files)
      if (files.length > 0) handleFiles(files)
    },
    [handleFiles, setDragOver],
  )

  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault()
    setDragOver(true)
  }, [setDragOver])

  const handleDragLeave = useCallback(() => setDragOver(false), [setDragOver])

  const handleFileInput = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const files = Array.from(e.target.files ?? [])
      if (files.length > 0) handleFiles(files)
      e.target.value = ''
    },
    [handleFiles],
  )

  const handleAdd = useCallback(async () => {
    setProcessing(true)
    try {
      for (const bundle of bundles) {
        const fileMap = new Map<string, File>()
        fileMap.set(bundle.audioFile.name, bundle.audioFile)
        fileMap.set(bundle.chartFile.name, bundle.chartFile)
        const placeholder = placeholderImageFile()
        fileMap.set((bundle.bgFile ?? placeholder).name, bundle.bgFile ?? placeholder)
        fileMap.set(
          (bundle.bannerFile ?? placeholder).name,
          bundle.bannerFile ?? placeholder,
        )

        const meta = buildCustomSongMeta(
          bundle,
          (bundle.bgFile ?? placeholder).name,
          (bundle.bannerFile ?? placeholder).name,
        )

        await addSong(meta, fileMap, storeInBrowser)
      }

      navigate(ROUTE_PATHS.songSelection)
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Failed to add songs')
    } finally {
      setProcessing(false)
    }
  }, [bundles, storeInBrowser, addSong, navigate, setError, setProcessing])

  return (
    <div className={styles.root}>
      <button className={styles.backBtn} onClick={() => navigate(ROUTE_PATHS.songSelection)}>
        &larr; BACK
      </button>

      <h1 className={`${styles.title} font-title`}>ADD TRACK</h1>
      <p className={styles.subtitle}>
        Everything stays on your device &mdash; nothing is uploaded or shared
      </p>

      <UploadDropZone
        dragOver={dragOver}
        fileInputRef={fileInputRef}
        onDrop={handleDrop}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
      />
      <input
        ref={fileInputRef}
        type="file"
        className={styles.fileInput}
        multiple
        accept=".ssc,.sm,.ogg,.mp3,.wav,.zip,.png,.jpg,.jpeg"
        onChange={handleFileInput}
      />

      {processing && <div className={styles.loading}>Processing...</div>}
      {error && <div className={styles.error}>{error}</div>}

      {bundles.length > 0 && (
        <>
          <div className={styles.songList}>
            {bundles.map((bundle) => (
              <UploadBundleCard
                key={bundle.id}
                bundle={bundle}
                onUpdateBundle={updateBundle}
                onRemoveBundle={removeBundle}
              />
            ))}
          </div>

          <div className={styles.actions}>
            <label
              className={styles.optionWithHelp}
              data-tooltip="Saves song files to your browser so they persist across sessions. Without this, uploaded tracks are lost when you close the tab. Uses disk space on this device."
            >
              <input
                type="checkbox"
                checked={storeInBrowser}
                onChange={(e) => setStoreInBrowser(e.target.checked)}
              />
              Store in browser
            </label>
            <button
              className={`${styles.addBtn} font-title`}
              disabled={processing || bundles.length === 0}
              onClick={handleAdd}
            >
              {processing ? 'ADDING...' : `ADD ${bundles.length} TRACK${bundles.length > 1 ? 'S' : ''}`}
            </button>
          </div>
        </>
      )}
    </div>
  )
}
