/**
 * Modal: Medium aus Archiv verknüpfen oder neue Datei hochladen, dann Inline-Platzhalter §11 einfügen.
 */
import React, { useEffect, useState, useCallback, useMemo } from 'react'
import api from '../utils/api'
import { resolveMediaAssetFileUrl } from '../utils/exerciseMediaUrl'
import {
  INLINE_MEDIA_SIZES,
  DEFAULT_INLINE_MEDIA_SIZE,
  sanitizeInlineMediaSize,
} from '../constants/inlineExerciseMedia'
import { sanitizeInlineMediaCaption } from '../utils/inlineMediaCaption'

function RtePickerAssetThumb({ asset }) {
  const id = asset.id
  const src = resolveMediaAssetFileUrl(id)
  const mt = (asset.mime_type || '').toLowerCase()
  if (mt.startsWith('image/') && src) {
    return <img alt="" src={src} className="rte-inline-asset-tile__thumb-img" />
  }
  if (mt.startsWith('video/') && src) {
    return (
      <video
        key={`v-${id}`}
        className="rte-inline-asset-tile__thumb-video"
        src={src}
        muted
        playsInline
        preload="metadata"
        onLoadedMetadata={(e) => {
          try {
            const el = e.currentTarget
            const d = el.duration
            el.currentTime = Number.isFinite(d) && d > 0 ? Math.min(0.05, d * 0.01) : 0.05
          } catch (_) {
            /* ignore */
          }
        }}
      />
    )
  }
  const nameLow = String(asset.original_filename || '').toLowerCase()
  if (mt.includes('pdf') || nameLow.endsWith('.pdf')) {
    return <span className="rte-inline-asset-tile__thumb-fallback">PDF</span>
  }
  return <span className="rte-inline-asset-tile__thumb-fallback">Datei</span>
}

/** MIME/Dateiname → Übungs-media_type */
function inferExerciseMediaType(file) {
  if (!file) return 'image'
  const mime = (file.type || '').toLowerCase()
  if (mime.startsWith('image/')) return 'image'
  if (mime.startsWith('video/')) return 'video'
  if (mime === 'application/pdf' || mime.includes('pdf')) return 'document'
  const name = (file.name || '').toLowerCase()
  if (/\.(mp4|webm|mov|mkv|avi|m4v|mpeg|mpg)$/.test(name)) return 'video'
  if (/\.(jpg|jpeg|png|gif|webp|bmp|svg)$/.test(name)) return 'image'
  if (/\.pdf$/.test(name)) return 'document'
  return 'image'
}

const DECL_INIT = {
  rights_holder_confirmed: false,
  contains_identifiable_persons: null,
  person_consent_confirmed: false,
  contains_minors: null,
  parental_consent_confirmed: false,
  contains_music: null,
  music_rights_confirmed: false,
  contains_third_party_content: null,
  third_party_rights_confirmed: false,
}

function validateDecl(decl) {
  if (!decl.rights_holder_confirmed)
    return 'Bitte bestätigen, dass du die erforderlichen Rechte an diesem Medium besitzt.'
  if (decl.contains_identifiable_persons === null)
    return 'Bitte angeben, ob erkennbare Personen abgebildet sind.'
  if (decl.contains_identifiable_persons && !decl.person_consent_confirmed)
    return 'Bitte bestätigen, dass die Einwilligungen aller erkennbaren Personen vorliegen.'
  if (decl.contains_minors === null)
    return 'Bitte angeben, ob Minderjährige abgebildet sind.'
  if (decl.contains_minors && !decl.parental_consent_confirmed)
    return 'Bitte bestätigen, dass die Einwilligungen der Sorgeberechtigten vorliegen.'
  if (decl.contains_music === null)
    return 'Bitte angeben, ob das Medium Musik enthält.'
  if (decl.contains_music && !decl.music_rights_confirmed)
    return 'Bitte bestätigen, dass die erforderlichen Musikrechte vorliegen.'
  if (decl.contains_third_party_content === null)
    return 'Bitte angeben, ob fremde geschützte Inhalte enthalten sind.'
  if (decl.contains_third_party_content && !decl.third_party_rights_confirmed)
    return 'Bitte bestätigen, dass die Rechte an allen enthaltenen Fremdmaterialien vorliegen.'
  return ''
}

/**
 * @param {{
 *   open: boolean,
 *   onClose: () => void,
 *   exerciseId: number,
 *   linkedExerciseMedia?: object[],
 *   onMediaListChanged: () => Promise<void>,
 *   onInserted: (exerciseMediaId: number, displaySize: string, caption?: string) => void,
 * }} props
 */
export default function ExerciseInlineFileMediaModal({
  open,
  onClose,
  exerciseId,
  linkedExerciseMedia = [],
  onMediaListChanged,
  onInserted,
}) {
  const [tab, setTab] = useState('library')
  const [q, setQ] = useState('')
  const [loading, setLoading] = useState(false)
  const [items, setItems] = useState([])
  const [err, setErr] = useState(null)
  const [selectedAssetId, setSelectedAssetId] = useState(null)
  const [busy, setBusy] = useState(false)
  const [uploadFile, setUploadFile] = useState(null)
  const [uploadTitle, setUploadTitle] = useState('')
  const [displaySize, setDisplaySize] = useState(DEFAULT_INLINE_MEDIA_SIZE)
  const [uploadInputKey, setUploadInputKey] = useState(0)
  const [decl, setDecl] = useState({ ...DECL_INIT })
  const [declErr, setDeclErr] = useState('')

  const setDeclField = (key, val) => setDecl((d) => ({ ...d, [key]: val }))

  const assetToExerciseMedia = useMemo(() => {
    const m = new Map()
    for (const row of linkedExerciseMedia || []) {
      const aid = row?.media_asset_id
      if (aid != null) m.set(Number(aid), row)
    }
    return m
  }, [linkedExerciseMedia])

  const loadAssets = useCallback(async () => {
    setLoading(true)
    setErr(null)
    try {
      const res = await api.listMediaAssets({
        q: q.trim() || undefined,
        limit: 48,
        lifecycle: 'active',
      })
      setItems(Array.isArray(res.items) ? res.items : [])
    } catch (e) {
      setErr(e.message || String(e))
      setItems([])
    } finally {
      setLoading(false)
    }
  }, [q])

  useEffect(() => {
    if (!open) return undefined
    setTab('library')
    setSelectedAssetId(null)
    setUploadFile(null)
    setUploadTitle('')
    setUploadInputKey((k) => k + 1)
    setDisplaySize(DEFAULT_INLINE_MEDIA_SIZE)
    setErr(null)
    setDecl({ ...DECL_INIT })
    setDeclErr('')
    const t = setTimeout(loadAssets, 280)
    return () => clearTimeout(t)
  }, [open])

  useEffect(() => {
    if (!open || tab !== 'library') return undefined
    const t = setTimeout(loadAssets, 300)
    return () => clearTimeout(t)
  }, [q, open, tab, loadAssets])

  const handleLinkSelected = async () => {
    if (!selectedAssetId) {
      alert('Bitte ein Archiv-Medium auswählen.')
      return
    }
    const size = sanitizeInlineMediaSize(displaySize)
    const assetMeta = items.find((x) => x.id === selectedAssetId)
    const capFromExisting = (row) =>
      sanitizeInlineMediaCaption(row?.original_filename || row?.title || assetMeta?.original_filename || '')

    const existing = assetToExerciseMedia.get(Number(selectedAssetId))
    if (existing?.id != null) {
      onInserted(Number(existing.id), size, capFromExisting(existing))
      onClose()
      return
    }

    setBusy(true)
    setErr(null)
    try {
      const row = await api.attachExerciseMediaFromAsset(exerciseId, {
        media_asset_id: selectedAssetId,
        title: '',
        description: '',
        context: 'ablauf',
        is_primary: false,
      })
      const mid = row?.id
      if (mid == null) {
        throw new Error('Antwort ohne exercise_media-ID')
      }
      await onMediaListChanged()
      onInserted(
        Number(mid),
        size,
        sanitizeInlineMediaCaption(assetMeta?.original_filename || ''),
      )
      onClose()
    } catch (e) {
      const msg = e.message || String(e)
      setErr(msg)
    } finally {
      setBusy(false)
    }
  }

  const handleUploadAndInsert = async () => {
    if (!uploadFile) {
      alert('Bitte eine Datei wählen.')
      return
    }
    const validErr = validateDecl(decl)
    if (validErr) {
      setDeclErr(validErr)
      return
    }
    setDeclErr('')
    const size = sanitizeInlineMediaSize(displaySize)
    const inferred = inferExerciseMediaType(uploadFile)
    const fd = new FormData()
    fd.append('file', uploadFile)
    fd.append('media_type', inferred)
    fd.append('title', uploadTitle.trim())
    fd.append('description', '')
    fd.append('context', 'ablauf')
    fd.append('is_primary', 'false')
    for (const [k, v] of Object.entries(decl)) {
      fd.append(k, String(v))
    }
    setBusy(true)
    setErr(null)
    try {
      const row = await api.uploadExerciseMedia(exerciseId, fd)
      const mid = row?.id
      if (mid == null) {
        throw new Error('Antwort ohne exercise_media-ID')
      }
      await onMediaListChanged()
      const cap = sanitizeInlineMediaCaption(
        uploadTitle.trim() || uploadFile.name || '',
      )
      onInserted(Number(mid), size, cap)
      setUploadFile(null)
      setUploadTitle('')
      setUploadInputKey((k) => k + 1)
      onClose()
    } catch (e) {
      if (e.code === 'MEDIA_ASSET_IN_TRASH' && e.payload?.media_asset_id != null) {
        alert(
          'Dieselbe Datei existiert bereits im Papierkorb — bitte in der Medienbibliothek reaktivieren oder eine andere Datei wählen.',
        )
      } else {
        alert(e.message || String(e))
      }
      setErr(e.message || String(e))
    } finally {
      setBusy(false)
    }
  }

  const selectedLinked = selectedAssetId != null && assetToExerciseMedia.has(Number(selectedAssetId))

  if (!open) return null

  return (
    <div className="admin-modal-backdrop" role="presentation" onClick={(e) => e.target === e.currentTarget && !busy && onClose()}>
      <div
        className="admin-modal-sheet rte-inline-media-modal"
        role="dialog"
        aria-modal="true"
        aria-labelledby="rte-inline-file-title"
        style={{
          maxWidth: '560px',
          width: '100%',
          maxHeight: '90vh',
          display: 'flex',
          flexDirection: 'column',
        }}
        onClick={(e) => e.stopPropagation()}
      >
        <div className="admin-modal-sheet__header">
          <h3 id="rte-inline-file-title" className="admin-modal-sheet__title">
            Medium im Textfeld
          </h3>
          <button type="button" className="btn btn-secondary admin-modal-sheet__close" disabled={busy} onClick={onClose}>
            Schließen
          </button>
        </div>

        <div style={{ padding: '10px 12px', borderBottom: '1px solid var(--border)', display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
          <button
            type="button"
            className={`btn btn-secondary ${tab === 'library' ? 'rte-tab--active' : ''}`}
            style={{ fontSize: '13px' }}
            onClick={() => setTab('library')}
            disabled={busy}
          >
            Aus Mediathek
          </button>
          <button
            type="button"
            className={`btn btn-secondary ${tab === 'upload' ? 'rte-tab--active' : ''}`}
            style={{ fontSize: '13px' }}
            onClick={() => setTab('upload')}
            disabled={busy}
          >
            Neu hochladen
          </button>
        </div>

        <div style={{ overflowY: 'auto', flex: 1, padding: '12px 14px' }}>
          {err && !loading ? (
            <p style={{ color: 'var(--danger)', marginTop: '0', marginBottom: '12px', fontSize: '0.9rem' }}>{err}</p>
          ) : null}
          {tab === 'library' && (
            <>
              <label className="form-label">Suche in der Bibliothek</label>
              <input
                className="form-input"
                value={q}
                onChange={(e) => setQ(e.target.value)}
                placeholder="Name, Tag, © …"
                disabled={busy}
              />
              {loading ? <p style={{ color: 'var(--text3)', marginTop: '12px' }}>Laden…</p> : null}
              <div className="rte-inline-asset-grid" style={{ marginTop: '14px' }}>
                {items.map((it) => {
                  const id = it.id
                  const selected = selectedAssetId === id
                  const label = it.original_filename || it.copyright_notice || `Archiv #${id}`
                  const linked = assetToExerciseMedia.has(Number(id))
                  return (
                    <button
                      key={id}
                      type="button"
                      className={`rte-inline-asset-tile${selected ? ' rte-inline-asset-tile--selected' : ''}`}
                      onClick={() => setSelectedAssetId(id)}
                      disabled={busy}
                    >
                      <div className="rte-inline-asset-tile__thumb" aria-hidden>
                        <RtePickerAssetThumb asset={it} />
                      </div>
                      {linked ? (
                        <span className="rte-inline-asset-tile__badge">Bereits verknüpft</span>
                      ) : null}
                      <span className="rte-inline-asset-tile__meta">
                        {(it.mime_type || '').split('/')[0] || 'datei'}
                      </span>
                      <span className="rte-inline-asset-tile__name">{label}</span>
                    </button>
                  )
                })}
              </div>
              {!loading && items.length === 0 ? (
                <p style={{ color: 'var(--text3)', marginTop: '12px' }}>Keine Treffer — Suche anpassen oder „Neu hochladen".</p>
              ) : null}
            </>
          )}

          {tab === 'upload' && (
            <>
              <label className="form-label">Datei</label>
              <div className="rte-inline-file-row">
                <input
                  key={uploadInputKey}
                  id="rte-inline-file-upload-input"
                  type="file"
                  accept="image/*,video/*,application/pdf"
                  className="rte-inline-file-input-hidden"
                  disabled={busy}
                  onChange={(e) => {
                    const f = e.target.files?.[0] || null
                    setUploadFile(f)
                  }}
                />
                <label htmlFor="rte-inline-file-upload-input" className="btn btn-secondary rte-inline-file-pick-btn">
                  Datei auswählen
                </label>
                <span className="rte-inline-file-name" title={uploadFile?.name || ''}>
                  {uploadFile ? uploadFile.name : 'Keine Datei ausgewählt'}
                </span>
              </div>
              <label className="form-label" style={{ marginTop: '12px' }}>
                Titel (optional)
              </label>
              <input
                className="form-input"
                value={uploadTitle}
                onChange={(e) => setUploadTitle(e.target.value)}
                disabled={busy}
              />

              {/* P-06 Rechte-Erklärung */}
              <div style={{ marginTop: '18px', paddingTop: '14px', borderTop: '1px solid var(--border)' }}>
                <p style={{ fontSize: '0.82rem', fontWeight: 600, marginBottom: '10px', color: 'var(--text2)' }}>
                  Rechte-Erklärung <span style={{ fontWeight: 400, color: 'var(--text3)' }}>(VORLÄUFIG – p06-v1-conservative)</span>
                </p>

                <div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginBottom: '10px' }}>
                  <input
                    type="checkbox"
                    id="up-rhc"
                    checked={decl.rights_holder_confirmed}
                    onChange={(e) => setDeclField('rights_holder_confirmed', e.target.checked)}
                    disabled={busy}
                    style={{ marginTop: '3px', flexShrink: 0 }}
                  />
                  <label htmlFor="up-rhc" style={{ fontSize: '0.85rem' }}>
                    Ich bestätige, dass ich die erforderlichen Rechte an diesem Medium besitze oder zur Veröffentlichung berechtigt bin. *
                  </label>
                </div>

                <fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
                  <legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Erkennbare Personen abgebildet? *</legend>
                  <div style={{ display: 'flex', gap: '14px' }}>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-cip" checked={decl.contains_identifiable_persons === true}
                        onChange={() => setDeclField('contains_identifiable_persons', true)} disabled={busy} /> Ja
                    </label>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-cip" checked={decl.contains_identifiable_persons === false}
                        onChange={() => setDeclField('contains_identifiable_persons', false)} disabled={busy} /> Nein
                    </label>
                  </div>
                  {decl.contains_identifiable_persons === true && (
                    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
                      <input type="checkbox" id="up-pcc" checked={decl.person_consent_confirmed}
                        onChange={(e) => setDeclField('person_consent_confirmed', e.target.checked)}
                        disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
                      <label htmlFor="up-pcc" style={{ fontSize: '0.85rem' }}>
                        Einwilligungen aller erkennbaren Personen liegen vor. *
                      </label>
                    </div>
                  )}
                </fieldset>

                <fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
                  <legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Minderjährige abgebildet? *</legend>
                  <div style={{ display: 'flex', gap: '14px' }}>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-cm" checked={decl.contains_minors === true}
                        onChange={() => setDeclField('contains_minors', true)} disabled={busy} /> Ja
                    </label>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-cm" checked={decl.contains_minors === false}
                        onChange={() => setDeclField('contains_minors', false)} disabled={busy} /> Nein
                    </label>
                  </div>
                  {decl.contains_minors === true && (
                    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
                      <input type="checkbox" id="up-pcc2" checked={decl.parental_consent_confirmed}
                        onChange={(e) => setDeclField('parental_consent_confirmed', e.target.checked)}
                        disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
                      <label htmlFor="up-pcc2" style={{ fontSize: '0.85rem' }}>
                        Einwilligungen der Sorgeberechtigten liegen vor. *
                      </label>
                    </div>
                  )}
                </fieldset>

                <fieldset style={{ border: 'none', padding: 0, marginBottom: '10px' }}>
                  <legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Musik enthalten? *</legend>
                  <div style={{ display: 'flex', gap: '14px' }}>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-cmu" checked={decl.contains_music === true}
                        onChange={() => setDeclField('contains_music', true)} disabled={busy} /> Ja
                    </label>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-cmu" checked={decl.contains_music === false}
                        onChange={() => setDeclField('contains_music', false)} disabled={busy} /> Nein
                    </label>
                  </div>
                  {decl.contains_music === true && (
                    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
                      <input type="checkbox" id="up-mrc" checked={decl.music_rights_confirmed}
                        onChange={(e) => setDeclField('music_rights_confirmed', e.target.checked)}
                        disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
                      <label htmlFor="up-mrc" style={{ fontSize: '0.85rem' }}>
                        Musikrechte (GEMA / Lizenz) liegen vor. *
                      </label>
                    </div>
                  )}
                </fieldset>

                <fieldset style={{ border: 'none', padding: 0, marginBottom: '4px' }}>
                  <legend style={{ fontSize: '0.85rem', fontWeight: 600, marginBottom: '4px' }}>Fremde geschützte Inhalte (Logos, Grafiken, Fotos Dritter)? *</legend>
                  <div style={{ display: 'flex', gap: '14px' }}>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-ctpc" checked={decl.contains_third_party_content === true}
                        onChange={() => setDeclField('contains_third_party_content', true)} disabled={busy} /> Ja
                    </label>
                    <label style={{ fontSize: '0.85rem' }}>
                      <input type="radio" name="up-ctpc" checked={decl.contains_third_party_content === false}
                        onChange={() => setDeclField('contains_third_party_content', false)} disabled={busy} /> Nein
                    </label>
                  </div>
                  {decl.contains_third_party_content === true && (
                    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px', marginTop: '6px' }}>
                      <input type="checkbox" id="up-tprc" checked={decl.third_party_rights_confirmed}
                        onChange={(e) => setDeclField('third_party_rights_confirmed', e.target.checked)}
                        disabled={busy} style={{ marginTop: '3px', flexShrink: 0 }} />
                      <label htmlFor="up-tprc" style={{ fontSize: '0.85rem' }}>
                        Rechte an allen enthaltenen Fremdmaterialien liegen vor. *
                      </label>
                    </div>
                  )}
                </fieldset>

                {declErr && (
                  <p style={{ color: 'var(--danger)', fontSize: '0.85rem', marginTop: '8px' }}>{declErr}</p>
                )}
              </div>
            </>
          )}
        </div>

        <div style={{ padding: '12px 14px', borderTop: '1px solid var(--border)', flexShrink: 0 }}>
          <div className="form-row" style={{ marginBottom: '12px' }}>
            <label className="form-label" style={{ marginBottom: '4px' }}>
              Darstellung im Text
            </label>
            <select className="form-input" value={displaySize} onChange={(e) => setDisplaySize(e.target.value)} disabled={busy}>
              {INLINE_MEDIA_SIZES.map((o) => (
                <option key={o.value} value={o.value}>
                  {o.label}
                </option>
              ))}
            </select>
          </div>
          {tab === 'library' ? (
            <button
              type="button"
              className="btn btn-primary btn-full"
              disabled={busy || !selectedAssetId}
              onClick={handleLinkSelected}
            >
              {busy ? 'Bitte warten…' : selectedLinked ? 'In Text einfügen (bereits verknüpft)' : 'Verknüpfen & in Text einfügen'}
            </button>
          ) : (
            <button type="button" className="btn btn-primary btn-full" disabled={busy || !uploadFile} onClick={handleUploadAndInsert}>
              {busy ? 'Hochladen…' : 'Hochladen & in Text einfügen'}
            </button>
          )}
        </div>
      </div>
    </div>
  )
}
