import { useMemo, useState } from 'react'
import { MODELS, PFLY_OOB, displayAuroc, featureSetLabel, type RealModel } from '../data/models'
import ModelDetail from './ModelDetail'

interface ModelPickerProps {
  selected: string // model code
  onChange: (code: string) => void
}

interface Group {
  key: string
  species: string
  models: RealModel[]
}

export default function ModelPicker({ selected, onChange }: ModelPickerProps) {
  const [openInfo, setOpenInfo] = useState<string | null>(null)

  // group models by species
  const groups = useMemo<Group[]>(() => {
    const byKey = new Map<string, Group>()
    for (const m of MODELS) {
      if (!byKey.has(m.speciesKey)) byKey.set(m.speciesKey, { key: m.speciesKey, species: m.species, models: [] })
      byKey.get(m.speciesKey)!.models.push(m)
    }
    return [...byKey.values()]
  }, [])

  const selectedGroupKey = useMemo(
    () => MODELS.find((m) => m.code === selected)?.speciesKey ?? groups[0]?.key,
    [selected, groups],
  )

  // collapsed species sections, only the selected model's species is open initially
  const [openGroups, setOpenGroups] = useState<Set<string>>(new Set(selectedGroupKey ? [selectedGroupKey] : []))
  const toggleGroup = (k: string) =>
    setOpenGroups((prev) => {
      const next = new Set(prev)
      next.has(k) ? next.delete(k) : next.add(k)
      return next
    })

  return (
    <div className="field">
      <div className="field-label">
        Model{' '}
        <span className="field-hint">
          Pick Pfly (any species) or one of {MODELS.length} context-specific models grouped by species.
        </span>
      </div>
      <div className="option-list" style={{ marginBottom: 8 }}>
        <label className={'option' + (selected === PFLY_OOB.code ? ' selected' : '')}>
          <input
            type="radio"
            name="model"
            checked={selected === PFLY_OOB.code}
            onChange={() => onChange(PFLY_OOB.code)}
          />
          <span className="option-body">
            <span className="option-title" style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
              <span className="mono">Pfly</span> · out-of-the-box
              <span className="badge badge-muted">sequence-only</span>
            </span>
            <span className="option-desc">
              Pretrained dlomix DetectabilityModel. Works for any species; not calibrated to a
              specific dataset.
            </span>
          </span>
        </label>
      </div>
      <div className="species-accordion">
        {groups.map((g) => {
          const isOpen = openGroups.has(g.key)
          const hasSelected = g.models.some((m) => m.code === selected)
          return (
            <div key={g.key} className={'species-group' + (isOpen ? ' open' : '')}>
              <button type="button" className="species-head" onClick={() => toggleGroup(g.key)}>
                <span className={'species-caret caret' + (isOpen ? ' open' : '')}>▶</span>
                <span className="species-name">{g.species.split('(')[0].trim()}</span>
                <span className="species-count">{g.models.length} model{g.models.length > 1 ? 's' : ''}</span>
                {hasSelected && !isOpen && <span className="badge badge-good species-sel">selected</span>}
              </button>
              {isOpen && (
                <div className="option-list species-body">
                  {g.models.map((m) => {
                    const on = selected === m.code
                    return (
                      <div key={m.code}>
                        <label className={'option' + (on ? ' selected' : '')}>
                          <input type="radio" name="model" checked={on} onChange={() => onChange(m.code)} />
                          <span className="option-body">
                            <span className="option-title" style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                              <span className="mono">{m.code}</span> · {m.enzyme}
                              <span className="badge badge-accent">AUROC {displayAuroc(m)}</span>
                            </span>
                            <span className="option-desc">
                              {featureSetLabel(m.bestFeatureSet)} · n={m.nPos.toLocaleString()}
                              {m.flags.length > 0 && ' · caveat, see details'}
                            </span>
                          </span>
                          <button
                            type="button"
                            className="btn btn-ghost btn-sm"
                            onClick={(e) => {
                              e.preventDefault()
                              setOpenInfo(openInfo === m.code ? null : m.code)
                            }}
                          >
                            {openInfo === m.code ? 'Hide' : 'Details'}
                          </button>
                        </label>
                        {openInfo === m.code && <ModelDetail m={m} />}
                      </div>
                    )
                  })}
                </div>
              )}
            </div>
          )
        })}
      </div>
    </div>
  )
}
