import { useState } from 'react'
import Modal from '@/components/ui/Modal'
import Button from '@/components/ui/Button'
import FormField from '@/components/ui/FormField'
import api from '@/lib/api'

function countSteps(stepsStr) {
  if (!stepsStr || !stepsStr.trim()) return 0
  return stepsStr.trim().split(',').length
}

function computeStepsAndNotes(stepsStr) {
  if (!stepsStr || !stepsStr.trim()) return { steps: 0, totalNotes: 0 }
  const tokens = stepsStr.trim().split(',')
  const bellSet = new Set()
  for (const token of tokens) {
    for (const part of token.split('+')) {
      const n = parseInt(part.trim(), 10)
      if (!isNaN(n) && n >= 1 && n <= 16) bellSet.add(n)
    }
  }
  return { steps: tokens.length, totalNotes: bellSet.size || 1 }
}

function validateSteps(stepsStr) {
  if (!stepsStr || !stepsStr.trim()) return 'Steps are required.'
  const tokens = stepsStr.trim().split(',')
  for (const token of tokens) {
    const parts = token.split('+')
    for (const part of parts) {
      const trimmed = part.trim()
      if (trimmed === '') return `Invalid token near: "${token.trim()}" — empty part found.`
      const n = parseInt(trimmed, 10)
      if (isNaN(n)) return `Invalid step value: "${trimmed}" — must be a number 0–16.`
      if (n < 0 || n > 16) return `Step value "${trimmed}" is out of range (must be 0–16).`
    }
  }
  return null
}

export default function BuildOnTheFlyModal({ open, onClose, melodyId, currentMelody, currentBuiltMelody, defaultName, defaultPid, onAssigned }) {
  const [name, setName] = useState(defaultName || '')
  const [pid, setPid] = useState(defaultPid || '')
  const [steps, setSteps] = useState('')
  const [building, setBuilding] = useState(false)
  const [error, setError] = useState('')
  const [statusMsg, setStatusMsg] = useState('')

  const handleBuildAndUpload = async () => {
    if (!name.trim()) { setError('Name is required.'); return }
    if (!pid.trim()) { setError('PID is required.'); return }
    if (!steps.trim()) { setError('Steps are required.'); return }

    const stepsError = validateSteps(steps)
    if (stepsError) { setError(stepsError); return }

    setBuilding(true)
    setError('')
    setStatusMsg('')

    try {
      setStatusMsg('Checking for conflicts…')
      const existing = await api.get('/builder/melodies')
      const list = existing.melodies || []
      const dupName = list.find((m) => m.name.toLowerCase() === name.trim().toLowerCase())
      if (dupName) { setError(`An archetype with the name "${name.trim()}" already exists.`); setBuilding(false); setStatusMsg(''); return }
      const dupPid = list.find((m) => m.pid && m.pid.toLowerCase() === pid.trim().toLowerCase())
      if (dupPid) { setError(`An archetype with the PID "${pid.trim()}" already exists.`); setBuilding(false); setStatusMsg(''); return }

      setStatusMsg('Creating archetype record…')
      const created = await api.post('/builder/melodies', { name: name.trim(), pid: pid.trim(), steps: steps.trim() })
      const builtId = created.id

      setStatusMsg('Building binary…')
      const built = await api.post(`/builder/melodies/${builtId}/build-binary`)

      setStatusMsg('Uploading to cloud storage…')
      const token = localStorage.getItem('access_token')
      const res = await fetch(`/api${built.binary_url}`, {
        headers: token ? { Authorization: `Bearer ${token}` } : {},
      })
      if (!res.ok) throw new Error(`Failed to fetch binary: ${res.statusText}`)
      const blob = await res.blob()
      const file = new File([blob], `${pid.trim()}.bsm`, { type: 'application/octet-stream' })
      await api.upload(`/melodies/${melodyId}/upload/binary`, file)

      setStatusMsg('Linking to melody…')
      if (currentBuiltMelody?.id) {
        try { await api.post(`/builder/melodies/${currentBuiltMelody.id}/unassign?firestore_melody_id=${melodyId}`) } catch { /* best-effort */ }
      }
      await api.post(`/builder/melodies/${builtId}/assign?firestore_melody_id=${melodyId}`)

      setStatusMsg('Saving archetype data…')
      const csv = steps.trim()
      const { steps: stepCount, totalNotes } = computeStepsAndNotes(csv)
      if (currentMelody && csv) {
        const existingInfo = currentMelody.information || {}
        const body = {
          information: { ...existingInfo, archetype_csv: csv, steps: stepCount, totalNotes, outdated_archetype: false },
          default_settings: currentMelody.default_settings,
          type: currentMelody.type,
          uid: currentMelody.uid,
          pid: currentMelody.pid,
        }
        if (currentMelody.url) body.url = currentMelody.url
        await api.put(`/melodies/${melodyId}`, body)
      }

      setStatusMsg('Done!')
      onAssigned?.({ name: name.trim(), pid: pid.trim(), steps: stepCount, totalNotes, archetype_csv: csv, id: builtId })
      onClose()
    } catch (err) {
      setError(err.message)
      setStatusMsg('')
    } finally {
      setBuilding(false)
    }
  }

  return (
    <Modal
      open={open}
      onClose={building ? undefined : onClose}
      persistent={building}
      title="Build on the Fly"
      size="md"
      footer={
        <div style={{ display: 'flex', gap: 'var(--space-2)', justifyContent: 'flex-end' }}>
          <Button variant="ghost" disabled={building} onClick={onClose}>Cancel</Button>
          <Button variant="primary" disabled={building} loading={building} onClick={handleBuildAndUpload}>
            {building ? 'Building & Uploading…' : 'Build & Upload'}
          </Button>
        </div>
      }
    >
      <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-4)' }}>
        <p style={{ fontSize: 'var(--font-size-sm)', color: 'var(--color-text-muted)', marginTop: 'calc(var(--space-1) * -1)' }}>
          Enter steps, build binary, and upload — all in one step.
        </p>

        {error && (
          <div style={{
            padding: 'var(--space-3) var(--space-4)',
            backgroundColor: 'var(--color-danger-bg)',
            border: '1px solid var(--color-danger)',
            borderRadius: 'var(--radius-md)',
            color: 'var(--color-danger)',
            fontSize: 'var(--font-size-sm)',
          }}>
            {error}
          </div>
        )}

        <div className="grid grid-cols-2 gap-4">
          <FormField
            label="Name"
            name="botf-name"
            type="text"
            required
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="e.g. Doksologia_3k"
            disabled={building}
          />
          <FormField
            label="PID"
            name="botf-pid"
            type="text"
            required
            value={pid}
            onChange={(e) => setPid(e.target.value)}
            placeholder="e.g. builtin_doksologia_3k"
            disabled={building}
          />
        </div>

        <div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 'var(--space-1)' }}>
            <span style={{ fontSize: 'var(--font-size-sm)', fontWeight: 'var(--font-weight-semibold)', color: 'var(--color-text-secondary)' }}>
              Steps <span style={{ color: 'var(--color-danger)' }}>*</span>
            </span>
            <span style={{ fontSize: 'var(--font-size-xs)', color: 'var(--color-text-muted)', fontFamily: 'var(--font-family-mono)' }}>
              {countSteps(steps)} steps
            </span>
          </div>
          <FormField
            label=""
            name="botf-steps"
            type="textarea"
            rows={5}
            value={steps}
            onChange={(e) => setSteps(e.target.value)}
            placeholder={'e.g. 1,2,2+1,1,2,3+1,0,3\n\n• Comma-separated values\n• Single bell: 1, 2, 3…\n• Multiple bells: 2+3+1\n• Silence: 0'}
            disabled={building}
            inputProps={{ style: { fontFamily: 'var(--font-family-mono)', resize: 'vertical' } }}
          />
        </div>

        {statusMsg && !error && (
          <div style={{
            padding: 'var(--space-2) var(--space-3)',
            backgroundColor: 'var(--color-bg-elevated)',
            border: '1px solid var(--color-border)',
            borderRadius: 'var(--radius-md)',
            fontSize: 'var(--font-size-sm)',
            color: 'var(--color-text-muted)',
            textAlign: 'center',
          }}>
            {statusMsg}
          </div>
        )}
      </div>
    </Modal>
  )
}
