import React, { useCallback, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import api from '../utils/api'
import { activeClubMemberships } from '../utils/activeClub'

const VIS_LABELS = {
  private: 'Privat',
  club: 'Verein',
  official: 'Offiziell',
}

function collectExerciseRows(sections) {
  const map = new Map()
  for (const sec of sections || []) {
    for (const it of sec.items || []) {
      if (it.item_type === 'note') continue
      const id = Number(it.exercise_id)
      if (!Number.isFinite(id) || id < 1) continue
      if (!map.has(id)) {
        map.set(id, it)
      }
    }
  }
  return [...map.entries()].map(([id, it]) => ({
    id,
    title: it.exercise_title || `Übung #${id}`,
    visibility: it.exercise_visibility,
    clubId: it.exercise_club_id != null ? Number(it.exercise_club_id) : null,
    createdBy: it.exercise_created_by != null ? Number(it.exercise_created_by) : null,
    status: it.exercise_status,
  }))
}

function needsClubForTarget(row, targetClubId) {
  if (targetClubId == null || !Number.isFinite(Number(targetClubId))) return false
  const vis = String(row.visibility || 'private').toLowerCase()
  if (vis === 'official') return false
  const tc = Number(targetClubId)
  if (vis === 'private') return true
  if (vis === 'club') {
    if (row.clubId == null) return true
    return row.clubId !== tc
  }
  return false
}

function userMayPromote(user, targetClubId, createdBy) {
  if (!user || targetClubId == null) return false
  const role = String(user.role || '').toLowerCase()
  if (role === 'admin' || role === 'superadmin') return true
  if (createdBy != null && Number(createdBy) === Number(user.id)) return true
  const row = activeClubMemberships(user?.clubs).find((c) => Number(c.id) === Number(targetClubId))
  if (!row || !Array.isArray(row.roles)) return false
  return row.roles.includes('club_admin')
}

/**
 * Listen-Panel im Trainingsplan: Übungen, die für die gewählte Gruppe noch nicht vereinsweit sichtbar sind,
 * und Freigabe auf „Verein“ (API: PUT / bulk-metadata).
 */
export default function TrainingPlanExerciseVisibilityPanel({
  sections,
  targetClubId,
  user,
  onMetaRefresh,
}) {
  const [busyId, setBusyId] = useState(null)
  const [bulkBusy, setBulkBusy] = useState(false)
  const [message, setMessage] = useState(null)

  const rows = useMemo(() => collectExerciseRows(sections), [sections])

  const { pending, okCount } = useMemo(() => {
    if (targetClubId == null || !Number.isFinite(Number(targetClubId))) {
      return { pending: [], okCount: 0 }
    }
    const pending = []
    let okCount = 0
    for (const r of rows) {
      if (needsClubForTarget(r, targetClubId)) pending.push(r)
      else okCount += 1
    }
    return { pending, okCount }
  }, [rows, targetClubId])

  const promotableIds = useMemo(
    () => pending.filter((r) => userMayPromote(user, targetClubId, r.createdBy)).map((r) => r.id),
    [pending, targetClubId, user]
  )

  const applyClubVisibility = useCallback(
    async (exerciseIds) => {
      if (!exerciseIds.length || targetClubId == null) return
      setMessage(null)
      const res = await api.bulkPatchExercisesMetadata({
        exercise_ids: exerciseIds,
        visibility: 'club',
        club_id: targetClubId,
      })
      const failed = res?.failed || []
      const updatedN = Number(res?.updated_count || 0)
      if (updatedN > 0 && onMetaRefresh) {
        await onMetaRefresh()
      }
      if (failed.length) {
        const first = failed[0]?.detail || 'Unbekannter Fehler'
        setMessage(
          failed.length === 1
            ? String(first)
            : `${failed.length} Übungen nicht geändert: ${first}`
        )
      }
    },
    [targetClubId, onMetaRefresh]
  )

  const onPromoteOne = useCallback(
    async (id) => {
      setBusyId(id)
      setMessage(null)
      try {
        await applyClubVisibility([id])
      } catch (e) {
        setMessage(e?.message || String(e))
      } finally {
        setBusyId(null)
      }
    },
    [applyClubVisibility]
  )

  const onPromoteAll = useCallback(async () => {
    if (!promotableIds.length) return
    setBulkBusy(true)
    setMessage(null)
    try {
      await applyClubVisibility(promotableIds)
    } catch (e) {
      setMessage(e?.message || String(e))
    } finally {
      setBulkBusy(false)
    }
  }, [applyClubVisibility, promotableIds])

  if (!rows.length) return null

  return (
    <div
      className="training-planning-template-panel training-plan-visibility-panel no-print"
      style={{ marginBottom: '1.15rem' }}
    >
      <span className="training-planning-template-panel__label">Sichtbarkeit für den Verein</span>
      <p className="training-planning-template-panel__help" style={{ marginTop: 0 }}>
        Übungen mit Sichtbarkeit „Privat“ oder einem anderen Verein sieht das Team bei der Durchführung
        nicht. Hier können Sie sie auf <strong>Verein</strong> setzen (gleiche Logik wie beim Speichern der
        Einheit).
      </p>
      {targetClubId == null || !Number.isFinite(Number(targetClubId)) ? (
        <p style={{ margin: '0.35rem 0 0', fontSize: '0.82rem', color: 'var(--text3)', lineHeight: 1.45 }}>
          Wählen Sie eine Trainingsgruppe, um passende Freigaben anzuzeigen.
        </p>
      ) : null}
      {targetClubId != null && Number.isFinite(Number(targetClubId)) && !pending.length && rows.length ? (
        <p
          style={{
            margin: '0.5rem 0 0',
            fontSize: '0.88rem',
            color: 'var(--text2)',
            lineHeight: 1.45,
          }}
        >
          Alle {rows.length} {rows.length === 1 ? 'Übung ist' : 'Übungen sind'} für diesen Verein in der
          Durchführung sichtbar (oder offiziell).
        </p>
      ) : null}
      {targetClubId != null && Number.isFinite(Number(targetClubId)) && pending.length ? (
        <>
          <div
            style={{
              display: 'flex',
              flexWrap: 'wrap',
              alignItems: 'center',
              gap: '10px',
              marginTop: '0.65rem',
            }}
          >
            <button
              type="button"
              className="btn btn-secondary"
              disabled={!promotableIds.length || bulkBusy}
              onClick={onPromoteAll}
            >
              {bulkBusy ? 'Speichern…' : `Alle auf Verein (${promotableIds.length})`}
            </button>
            {okCount > 0 ? (
              <span style={{ fontSize: '0.82rem', color: 'var(--text3)' }}>
                {okCount} weitere {okCount === 1 ? 'Übung' : 'Übungen'} bereits passend
              </span>
            ) : null}
          </div>
          <ul
            style={{
              listStyle: 'none',
              margin: '0.75rem 0 0',
              padding: 0,
              display: 'flex',
              flexDirection: 'column',
              gap: '8px',
            }}
          >
            {pending.map((r) => {
              const vis = String(r.visibility || 'private').toLowerCase()
              const visLabel = VIS_LABELS[vis] || vis
              const may = userMayPromote(user, targetClubId, r.createdBy)
              const loading = busyId === r.id
              return (
                <li
                  key={r.id}
                  style={{
                    display: 'flex',
                    flexWrap: 'wrap',
                    alignItems: 'center',
                    gap: '10px',
                    padding: '10px 12px',
                    borderRadius: '10px',
                    border: '1px solid var(--border2)',
                    background: 'var(--surface)',
                  }}
                >
                  <div style={{ flex: '1 1 160px', minWidth: 0 }}>
                    <Link to={`/exercises/${r.id}`} style={{ fontWeight: 600, fontSize: '0.9rem' }}>
                      {r.title}
                    </Link>
                    <div style={{ fontSize: '0.78rem', color: 'var(--text3)', marginTop: '4px' }}>
                      Aktuell: {visLabel}
                      {vis === 'club' && r.clubId != null && r.clubId !== Number(targetClubId)
                        ? ` · anderer Verein (#${r.clubId})`
                        : ''}
                    </div>
                  </div>
                  <button
                    type="button"
                    className="btn btn-primary"
                    disabled={!may || loading || bulkBusy}
                    title={
                      may
                        ? 'Sichtbarkeit auf Verein setzen'
                        : 'Nur Ersteller, Plattform-Admin oder Vereinsorga (Admin im Verein)'
                    }
                    onClick={() => onPromoteOne(r.id)}
                  >
                    {loading ? '…' : 'Auf Verein'}
                  </button>
                </li>
              )
            })}
          </ul>
          {pending.some((r) => !userMayPromote(user, targetClubId, r.createdBy)) ? (
            <p className="training-planning-template-panel__help" style={{ marginTop: '0.65rem' }}>
              Einige Einträge können Sie nicht selbst freigeben: Denken Sie an die Vereinsorga oder speichern Sie
              die Einheit — bei ausreichender Berechtigung werden private Übungen dann automatisch mitgeführt.
            </p>
          ) : null}
        </>
      ) : null}
      {message ? (
        <p
          role="alert"
          style={{
            margin: '0.65rem 0 0',
            fontSize: '0.84rem',
            color: 'var(--danger, #c0392b)',
            lineHeight: 1.45,
          }}
        >
          {message}
        </p>
      ) : null}
    </div>
  )
}
