import { useCallback, useEffect, useState } from 'react'
import { api } from './api'
import { loadAllBundles } from './persist'
import { ErrorBox } from './hooks'
import Stepper from './components/Stepper'
import ReelBar from './components/ReelBar'
import CloneBar from './components/CloneBar'
import SetupStep from './steps/SetupStep'
import ReferencesStep from './steps/ReferencesStep'
import TopicsStep from './steps/TopicsStep'
import ScriptStep from './steps/ScriptStep'
import MediaStep from './steps/MediaStep'
import EffectsStep from './steps/EffectsStep'
import RenderStep from './steps/RenderStep'
import ReviewStep from './steps/ReviewStep'

export const STEPS = ['Setup', 'References', 'Topics', 'Script', 'Media', 'Effects', 'Render', 'Review']
const REEL_STEP_START = 3 // steps >= this operate on the selected reel

export default function App() {
  const [projects, setProjects] = useState(null)
  const [projectId, setProjectId] = useState(null)
  const [data, setData] = useState(null) // project-level: {project, style, topics, reels}
  const [reelId, setReelId] = useState(null)
  const [reelData, setReelData] = useState(null) // {reel, script, voice, media, renders, clone}
  const [step, setStep] = useState(0)
  const [error, setError] = useState('')

  // Replay a browser-cached project onto the server (returns true if it did).
  // Used when the server (ephemeral hosting) has wiped a project we still hold.
  const restoreFromCache = useCallback(async (pid) => {
    const bundle = (await loadAllBundles()).find((b) => b.project_id === pid)
    if (!bundle) return false
    try { await api.post('/api/projects/import', bundle); return true } catch { return false }
  }, [])

  const loadProjects = useCallback(async () => {
    try {
      let serverList = await api.get('/api/projects')
      const bundles = await loadAllBundles()
      const serverIds = new Set(serverList.map((p) => p.id))
      const missing = bundles.filter((b) => b.project_id && !serverIds.has(b.project_id))
      if (missing.length) {
        // Server lost these (restart/wipe) but the browser still has them.
        await Promise.all(missing.map((b) => api.post('/api/projects/import', b).catch(() => {})))
        serverList = await api.get('/api/projects')
      }
      setProjects(serverList)
    } catch (e) {
      setError(e.message)
    }
  }, [])

  const refreshProject = useCallback(async () => {
    if (!projectId) return null
    try {
      const d = await api.get(`/api/projects/${projectId}`)
      setData(d)
      return d
    } catch (e) {
      if (await restoreFromCache(projectId)) {
        try { const d = await api.get(`/api/projects/${projectId}`); setData(d); return d } catch { /* fall through */ }
      }
      setError(e.message)
      return null
    }
  }, [projectId, restoreFromCache])

  const refreshReel = useCallback(async () => {
    if (!projectId || !reelId) { setReelData(null); return null }
    try {
      const d = await api.get(`/api/projects/${projectId}/reels/${reelId}`)
      setReelData(d)
      return d
    } catch (e) {
      if (await restoreFromCache(projectId)) {
        try { const d = await api.get(`/api/projects/${projectId}/reels/${reelId}`); setReelData(d); return d } catch { /* fall through */ }
      }
      setError(e.message)
      return null
    }
  }, [projectId, reelId, restoreFromCache])

  useEffect(() => { loadProjects() }, [loadProjects])
  useEffect(() => { setData(null); setReelId(null); setReelData(null); refreshProject() }, [projectId, refreshProject])
  useEffect(() => { refreshReel() }, [reelId, refreshReel])

  const selectReel = (id) => { setReelId(id); setStep(REEL_STEP_START) }

  const newReel = async () => {
    const reel = await api.post(`/api/projects/${projectId}/reels`, {}).catch((e) => { setError(e.message) })
    if (reel) { await refreshProject(); selectReel(reel.id) }
  }

  const deleteReel = async (id) => {
    if (!window.confirm('Delete this reel and all its media?')) return
    await api.del(`/api/projects/${projectId}/reels/${id}`).catch((e) => setError(e.message))
    if (id === reelId) { setReelId(null); setStep(2) }
    await refreshProject()
  }

  const canEnter = (i) => {
    if (!data) return i === 0
    if (i < REEL_STEP_START) return true
    if (!reelId) return false
    if (i === 3) return true                       // Script (offers generate)
    if (i === 4) return !!reelData?.script         // Media
    if (i === 5) return !!reelData?.voice && !!reelData?.media // Effects
    if (i === 6) return !!reelData?.voice && !!reelData?.media // Render
    if (i === 7) return !!(reelData?.renders?.results?.length) // Review
    return false
  }

  if (!projectId) {
    return (
      <Home
        projects={projects}
        error={error}
        onOpen={(id) => { setProjectId(id); setStep(1) }}
        onCreate={(project) => { setProjectId(project.id); setStep(1); loadProjects() }}
        onDelete={async (id) => {
          if (!window.confirm('Delete this project and all its reels?')) return
          await api.del(`/api/projects/${id}`).catch((e) => setError(e.message))
          loadProjects()
        }}
      />
    )
  }

  // Props shared with every step.
  const shared = {
    projectId, data, refreshProject,
    reelId, reelData, refreshReel, selectReel, setReelId,
    setStep,
  }

  return (
    <div className="layout">
      <div className="sidebar">
        <h1>Reel <span>Studio</span> v2</h1>
        <button className="home-link" onClick={() => { setProjectId(null); loadProjects() }}>
          ← All projects
        </button>
        {data && <div className="project-name" title={data.project.name}>{data.project.name}</div>}
        <Stepper steps={STEPS} current={step} canEnter={canEnter} onSelect={setStep} />
        {data && (
          <ReelBar
            reels={data.reels || []}
            reelId={reelId}
            onSelect={selectReel}
            onNew={newReel}
            onDelete={deleteReel}
          />
        )}
      </div>
      <div className="main">
        <ErrorBox error={error} onRetry={() => { setError(''); refreshProject() }} />
        {!data && !error && <p className="muted"><span className="spinner" />Loading project…</p>}
        {data && (
          <>
            <CloneBar
              projectId={projectId}
              onCloned={async (reel) => { await refreshProject(); selectReel(reel.id) }}
            />
            {step === 0 && <SetupStep {...shared} mode="edit" />}
            {step === 1 && <ReferencesStep {...shared} />}
            {step === 2 && <TopicsStep {...shared} />}
            {step === 3 && <ScriptStep {...shared} />}
            {step === 4 && <MediaStep {...shared} />}
            {step === 5 && <EffectsStep {...shared} />}
            {step === 6 && <RenderStep {...shared} />}
            {step === 7 && <ReviewStep {...shared} />}
          </>
        )}
      </div>
    </div>
  )
}

function Home({ projects, error, onOpen, onCreate, onDelete }) {
  const [creating, setCreating] = useState(false)
  return (
    <div className="layout">
      <div className="main" style={{ margin: '0 auto' }}>
        <h2>Reel Studio v2</h2>
        <p className="subtitle">AI short-form video pipeline — pick a project or start a new one.</p>
        <ErrorBox error={error} />
        {creating ? (
          <SetupStep mode="create" onCreated={onCreate} onCancel={() => setCreating(false)} />
        ) : (
          <>
            <button className="btn" onClick={() => setCreating(true)}>+ New project</button>
            <div className="spacer" />
            {projects === null && <p className="muted"><span className="spinner" />Loading…</p>}
            {projects?.length === 0 && <p className="muted">No projects yet.</p>}
            {projects?.map((p) => (
              <div key={p.id} className="project-tile" onClick={() => onOpen(p.id)}>
                <div>
                  <strong>{p.name}</strong>
                  <div className="muted">{p.niche.topic} · {p.format.replace('_', ' ')}</div>
                </div>
                <button
                  className="btn small danger"
                  onClick={(e) => { e.stopPropagation(); onDelete(p.id) }}
                >
                  Delete
                </button>
              </div>
            ))}
          </>
        )}
      </div>
    </div>
  )
}
