import React, { useEffect, useMemo, useState } from 'react'
import api from '../../utils/api'

function downloadJson(obj, filename) {
  const blob = new Blob([JSON.stringify(obj, null, 2)], {
    type: 'application/json;charset=utf-8'
  })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
  URL.revokeObjectURL(url)
}

function groupModelSkills(model) {
  if (!model?.model_skills?.length) return []
  const groups = new Map()
  for (const ms of model.model_skills) {
    const main = ms.skill_main_category_name || '—'
    const sub = ms.skill_subcategory_name || '—'
    const k = `${main}\t${sub}`
    if (!groups.has(k)) groups.set(k, { main, sub, skills: [] })
    groups.get(k).skills.push(ms)
  }
  return Array.from(groups.values())
}

function cellMapForSkill(model, skillId) {
  const m = {}
  for (const sl of model.skill_levels || []) {
    if (Number(sl.skill_id) === Number(skillId)) {
      m[sl.level_number] = sl
    }
  }
  return m
}

export default function MaturityMatrixToolsAdmin() {
  const [focusAreas, setFocusAreas] = useState([])
  const [styles, setStyles] = useState([])
  const [trainingTypes, setTrainingTypes] = useState([])
  const [models, setModels] = useState([])
  const [focusId, setFocusId] = useState('')
  const [styleId, setStyleId] = useState('')
  const [typeId, setTypeId] = useState('')
  const [matrix, setMatrix] = useState(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  const [message, setMessage] = useState('')
  const [importMode, setImportMode] = useState('create')
  const [replaceModelId, setReplaceModelId] = useState('')
  const [exportModelId, setExportModelId] = useState('')
  const [importBindings, setImportBindings] = useState(true)
  const [stackWipe, setStackWipe] = useState(false)
  const [stackConfirmText, setStackConfirmText] = useState('')
  const [stackLoading, setStackLoading] = useState(false)
  const [stackImportLoading, setStackImportLoading] = useState(false)

  useEffect(() => {
    let cancelled = false
    ;(async () => {
      try {
        const [fa, sd, tt, m] = await Promise.all([
          api.listFocusAreas({}),
          api.listStyleDirections({}),
          api.listTrainingTypes({}),
          api.listMaturityModels({})
        ])
        if (!cancelled) {
          setFocusAreas(fa)
          setStyles(sd)
          setTrainingTypes(tt)
          setModels(m)
        }
      } catch (e) {
        if (!cancelled) setError(e.message || String(e))
      }
    })()
    return () => {
      cancelled = true
    }
  }, [])

  const groups = useMemo(() => (matrix ? groupModelSkills(matrix) : []), [matrix])
  const levels = matrix?.levels || []

  async function handleResolve() {
    if (!focusId) {
      setError('Fokusbereich wählen.')
      return
    }
    setLoading(true)
    setError('')
    setMessage('')
    setMatrix(null)
    try {
      const params = { focus_area_id: focusId }
      if (styleId) params.style_direction_id = styleId
      if (typeId) params.training_type_id = typeId
      const m = await api.resolveMaturityModel(params)
      setMatrix(m)
      if (!m) setError('Keine Matrix für diesen Kontext.')
      else setMessage('Matrix geladen.')
    } catch (e) {
      setError(e.message || String(e))
    } finally {
      setLoading(false)
    }
  }

  async function handleExportResolved() {
    if (!focusId) {
      setError('Fokusbereich wählen.')
      return
    }
    setError('')
    setMessage('')
    try {
      const params = { focus_area_id: focusId }
      if (styleId) params.style_direction_id = styleId
      if (typeId) params.training_type_id = typeId
      const bundle = await api.exportResolvedMaturityBundle(params)
      downloadJson(bundle, 'faehigkeitsmatrix-aufgeloest.json')
      setMessage('Export gestartet (Download).')
    } catch (e) {
      setError(e.message || String(e))
    }
  }

  async function handleExportStored() {
    if (!exportModelId) {
      setError('Modell für Export auswählen.')
      return
    }
    setError('')
    setMessage('')
    try {
      const bundle = await api.exportMaturityModelBundle(parseInt(exportModelId, 10))
      downloadJson(bundle, `reifegradmodell-${exportModelId}.json`)
      setMessage('Export gestartet (Download).')
    } catch (e) {
      setError(e.message || String(e))
    }
  }

  async function handleExportStack() {
    setError('')
    setMessage('')
    setStackLoading(true)
    try {
      const bundle = await api.exportMatrixStackBundle()
      const name = `matrix-stack-${(bundle.bundle_export_id || 'export').slice(0, 8)}.json`
      downloadJson(bundle, name)
      setMessage('Komplett-Stack exportiert (Download).')
    } catch (err) {
      setError(err.message || String(err))
    } finally {
      setStackLoading(false)
    }
  }

  async function handleImportStackFile(e) {
    const file = e.target.files?.[0]
    if (!file) return
    setError('')
    setMessage('')
    setStackImportLoading(true)
    try {
      const data = JSON.parse(await file.text())
      if (data.kind !== 'shinkan.matrix_stack.v1') {
        setError('Erwartet wird eine Datei mit kind: shinkan.matrix_stack.v1 (Komplett-Stack-Export).')
        e.target.value = ''
        return
      }
      if (stackWipe && stackConfirmText !== 'DELETE_MATURITY_STACK') {
        setError('Vollständiges Ersetzen: Bestätigung exakt „DELETE_MATURITY_STACK“ eintragen (Superadmin).')
        e.target.value = ''
        return
      }
      const payload = {
        ...data,
        replace_all_maturity_models: stackWipe,
        confirm_replace_all: stackWipe ? stackConfirmText : undefined
      }
      const res = await api.importMatrixStackBundle(payload)
      const w = res.warnings || []
      setMessage(
        `Stack-Import OK. Modell-Zuordnung: ${Object.keys(res.model_id_map || {}).length} Modell(e), Skills gemappt: ${Object.keys(res.skill_id_map || {}).length}.` +
          (w.length ? ` ${w.length} Hinweis(e) (Konsole).` : '')
      )
      if (w.length) console.warn('matrix_stack import warnings', w)
      setModels(await api.listMaturityModels({}))
    } catch (err) {
      setError(err.message || String(err))
    } finally {
      setStackImportLoading(false)
      e.target.value = ''
    }
  }

  async function handleImportFile(e) {
    const file = e.target.files?.[0]
    if (!file) return
    setError('')
    setMessage('')
    try {
      const data = JSON.parse(await file.text())
      if (data.kind === 'shinkan.matrix_stack.v1') {
        setError('Komplett-Stack: bitte die Datei im Abschnitt „Komplett-Stack“ importieren (eigenes Dateifeld).')
        e.target.value = ''
        return
      } else {
        const payload = { ...data, mode: importMode, import_bindings: importBindings }
        if (importMode === 'replace') {
          if (!replaceModelId) {
            setError('Bei „Ersetzen“ die Ziel-Modell-ID angeben.')
            e.target.value = ''
            return
          }
          payload.replace_model_id = parseInt(replaceModelId, 10)
        }
        const res = await api.importMaturityModelBundle(payload)
        setMessage(`Import erfolgreich. Modell-ID: ${res.id}`)
        setModels(await api.listMaturityModels({}))
      }
    } catch (err) {
      setError(err.message || String(err))
    } finally {
      e.target.value = ''
    }
  }

  return (
    <div className="admin-matrix-tools">
      <p className="admin-matrix-tools__intro muted">
        Matrix nach Kontext auflösen, hierarchisch nach Hauptkategorie und Kategorie darstellen, sowie JSON
        exportieren oder importieren (gespeichertes Modell inkl. optional Kontext-Bindings, aufgelöste Matrix, oder{' '}
        <strong>Komplett-Stack</strong> mit Fähigkeitskatalog und allen Reifegradmodellen für Test → Prod).
      </p>

      {error ? (
        <div className="skills-catalog-admin__error" role="alert">
          {error}
        </div>
      ) : null}
      {message ? <p className="muted admin-matrix-tools__msg">{message}</p> : null}

      <section className="card admin-matrix-tools__section">
        <h2 className="admin-matrix-tools__h2">Kontext und Anzeige</h2>
        <div className="admin-matrix-tools__filters">
          <div>
            <label className="form-label">Fokusbereich</label>
            <select
              className="form-input"
              value={focusId}
              onChange={(e) => setFocusId(e.target.value)}
            >
              <option value="">— wählen —</option>
              {focusAreas.map((f) => (
                <option key={f.id} value={f.id}>
                  {f.name}
                </option>
              ))}
            </select>
          </div>
          <div>
            <label className="form-label">Stilrichtung (optional)</label>
            <select
              className="form-input"
              value={styleId}
              onChange={(e) => setStyleId(e.target.value)}
            >
              <option value="">— alle / egal —</option>
              {styles.map((s) => (
                <option key={s.id} value={s.id}>
                  {s.name}
                </option>
              ))}
            </select>
          </div>
          <div>
            <label className="form-label">Trainingsstil (optional)</label>
            <select className="form-input" value={typeId} onChange={(e) => setTypeId(e.target.value)}>
              <option value="">— alle / egal —</option>
              {trainingTypes.map((t) => (
                <option key={t.id} value={t.id}>
                  {t.name}
                </option>
              ))}
            </select>
          </div>
        </div>
        <div className="admin-matrix-tools__actions">
          <button type="button" className="btn btn-primary" disabled={loading} onClick={handleResolve}>
            {loading ? 'Lade…' : 'Matrix auflösen & anzeigen'}
          </button>
          <button type="button" className="btn btn-secondary" onClick={handleExportResolved}>
            Aufgelöste Matrix exportieren (JSON)
          </button>
        </div>
        {matrix?.resolution ? (
          <p className="muted admin-matrix-tools__meta">
            Quelle:{' '}
            {matrix.resolution.merged
              ? `zusammengeführt aus Modell-IDs ${(matrix.resolution.source_model_ids || []).join(', ')}`
              : `Modell-ID ${matrix.id}`}
          </p>
        ) : null}
      </section>

      {matrix ? (
        <section className="card admin-matrix-tools__section admin-matrix-tools__visual">
          <h2 className="admin-matrix-tools__h2">
            {matrix.name}
            <span className="muted admin-matrix-tools__subtitle">
              {' '}
              · {matrix.level_count} Stufen · {matrix.model_skills?.length || 0} Fähigkeiten
            </span>
          </h2>
          {groups.map((g) => (
            <div key={`${g.main}-${g.sub}`} className="admin-matrix-visual-group">
              <h3 className="admin-matrix-visual-group__main">{g.main}</h3>
              <h4 className="admin-matrix-visual-group__sub">{g.sub}</h4>
              <div className="admin-matrix-visual-table-wrap">
                <table className="admin-matrix-visual-table">
                  <thead>
                    <tr>
                      <th className="admin-matrix-visual-table__skill">Fähigkeit</th>
                      {levels.map((lv) => (
                        <th key={lv.level_number} className="admin-matrix-visual-table__level">
                          <span className="admin-matrix-visual-table__ln">{lv.level_number}</span>
                          <span className="admin-matrix-visual-table__lname">{lv.name}</span>
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {g.skills.map((ms) => {
                      const cells = cellMapForSkill(matrix, ms.skill_id)
                      return (
                        <tr key={ms.skill_id}>
                          <td className="admin-matrix-visual-table__skill-cell">{ms.skill_name}</td>
                          {levels.map((lv) => {
                            const c = cells[lv.level_number]
                            return (
                              <td key={lv.level_number} className="admin-matrix-visual-table__cell">
                                {c ? (
                                  <>
                                    <div className="admin-matrix-visual-table__goal">
                                      {c.description || '—'}
                                    </div>
                                    {c.observable_criteria ? (
                                      <div className="admin-matrix-visual-table__obs muted">
                                        <strong>Beobachtung:</strong> {c.observable_criteria}
                                      </div>
                                    ) : null}
                                  </>
                                ) : (
                                  <span className="muted">—</span>
                                )}
                              </td>
                            )
                          })}
                        </tr>
                      )
                    })}
                  </tbody>
                </table>
              </div>
            </div>
          ))}
        </section>
      ) : null}

      <section className="card admin-matrix-tools__section">
        <h2 className="admin-matrix-tools__h2">Komplett-Stack (Katalog + Modelle + Bindings)</h2>
        <p className="muted admin-matrix-tools__hint">
          Export enthält <code className="admin-bindings__code">skill_main_categories</code>,{' '}
          <code className="admin-bindings__code">skill_categories</code>, <code className="admin-bindings__code">skills</code>,{' '}
          <code className="admin-bindings__code">skill_level_definitions</code>, alle Reifegradmodelle (Stufen, Matrix-Zellen,
          Legacy-Kontext M:N) sowie <code className="admin-bindings__code">context_bindings</code> mit{' '}
          <strong>Fokus-/Stil-/Trainingsstil-Namen</strong> für die Ziel-DB. Auf Prod müssen dieselben
          Katalognamen für Fokusbereiche, Stilrichtungen und Trainingsstile existieren.
        </p>
        <div className="admin-matrix-tools__actions">
          <button
            type="button"
            className="btn btn-primary"
            disabled={stackLoading || stackImportLoading}
            onClick={handleExportStack}
          >
            {stackLoading ? 'Export…' : 'Komplett-Stack exportieren'}
          </button>
        </div>
        <h3 className="admin-matrix-tools__h3">Komplett-Stack importieren</h3>
        <p className="muted admin-matrix-tools__hint">
          JSON vom Export dieses Dialogs (<code className="admin-bindings__code">shinkan.matrix_stack.v1</code>). Katalog
          wird per Slug zusammengeführt; Skills per Kategorie + Name. Reifegradmodelle werden neu angelegt; Kontext-Bindings
          über Namen der Fokus-/Stil-/Trainingsstil-Kataloge auf der Ziel-DB.
        </p>
        <label className="form-label admin-matrix-tools__check">
          <input
            type="checkbox"
            checked={stackWipe}
            onChange={(e) => {
              setStackWipe(e.target.checked)
              if (!e.target.checked) setStackConfirmText('')
            }}
          />{' '}
          Zuerst alle Reifegradmodelle auf dieser Datenbank löschen (nur Superadmin)
        </label>
        {stackWipe ? (
          <>
            <label className="form-label">Bestätigung (exakt)</label>
            <input
              className="form-input"
              value={stackConfirmText}
              onChange={(e) => setStackConfirmText(e.target.value)}
              placeholder="DELETE_MATURITY_STACK"
              autoComplete="off"
            />
          </>
        ) : null}
        <label className="form-label">Stack-JSON-Datei</label>
        <input
          type="file"
          accept="application/json,.json"
          disabled={stackImportLoading}
          onChange={handleImportStackFile}
        />
        {stackImportLoading ? <p className="muted admin-matrix-tools__msg">Import läuft…</p> : null}
      </section>

      <section className="card admin-matrix-tools__section">
        <h2 className="admin-matrix-tools__h2">Export / Import (JSON)</h2>
        <div className="admin-matrix-tools__io-grid">
          <div>
            <h3 className="admin-matrix-tools__h3">Gespeichertes Modell exportieren</h3>
            <p className="muted admin-matrix-tools__hint">
              Enthält Stufen, Fähigkeiten, Zelltexte und die dem Modell zugeordneten Kontext-Bindings.
            </p>
            <label className="form-label">Modell</label>
            <select
              className="form-input"
              value={exportModelId}
              onChange={(e) => setExportModelId(e.target.value)}
            >
              <option value="">— wählen —</option>
              {models.map((m) => (
                <option key={m.id} value={m.id}>
                  {m.name} ({m.status})
                </option>
              ))}
            </select>
            <button
              type="button"
              className="btn btn-secondary admin-matrix-tools__btn-mt"
              onClick={handleExportStored}
            >
              JSON herunterladen
            </button>
          </div>
          <div>
            <h3 className="admin-matrix-tools__h3">Import</h3>
            <p className="muted admin-matrix-tools__hint">
              <code className="admin-bindings__code">shinkan.maturity_model.v1</code> oder{' '}
              <code className="admin-bindings__code">shinkan.maturity_matrix_resolved.v1</code>. Komplett-Stack bitte im
              Abschnitt <strong>Komplett-Stack</strong> oben importieren. Aufgelöste Matrizen legen ein neues Modell an bzw.
              ersetzen den Inhalt des Zielmodells (ohne Bindings).
            </p>
            <label className="form-label">Modus</label>
            <select
              className="form-input"
              value={importMode}
              onChange={(e) => setImportMode(e.target.value)}
            >
              <option value="create">Neues Modell anlegen</option>
              <option value="replace">Bestehendes Modell ersetzen (Matrix-Inhalt)</option>
            </select>
            {importMode === 'replace' ? (
              <>
                <label className="form-label">Ziel-Modell-ID</label>
                <input
                  className="form-input"
                  type="number"
                  inputMode="numeric"
                  value={replaceModelId}
                  onChange={(e) => setReplaceModelId(e.target.value)}
                  placeholder="z. B. 3"
                />
              </>
            ) : null}
            <label className="form-label admin-matrix-tools__check">
              <input
                type="checkbox"
                checked={importBindings}
                onChange={(e) => setImportBindings(e.target.checked)}
              />{' '}
              Kontext-Bindings mit importieren (nur bei <code className="admin-bindings__code">.maturity_model.v1</code>)
            </label>
            <label className="form-label">JSON-Datei</label>
            <input type="file" accept="application/json,.json" onChange={handleImportFile} />
          </div>
        </div>
      </section>
    </div>
  )
}
