/**
 * StepPreUpload — STEP file uploader used during order creation (before an
 * order ID exists).  Files are uploaded immediately to /api/uploads/step so
 * we have cad_file_ids ready.  Client-side filename matching gives the user
 * live feedback on which Excel rows already have a STEP file.
 */
import { useState, useCallback } from 'react'
import { useDropzone } from 'react-dropzone'
import { Upload, CheckCircle, XCircle, Loader2, FileBox } from 'lucide-react'
import { toast } from 'sonner'
import api from '../../api/client'

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface StepUploadResponse {
  cad_file_id: string
  original_name: string
  file_hash: string
  status: string
}

type FileStatus = 'uploading' | 'done' | 'error'

interface FileEntry {
  file: File
  status: FileStatus
  errorMsg?: string
  cadFileId?: string
}

export interface StepUploadState {
  ids: string[]        // cad_file_ids of successfully uploaded files
  names: string[]      // original_names of successfully uploaded files
}

interface Props {
  /** name_cad_modell values from parsed rows — used for match preview */
  itemNames: string[]
  /** Called whenever the set of successfully uploaded files changes */
  onUpdate: (state: StepUploadState) => void
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function normStem(name: string): string {
  return name.trim().toLowerCase().replace(/\.(step|stp)$/i, '')
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export default function StepPreUpload({ itemNames, onUpdate }: Props) {
  const [entries, setEntries] = useState<FileEntry[]>([])

  const getSuccessState = (updated: FileEntry[]): StepUploadState => ({
    ids: updated.filter((e) => e.status === 'done' && e.cadFileId).map((e) => e.cadFileId!),
    names: updated.filter((e) => e.status === 'done').map((e) => e.file.name),
  })

  const onDrop = useCallback(
    async (accepted: File[]) => {
      if (accepted.length === 0) return

      const startIdx = entries.length
      const newEntries: FileEntry[] = accepted.map((f) => ({ file: f, status: 'uploading' }))
      const merged = [...entries, ...newEntries]
      setEntries(merged)

      let working = [...merged]

      for (let i = 0; i < accepted.length; i++) {
        const idx = startIdx + i
        const file = accepted[i]
        const form = new FormData()
        form.append('file', file)
        try {
          const res = await api.post<StepUploadResponse>('/uploads/step', form, {
            headers: { 'Content-Type': 'multipart/form-data' },
          })
          working = working.map((e, j) =>
            j === idx ? { ...e, status: 'done', cadFileId: res.data.cad_file_id } : e,
          )
        } catch (err: any) {
          const msg: string = err?.response?.data?.detail ?? err?.message ?? 'Upload failed'
          working = working.map((e, j) =>
            j === idx ? { ...e, status: 'error', errorMsg: msg } : e,
          )
          toast.error(`${file.name}: ${msg}`)
        }
        setEntries([...working])
      }

      onUpdate(getSuccessState(working))
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [entries, onUpdate],
  )

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: { 'application/octet-stream': ['.stp', '.step'] },
    multiple: true,
  })

  // Client-side match preview
  const uploadedStems = new Set(
    entries.filter((e) => e.status === 'done').map((e) => normStem(e.file.name)),
  )
  const matched = itemNames.filter((n) => uploadedStems.has(normStem(n)))
  const missing = itemNames.filter((n) => !uploadedStems.has(normStem(n)))

  return (
    <div className="space-y-4">
      {/* Match status bar */}
      {itemNames.length > 0 && (
        <div className="flex items-center gap-3 text-sm">
          <div className="flex items-center gap-1.5 text-status-success-text">
            <CheckCircle size={15} className="shrink-0" />
            <span><strong>{matched.length}</strong> matched</span>
          </div>
          {missing.length > 0 && (
            <div className="flex items-center gap-1.5 text-amber-600">
              <FileBox size={15} className="shrink-0" />
              <span><strong>{missing.length}</strong> still need a STEP file</span>
            </div>
          )}
          {missing.length === 0 && (
            <span className="text-status-success-text font-medium">All items covered ✓</span>
          )}
        </div>
      )}

      {/* Drop zone */}
      <div
        {...getRootProps()}
        className={[
          'border-2 border-dashed rounded-xl p-6 text-center cursor-pointer transition-colors',
          isDragActive
            ? 'border-accent bg-status-success-bg'
            : 'border-border-default hover:border-border-default bg-surface-alt',
        ].join(' ')}
      >
        <input {...getInputProps()} />
        <Upload size={28} className="mx-auto mb-2 text-content-muted" />
        {isDragActive ? (
          <p className="text-accent font-medium">Drop STEP files here</p>
        ) : (
          <>
            <p className="text-content-secondary font-medium">Drag & drop .stp / .step files</p>
            <p className="text-sm text-content-muted mt-1">or click to browse — multiple files at once</p>
          </>
        )}
      </div>

      {/* Uploaded file list */}
      {entries.length > 0 && (
        <ul className="divide-y divide-border-light rounded-lg border border-border-default bg-surface overflow-hidden">
          {entries.map((entry, idx) => {
            const stem = normStem(entry.file.name)
            const isMatched = itemNames.some((n) => normStem(n) === stem)
            return (
              <li key={idx} className="flex items-center gap-3 px-4 py-2.5">
                {entry.status === 'uploading' && (
                  <Loader2 size={15} className="animate-spin text-blue-500 shrink-0" />
                )}
                {entry.status === 'done' && (
                  <CheckCircle size={15} className={isMatched ? 'text-green-500 shrink-0' : 'text-amber-400 shrink-0'} />
                )}
                {entry.status === 'error' && (
                  <XCircle size={15} className="text-red-500 shrink-0" />
                )}
                <div className="flex-1 min-w-0">
                  <p className="text-sm font-medium text-content truncate">{entry.file.name}</p>
                  {entry.status === 'error' && (
                    <p className="text-xs text-red-500">{entry.errorMsg}</p>
                  )}
                  {entry.status === 'done' && !isMatched && (
                    <p className="text-xs text-amber-600">No matching row in Excel</p>
                  )}
                </div>
                {entry.status === 'uploading' && (
                  <span className="text-xs text-blue-500 shrink-0">Uploading…</span>
                )}
                {entry.status === 'done' && (
                  <span className={`text-xs shrink-0 ${isMatched ? 'text-green-600' : 'text-amber-500'}`}>
                    {isMatched ? 'Matched' : 'Unmatched'}
                  </span>
                )}
              </li>
            )
          })}
        </ul>
      )}

      {/* Missing items list */}
      {missing.length > 0 && entries.some((e) => e.status === 'done') && (
        <div className="rounded-lg border border-border-default bg-status-warning-bg p-3">
          <p className="text-xs font-semibold text-status-warning-text mb-1.5">
            Still missing ({missing.length}):
          </p>
          <div className="flex flex-wrap gap-1">
            {missing.slice(0, 12).map((name) => (
              <span
                key={name}
                className="text-xs font-mono bg-status-warning-bg text-status-warning-text px-1.5 py-0.5 rounded border border-border-default"
              >
                {name}
              </span>
            ))}
            {missing.length > 12 && (
              <span className="text-xs text-status-warning-text">+{missing.length - 12} more</span>
            )}
          </div>
        </div>
      )}
    </div>
  )
}
