import React, { useState, useEffect, useMemo, useCallback } from 'react'
import { Link } from 'react-router-dom'
import api from '../utils/api'
import { SKILL_LEVEL_OPTIONS } from '../constants/skillLevels'
import MultiSelectCombo from '../components/MultiSelectCombo'
import ExerciseProgressionGraphPanel from '../components/ExerciseProgressionGraphPanel'

const PAGE_SIZE = 100
const LEVEL_FILTER_OPTS = SKILL_LEVEL_OPTIONS.filter((o) => o.level != null)

const INITIAL_FILTERS = {
  focus_area_ids: [],
  style_direction_ids: [],
  training_type_ids: [],
  target_group_ids: [],
  skill_ids: [],
  skill_min_level: '',
  skill_max_level: '',
  visibility_any: [],
  status_any: [],
}

function levelOptionShort(levelStr) {
  const o = LEVEL_FILTER_OPTS.find((x) => String(x.level) === String(levelStr))
  return o ? String(o.level) : String(levelStr)
}

function ExercisesListPage() {
  const [exercises, setExercises] = useState([])
  const [catalogs, setCatalogs] = useState({
    focusAreas: [],
    styleDirections: [],
    trainingTypes: [],
    targetGroups: [],
    skills: [],
  })
  const [catalogsReady, setCatalogsReady] = useState(false)
  const [listFetching, setListFetching] = useState(false)
  const [loadingMore, setLoadingMore] = useState(false)
  const [offset, setOffset] = useState(0)
  const [hasMore, setHasMore] = useState(false)
  const [searchInput, setSearchInput] = useState('')
  const [aiSearchInput, setAiSearchInput] = useState('')
  const [debouncedSearch, setDebouncedSearch] = useState('')
  const [debouncedAiSearch, setDebouncedAiSearch] = useState('')
  const [filters, setFilters] = useState(() => ({ ...INITIAL_FILTERS }))
  const [filterModalOpen, setFilterModalOpen] = useState(false)
  const [pageTab, setPageTab] = useState('list')

  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(searchInput.trim()), 400)
    return () => clearTimeout(t)
  }, [searchInput])

  useEffect(() => {
    const t = setTimeout(() => setDebouncedAiSearch(aiSearchInput.trim()), 400)
    return () => clearTimeout(t)
  }, [aiSearchInput])

  useEffect(() => {
    if (!filterModalOpen) return
    const onKey = (e) => {
      if (e.key === 'Escape') setFilterModalOpen(false)
    }
    window.addEventListener('keydown', onKey)
    return () => window.removeEventListener('keydown', onKey)
  }, [filterModalOpen])

  const focusOptions = useMemo(
    () =>
      catalogs.focusAreas.map((fa) => ({
        id: fa.id,
        label: `${fa.icon || ''} ${fa.name || ''}`.trim(),
      })),
    [catalogs.focusAreas]
  )
  const styleOptions = useMemo(
    () => catalogs.styleDirections.map((s) => ({ id: s.id, label: s.name || String(s.id) })),
    [catalogs.styleDirections]
  )
  const trainingTypeOptions = useMemo(
    () => catalogs.trainingTypes.map((t) => ({ id: t.id, label: t.name || String(t.id) })),
    [catalogs.trainingTypes]
  )
  const targetGroupOptions = useMemo(
    () => catalogs.targetGroups.map((g) => ({ id: g.id, label: g.name || String(g.id) })),
    [catalogs.targetGroups]
  )
  const skillOptions = useMemo(
    () => catalogs.skills.map((s) => ({ id: s.id, label: s.name || String(s.id) })),
    [catalogs.skills]
  )
  const visibilityOptions = useMemo(
    () => [
      { id: 'private', label: 'Privat' },
      { id: 'club', label: 'Verein' },
      { id: 'official', label: 'Offiziell' },
    ],
    []
  )
  const statusOptions = useMemo(
    () => [
      { id: 'draft', label: 'Entwurf' },
      { id: 'in_review', label: 'In Prüfung' },
      { id: 'approved', label: 'Freigegeben' },
      { id: 'archived', label: 'Archiviert' },
    ],
    []
  )

  const filterChips = useMemo(() => {
    const chips = []

    ;(filters.focus_area_ids || []).forEach((id) => {
      const opt = focusOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `fa-${id}`,
        label: `Fokus: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            focus_area_ids: prev.focus_area_ids.filter((x) => String(x) !== String(id)),
          })),
      })
    })
    ;(filters.style_direction_ids || []).forEach((id) => {
      const opt = styleOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `sd-${id}`,
        label: `Stil: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            style_direction_ids: prev.style_direction_ids.filter((x) => String(x) !== String(id)),
          })),
      })
    })
    ;(filters.training_type_ids || []).forEach((id) => {
      const opt = trainingTypeOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `tt-${id}`,
        label: `Trainingsstil: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            training_type_ids: prev.training_type_ids.filter((x) => String(x) !== String(id)),
          })),
      })
    })
    ;(filters.target_group_ids || []).forEach((id) => {
      const opt = targetGroupOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `tg-${id}`,
        label: `Zielgruppe: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            target_group_ids: prev.target_group_ids.filter((x) => String(x) !== String(id)),
          })),
      })
    })
    ;(filters.skill_ids || []).forEach((id) => {
      const opt = skillOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `sk-${id}`,
        label: `Fähigkeit: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            skill_ids: prev.skill_ids.filter((x) => String(x) !== String(id)),
          })),
      })
    })

    if (filters.skill_min_level || filters.skill_max_level) {
      const a = filters.skill_min_level ? levelOptionShort(filters.skill_min_level) : '…'
      const b = filters.skill_max_level ? levelOptionShort(filters.skill_max_level) : '…'
      chips.push({
        key: 'skill-levels',
        label: `Stufe ${a}–${b}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            skill_min_level: '',
            skill_max_level: '',
          })),
      })
    }

    ;(filters.visibility_any || []).forEach((id) => {
      const opt = visibilityOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `vis-${id}`,
        label: `Sichtbarkeit: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            visibility_any: prev.visibility_any.filter((x) => String(x) !== String(id)),
          })),
      })
    })
    ;(filters.status_any || []).forEach((id) => {
      const opt = statusOptions.find((o) => String(o.id) === String(id))
      chips.push({
        key: `st-${id}`,
        label: `Status: ${opt?.label ?? id}`,
        onRemove: () =>
          setFilters((prev) => ({
            ...prev,
            status_any: prev.status_any.filter((x) => String(x) !== String(id)),
          })),
      })
    })

    return chips
  }, [
    filters,
    focusOptions,
    styleOptions,
    trainingTypeOptions,
    targetGroupOptions,
    skillOptions,
    visibilityOptions,
    statusOptions,
  ])

  /** Für Browser-/datalist-Vorschläge (aktuelle Treffer-Titel, begrenzt) */
  const searchTitleSuggestions = useMemo(() => {
    const titles = exercises.map((e) => (e.title || '').trim()).filter(Boolean)
    return [...new Set(titles)].slice(0, 80)
  }, [exercises])

  const queryBase = useMemo(() => {
    const q = {}
    const n = (v) => (v === '' || v == null ? undefined : Number(v))
    const ids = (arr) =>
      Array.isArray(arr) && arr.length ? arr.map((x) => Number(x)).filter((x) => !Number.isNaN(x)) : undefined
    const fa = ids(filters.focus_area_ids)
    if (fa?.length) q.focus_area_ids = fa
    const sd = ids(filters.style_direction_ids)
    if (sd?.length) q.style_direction_ids = sd
    const tt = ids(filters.training_type_ids)
    if (tt?.length) q.training_type_ids = tt
    const tg = ids(filters.target_group_ids)
    if (tg?.length) q.target_group_ids = tg
    const sk = ids(filters.skill_ids)
    if (sk?.length) q.skill_ids = sk
    if (filters.skill_min_level) q.skill_min_level = n(filters.skill_min_level)
    if (filters.skill_max_level) q.skill_max_level = n(filters.skill_max_level)
    if (filters.visibility_any?.length) q.visibility_any = [...filters.visibility_any]
    if (filters.status_any?.length) q.status_any = [...filters.status_any]
    if (debouncedSearch) q.search = debouncedSearch
    if (debouncedAiSearch) q.ai_search = debouncedAiSearch
    return q
  }, [filters, debouncedSearch, debouncedAiSearch])

  useEffect(() => {
    let cancelled = false
    ;(async () => {
      try {
        const [fa, sd, tt, tg, sk] = await Promise.all([
          api.listFocusAreas(),
          api.listStyleDirections(),
          api.listTrainingTypes(),
          api.listTargetGroups(),
          api.listSkills(),
        ])
        if (!cancelled) {
          setCatalogs({
            focusAreas: fa,
            styleDirections: sd,
            trainingTypes: tt,
            targetGroups: tg,
            skills: sk,
          })
          setCatalogsReady(true)
        }
      } catch (err) {
        if (!cancelled) {
          console.error(err)
          alert('Kataloge konnten nicht geladen werden: ' + err.message)
          setCatalogsReady(true)
        }
      }
    })()
    return () => {
      cancelled = true
    }
  }, [])

  useEffect(() => {
    if (!catalogsReady || pageTab !== 'list') return
    let cancelled = false
    const run = async () => {
      setListFetching(true)
      setOffset(0)
      try {
        const batch = await api.listExercises({ ...queryBase, limit: PAGE_SIZE, offset: 0 })
        if (cancelled) return
        setExercises(batch)
        setHasMore(batch.length === PAGE_SIZE)
        setOffset(batch.length)
      } catch (err) {
        if (!cancelled) {
          console.error('Failed to load data:', err)
          alert('Fehler beim Laden: ' + err.message)
        }
      } finally {
        if (!cancelled) setListFetching(false)
      }
    }
    run()
    return () => {
      cancelled = true
    }
  }, [queryBase, catalogsReady, pageTab])

  const loadMore = async () => {
    if (loadingMore || !hasMore) return
    setLoadingMore(true)
    try {
      const batch = await api.listExercises({ ...queryBase, limit: PAGE_SIZE, offset })
      setExercises((prev) => [...prev, ...batch])
      setHasMore(batch.length === PAGE_SIZE)
      setOffset((o) => o + batch.length)
    } catch (err) {
      alert('Fehler: ' + err.message)
    } finally {
      setLoadingMore(false)
    }
  }

  const handleDelete = async (exercise) => {
    if (!confirm(`Übung "${exercise.title}" wirklich löschen?`)) return
    try {
      await api.deleteExercise(exercise.id)
      setExercises((prev) => prev.filter((e) => e.id !== exercise.id))
    } catch (err) {
      alert('Fehler beim Löschen: ' + err.message)
    }
  }

  const resetAllFilters = useCallback(() => setFilters({ ...INITIAL_FILTERS }), [])

  if (!catalogsReady && pageTab === 'list') {
    return (
      <div style={{ padding: '2rem', textAlign: 'center' }}>
        <div className="spinner"></div>
        <p>Lade Kataloge…</p>
      </div>
    )
  }

  return (
    <div className="app-page">
      <div
        style={{
          display: 'flex',
          justifyContent: 'space-between',
          alignItems: 'center',
          marginBottom: '12px',
          flexWrap: 'wrap',
          gap: '8px',
        }}
      >
        <h1 style={{ fontSize: '1.35rem' }}>Übungen</h1>
        {pageTab === 'list' ? (
          <Link to="/exercises/new" className="btn btn-primary">
            + Neu
          </Link>
        ) : (
          <span />
        )}
      </div>

      <div
        role="tablist"
        aria-label="Übungen Bereiche"
        style={{ display: 'flex', gap: '8px', marginBottom: '14px', flexWrap: 'wrap' }}
      >
        <button
          type="button"
          role="tab"
          aria-selected={pageTab === 'list'}
          className={pageTab === 'list' ? 'btn btn-primary' : 'btn btn-secondary'}
          onClick={() => setPageTab('list')}
        >
          Liste
        </button>
        <button
          type="button"
          role="tab"
          aria-selected={pageTab === 'progression'}
          className={pageTab === 'progression' ? 'btn btn-primary' : 'btn btn-secondary'}
          onClick={() => setPageTab('progression')}
        >
          Progressionsgraphen
        </button>
      </div>

      {pageTab === 'progression' ? (
        <ExerciseProgressionGraphPanel />
      ) : (
        <>
      <div className="card exercise-search-bar" style={{ marginBottom: '12px' }}>
        <label className="form-label">Volltextsuche (Titel, Ziel, …)</label>
        <datalist id="exercise-search-titles">
          {searchTitleSuggestions.map((t) => (
            <option key={t} value={t} />
          ))}
        </datalist>
        <input
          type="search"
          className="form-input"
          placeholder="Suchbegriffe…"
          value={searchInput}
          onChange={(e) => setSearchInput(e.target.value)}
          autoComplete="on"
          name="exercise-fulltext-search"
          list="exercise-search-titles"
          enterKeyHint="search"
          style={{ marginBottom: '10px' }}
        />
        <label className="form-label">Ergänzende Suche / KI-Vorbereitung (Beta)</label>
        <input
          type="search"
          className="form-input"
          placeholder="zweiter Begriff — zusätzliche Volltextsuche (ODER)"
          value={aiSearchInput}
          onChange={(e) => setAiSearchInput(e.target.value)}
          autoComplete="on"
          name="exercise-ai-search"
          list="exercise-search-titles"
          enterKeyHint="search"
        />
        <div className="exercise-search-bar__actions">
          <button type="button" className="btn btn-secondary exercise-filter-trigger" onClick={() => setFilterModalOpen(true)}>
            Filter
            {filterChips.length > 0 ? (
              <span className="exercise-filter-badge" aria-hidden>
                {filterChips.length}
              </span>
            ) : null}
          </button>
          {filterChips.length > 0 ? (
            <button type="button" className="btn" onClick={resetAllFilters}>
              Alle entfernen
            </button>
          ) : null}
        </div>
        {filterChips.length > 0 ? (
          <div className="exercise-filter-chips-row" role="list" aria-label="Aktive Filter">
            {filterChips.map((c) => (
              <button
                key={c.key}
                type="button"
                role="listitem"
                className="exercise-filter-chip"
                title="Filter entfernen"
                onClick={() => c.onRemove()}
              >
                <span className="exercise-filter-chip__text">{c.label}</span>
                <span className="exercise-filter-chip__x" aria-hidden>
                  ×
                </span>
              </button>
            ))}
          </div>
        ) : null}
        <p style={{ fontSize: '12px', color: 'var(--text3)', marginTop: '10px', marginBottom: 0 }}>
          Trefferliste aktualisiert sich kurz nach Eingabe. Titel der aktuellen Liste erscheinen als Vorschläge (Pfeil im
          Feld). Fachliche Filter über „Filter“ – zwischen Feldern UND, Auswahl mehrerer Werte je Feld mit ODER.
        </p>
      </div>

      {filterModalOpen && (
        <div
          className="admin-modal-backdrop"
          role="presentation"
          onClick={(e) => {
            if (e.target === e.currentTarget) setFilterModalOpen(false)
          }}
        >
          <div
            className="admin-modal-sheet exercise-filter-modal"
            role="dialog"
            aria-modal="true"
            aria-labelledby="exercise-filter-modal-title"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="admin-modal-sheet__header">
              <h3 id="exercise-filter-modal-title" className="admin-modal-sheet__title">
                Übungen filtern
              </h3>
              <button
                type="button"
                className="btn btn-secondary admin-modal-sheet__close"
                onClick={() => setFilterModalOpen(false)}
              >
                Schließen
              </button>
            </div>
            <div className="admin-modal-sheet__body exercise-filter-modal__scroll">
              <p style={{ fontSize: '13px', color: 'var(--text2)', marginTop: 0, marginBottom: '14px' }}>
                Zwischen den Bereichen gilt <strong>UND</strong>. Innerhalb eines Feldes werden mehrere Einträge mit{' '}
                <strong>ODER</strong> verknüpft.
              </p>

              <section className="exercise-filter-section">
                <h4 className="exercise-filter-section-title">Zuordnung</h4>
                <div className="exercise-filters-modal-grid">
                  <div>
                    <label className="form-label">Fokus</label>
                    <MultiSelectCombo
                      value={filters.focus_area_ids}
                      onChange={(v) => setFilters({ ...filters, focus_area_ids: v })}
                      options={focusOptions}
                      placeholder="Fokus suchen oder „▼ Alle“ …"
                    />
                  </div>
                  <div>
                    <label className="form-label">Stilrichtung</label>
                    <MultiSelectCombo
                      value={filters.style_direction_ids}
                      onChange={(v) => setFilters({ ...filters, style_direction_ids: v })}
                      options={styleOptions}
                      placeholder="Stilrichtung suchen …"
                    />
                  </div>
                  <div>
                    <label className="form-label">Trainingsstil</label>
                    <MultiSelectCombo
                      value={filters.training_type_ids}
                      onChange={(v) => setFilters({ ...filters, training_type_ids: v })}
                      options={trainingTypeOptions}
                      placeholder="Trainingsstil suchen …"
                    />
                  </div>
                  <div>
                    <label className="form-label">Zielgruppe</label>
                    <MultiSelectCombo
                      value={filters.target_group_ids}
                      onChange={(v) => setFilters({ ...filters, target_group_ids: v })}
                      options={targetGroupOptions}
                      placeholder="Zielgruppe suchen …"
                    />
                  </div>
                </div>
              </section>

              <section className="exercise-filter-section">
                <h4 className="exercise-filter-section-title">Fähigkeit und zugehörige Stufe</h4>
                <div className="exercise-filter-skill-block">
                  <label className="form-label">Fähigkeit</label>
                  <MultiSelectCombo
                    value={filters.skill_ids}
                    onChange={(v) => setFilters({ ...filters, skill_ids: v })}
                    options={skillOptions}
                    placeholder="Fähigkeit suchen …"
                  />
                  <p className="exercise-filter-skill-hint">
                    Die Stufen filtern nach dem Niveau der Zuordnung Übung ↔ Fähigkeit (von–bis).
                  </p>
                  <div className="exercise-filter-skill-levels-row">
                    <label className="exercise-filter-skill-level-field">
                      <span className="exercise-filter-skill-level-caption">von</span>
                      <select
                        className="form-input exercise-filter-level-select"
                        title="Mindest-Stufe"
                        value={filters.skill_min_level}
                        onChange={(e) => setFilters({ ...filters, skill_min_level: e.target.value })}
                      >
                        <option value="">–</option>
                        {LEVEL_FILTER_OPTS.map((o) => (
                          <option key={o.value} value={String(o.level)} title={o.label}>
                            {o.level}
                          </option>
                        ))}
                      </select>
                    </label>
                    <span className="exercise-filter-skill-dash" aria-hidden>
                      –
                    </span>
                    <label className="exercise-filter-skill-level-field">
                      <span className="exercise-filter-skill-level-caption">bis</span>
                      <select
                        className="form-input exercise-filter-level-select"
                        title="Höchst-Stufe"
                        value={filters.skill_max_level}
                        onChange={(e) => setFilters({ ...filters, skill_max_level: e.target.value })}
                      >
                        <option value="">–</option>
                        {LEVEL_FILTER_OPTS.map((o) => (
                          <option key={`m-${o.value}`} value={String(o.level)} title={o.label}>
                            {o.level}
                          </option>
                        ))}
                      </select>
                    </label>
                  </div>
                </div>
              </section>

              <section className="exercise-filter-section exercise-filter-section--last">
                <h4 className="exercise-filter-section-title">Freigabe</h4>
                <div className="exercise-filters-modal-grid exercise-filters-modal-grid--two">
                  <div>
                    <label className="form-label">Sichtbarkeit</label>
                    <MultiSelectCombo
                      value={filters.visibility_any}
                      onChange={(v) => setFilters({ ...filters, visibility_any: v })}
                      options={visibilityOptions}
                      placeholder="Sichtbarkeit wählen …"
                    />
                  </div>
                  <div>
                    <label className="form-label">Status</label>
                    <MultiSelectCombo
                      value={filters.status_any}
                      onChange={(v) => setFilters({ ...filters, status_any: v })}
                      options={statusOptions}
                      placeholder="Status wählen …"
                    />
                  </div>
                </div>
              </section>
            </div>
            <div className="exercise-filter-modal__footer">
              <button type="button" className="btn" onClick={resetAllFilters}>
                Alle Filter zurücksetzen
              </button>
              <button type="button" className="btn btn-primary" onClick={() => setFilterModalOpen(false)}>
                Fertig
              </button>
            </div>
          </div>
        </div>
      )}

      {listFetching && exercises.length === 0 ? (
        <div className="card" style={{ textAlign: 'center', padding: '2rem' }}>
          <div className="spinner"></div>
          <p style={{ color: 'var(--text2)', marginTop: '12px' }}>Lade Übungen…</p>
        </div>
      ) : exercises.length === 0 ? (
        <div className="card">
          <p style={{ color: 'var(--text2)', textAlign: 'center' }}>
            Keine Übungen gefunden.
          </p>
        </div>
      ) : (
        <>
          {listFetching ? (
            <p style={{ fontSize: '13px', color: 'var(--text3)', marginBottom: '8px' }}>Aktualisiere Treffer…</p>
          ) : null}
          <p style={{ fontSize: '13px', color: 'var(--text2)', marginBottom: '10px' }}>
            {exercises.length} angezeigt
            {hasMore ? ' · es gibt weitere Einträge' : ''}
          </p>
          <div
            style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
              gap: '12px',
            }}
          >
            {exercises.map((exercise) => (
              <div key={exercise.id} className="card exercise-card">
                <div className="exercise-card__body">
                  <h3 style={{ marginBottom: '8px', fontSize: '1.05rem', lineHeight: 1.3 }}>
                    <Link
                      to={`/exercises/${exercise.id}`}
                      style={{ color: 'inherit', textDecoration: 'none' }}
                    >
                      {exercise.title}
                    </Link>
                  </h3>
                  <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap', marginBottom: '8px' }}>
                    {exercise.focus_area && (
                      <span className="exercise-tag exercise-tag--accent">{exercise.focus_area}</span>
                    )}
                    <span className="exercise-tag">{exercise.visibility}</span>
                    <span className="exercise-tag">{exercise.status}</span>
                  </div>
                  {exercise.summary && (
                    <p style={{ color: 'var(--text2)', fontSize: '13px', lineHeight: 1.4 }}>
                      {exercise.summary.length > 160
                        ? `${exercise.summary.slice(0, 160)}…`
                        : exercise.summary}
                    </p>
                  )}
                </div>
                <div className="exercise-card__actions">
                  <Link to={`/exercises/${exercise.id}`} className="btn btn-secondary">
                    Ansehen
                  </Link>
                  <Link to={`/exercises/${exercise.id}/edit`} className="btn btn-secondary">
                    Bearbeiten
                  </Link>
                  <button
                    type="button"
                    className="btn"
                    style={{
                      background: 'var(--danger)',
                      color: 'white',
                      border: 'none',
                    }}
                    onClick={() => handleDelete(exercise)}
                  >
                    Löschen
                  </button>
                </div>
              </div>
            ))}
          </div>
          {hasMore && (
            <div style={{ textAlign: 'center', marginTop: '16px' }}>
              <button type="button" className="btn btn-secondary" disabled={loadingMore} onClick={loadMore}>
                {loadingMore ? 'Laden…' : 'Mehr laden'}
              </button>
            </div>
          )}
        </>
      )}
    </>
      )}
    </div>
  )
}

export default ExercisesListPage
