import { useCallback, useEffect, useMemo, useState } from 'react'
import type { StoryGroup } from './types/jira'
import { fetchAllIssuesByJql, MIGRATION_EPIC_KEY, MIGRATION_JQL, jiraClient } from './api/jiraClient'
import { groupSubtasksUnderStories } from './lib/groupIssues'
import { statusToPhase } from './lib/statusPhase'
import { appendBurnupSnapshot, loadBurnupHistory, type BurnupPoint } from './lib/burnupHistory'
import {
  loadDashboardConfig,
  saveDashboardConfig,
  type DashboardConfig,
} from './lib/dashboardConfig'
import { assigneeMatchesMyView } from './lib/assigneeMatch'
import { isAxiosError } from 'axios'
import { ExecutiveSummary } from './components/ExecutiveSummary'
import { BurnupChart } from './components/BurnupChart'
import { StoryCard } from './components/StoryCard'
import { BoardView } from './components/BoardView'
import { DashboardSkeleton } from './components/DashboardSkeleton'
import { MilestonesTimeline } from './components/MilestonesTimeline'
import { DashboardSettingsModal } from './components/DashboardSettingsModal'

type ViewMode = 'list' | 'board'

export default function App() {
  const [groups, setGroups] = useState<StoryGroup[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [updatedAt, setUpdatedAt] = useState<Date | null>(null)
  const [view, setView] = useState<ViewMode>('list')
  const [burnupData, setBurnupData] = useState<BurnupPoint[]>(() => loadBurnupHistory())
  const [dashboardCfg, setDashboardCfg] = useState<DashboardConfig>(() => loadDashboardConfig())
  const [settingsOpen, setSettingsOpen] = useState(false)

  const myViewActive = Boolean(dashboardCfg.myViewActive)

  const displayGroups = useMemo(() => {
    if (!myViewActive) return groups
    return groups.filter((g) =>
      g.subtasks.some((st) => assigneeMatchesMyView(st, dashboardCfg)),
    )
  }, [groups, myViewActive, dashboardCfg])

  const toggleMyView = () => {
    const next: DashboardConfig = { ...dashboardCfg, myViewActive: !myViewActive }
    setDashboardCfg(next)
    saveDashboardConfig(next)
  }

  const saveSettings = (next: DashboardConfig) => {
    setDashboardCfg(next)
    saveDashboardConfig(next)
  }

  const load = useCallback(async (signal?: AbortSignal) => {
    setLoading(true)
    setError(null)
    try {
      const issues = await fetchAllIssuesByJql(MIGRATION_JQL, signal)
      const grouped = groupSubtasksUnderStories(issues)
      setGroups(grouped)
      setUpdatedAt(new Date())

      const totalSubs = grouped.reduce((acc, g) => acc + g.subtasks.length, 0)
      const doneSubs = grouped.reduce(
        (acc, g) =>
          acc +
          g.subtasks.filter((s) => statusToPhase(s.fields.status.name) === 'done').length,
        0,
      )
      setBurnupData(appendBurnupSnapshot(doneSubs, totalSubs))
    } catch (e) {
      if (signal?.aborted || (isAxiosError(e) && e.code === 'ERR_CANCELED')) {
        return
      }
      if (isAxiosError(e)) {
        const msg =
          typeof e.response?.data === 'object' &&
          e.response.data !== null &&
          'errorMessages' in e.response.data &&
          Array.isArray((e.response.data as { errorMessages: string[] }).errorMessages)
            ? (e.response.data as { errorMessages: string[] }).errorMessages.join(' ')
            : e.message
        setError(msg || 'Erreur réseau Jira')
      } else {
        setError(e instanceof Error ? e.message : 'Erreur inconnue')
      }
      setGroups([])
    } finally {
      if (!signal?.aborted) setLoading(false)
    }
  }, [])

  useEffect(() => {
    const ac = new AbortController()
    void load(ac.signal)
    return () => ac.abort()
  }, [load])

  const baseOk = import.meta.env.DEV ? true : Boolean(jiraClient.defaults.baseURL)

  return (
    <div className="min-h-screen px-4 pb-20 pt-8 sm:px-6 md:px-8 md:pt-10">
      <header className="mx-auto mb-6 flex max-w-7xl flex-col gap-4 lg:mb-8 lg:flex-row lg:items-end lg:justify-between">
        <div>
          <p className="text-xs font-semibold uppercase tracking-[0.2em] text-cyan-300/90">
            OroCommerce · Migration exécutive
          </p>
          <h1 className="mt-1 text-3xl font-semibold tracking-tight text-white md:text-4xl">
            Pilotage migration
          </h1>
          <p className="mt-2 max-w-2xl text-sm text-slate-400">
            Périmètre DCC sous l’épopée{' '}
            <span className="font-mono text-slate-200">{MIGRATION_EPIC_KEY}</span> (JQL{' '}
            <span className="font-mono text-slate-400">parentEpic</span>, sous-tâches incluses),
            parent résolu (clé ou id), jalons, export JSON pour Synology.
          </p>
        </div>
        <div className="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center">
          <div className="flex flex-wrap items-center gap-2">
            <button
              type="button"
              onClick={toggleMyView}
              className={`rounded-xl border px-4 py-2.5 text-sm font-semibold transition ${
                myViewActive
                  ? 'border-cyan-400/60 bg-cyan-500/20 text-cyan-50 shadow-[0_0_16px_rgba(34,211,238,0.25)]'
                  : 'border-white/10 bg-slate-950/50 text-slate-300 hover:border-white/20 hover:text-white'
              }`}
              title="Stories avec au moins une sous-tâche qui vous est assignée (accountId ou e-mail configurés)."
            >
              Ma vue
            </button>
            <button
              type="button"
              onClick={() => setSettingsOpen(true)}
              className="rounded-xl border border-white/10 bg-slate-950/50 px-4 py-2.5 text-sm font-medium text-slate-300 transition hover:border-white/20 hover:text-white"
            >
              Réglages
            </button>
          </div>
          <div className="flex rounded-xl border border-white/10 bg-slate-950/50 p-1 backdrop-blur-md">
            <button
              type="button"
              onClick={() => setView('list')}
              className={`rounded-lg px-4 py-2 text-sm font-medium transition ${
                view === 'list'
                  ? 'bg-cyan-500/20 text-cyan-100 shadow-[0_0_12px_rgba(34,211,238,0.2)]'
                  : 'text-slate-400 hover:text-white'
              }`}
            >
              Liste
            </button>
            <button
              type="button"
              onClick={() => setView('board')}
              className={`rounded-lg px-4 py-2 text-sm font-medium transition ${
                view === 'board'
                  ? 'bg-cyan-500/20 text-cyan-100 shadow-[0_0_12px_rgba(34,211,238,0.2)]'
                  : 'text-slate-400 hover:text-white'
              }`}
            >
              Board
            </button>
          </div>
          <div className="flex flex-wrap items-center gap-3">
            {updatedAt && !loading && (
              <span className="text-xs text-slate-500">
                Mis à jour {updatedAt.toLocaleTimeString('fr-FR')}
              </span>
            )}
            <button
              type="button"
              onClick={() => void load(undefined)}
              disabled={loading}
              className="inline-flex items-center justify-center rounded-xl bg-cyan-500 px-4 py-2.5 text-sm font-semibold text-slate-950 shadow-lg shadow-cyan-500/25 transition hover:bg-cyan-400 disabled:cursor-not-allowed disabled:opacity-60"
            >
              {loading ? 'Chargement…' : 'Actualiser'}
            </button>
          </div>
        </div>
      </header>

      <main className="mx-auto max-w-7xl">
        {!baseOk && (
          <div className="mb-6 rounded-xl border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-sm text-amber-100">
            Configurez <code className="rounded bg-black/30 px-1">VITE_JIRA_BASE_URL</code> pour
            un build de production pointant vers votre proxy HTTPS (le proxy Vite ne s’applique
            qu’en <code className="rounded bg-black/30 px-1">npm run dev</code>).
          </div>
        )}

        {error && (
          <div
            className="mb-6 rounded-xl border border-rose-500/40 bg-rose-950/40 px-4 py-3 text-sm text-rose-100"
            role="alert"
          >
            {error}
          </div>
        )}

        {loading && <DashboardSkeleton />}

        {!loading && !error && groups.length === 0 && (
          <p className="rounded-2xl border border-white/10 bg-slate-950/35 px-6 py-10 text-center text-slate-400 backdrop-blur-md">
            Aucun ticket ne correspond au JQL actuel.
          </p>
        )}

        {!loading && !error && groups.length > 0 && (
          <>
            <MilestonesTimeline
              milestones={dashboardCfg.milestones}
              groups={groups}
              onOpenSettings={() => setSettingsOpen(true)}
            />

            <ExecutiveSummary groups={displayGroups} />

            <section className="mb-10">
              <h2 className="mb-3 text-sm font-semibold uppercase tracking-[0.18em] text-slate-400">
                Burnup
              </h2>
              <BurnupChart data={burnupData} />
            </section>

            <section>
              <div className="mb-4 flex flex-wrap items-end justify-between gap-2">
                <h2 className="text-sm font-semibold uppercase tracking-[0.18em] text-slate-400">
                  {view === 'list' ? 'Stories (liste)' : 'Stories par composant'}
                </h2>
                {myViewActive && (
                  <span className="text-xs text-cyan-300/90">
                    Filtre actif : {displayGroups.length} / {groups.length} stories
                  </span>
                )}
              </div>
              {displayGroups.length === 0 ? (
                <p className="rounded-2xl border border-white/10 bg-slate-950/35 px-6 py-8 text-center text-sm text-slate-400 backdrop-blur-md">
                  Aucune story ne correspond à « Ma vue ». Vérifiez vos assignations ou configurez
                  votre accountId / e-mail dans les réglages.
                </p>
              ) : view === 'list' ? (
                <div className="grid grid-cols-1 gap-5 lg:grid-cols-2">
                  {displayGroups.map((g) => (
                    <StoryCard key={g.story.key} group={g} />
                  ))}
                </div>
              ) : (
                <BoardView groups={displayGroups} />
              )}
            </section>
          </>
        )}
      </main>

      <DashboardSettingsModal
        open={settingsOpen}
        config={dashboardCfg}
        onClose={() => setSettingsOpen(false)}
        onSave={saveSettings}
      />
    </div>
  )
}
