import { useCallback, useEffect, useState } from 'react'
import { ApiError, getOrgs, logout, type Org } from './api/client'
import ContactsPage from './components/ContactsPage'
import Dashboard from './components/Dashboard'
import LoginPage from './components/LoginPage'
import OrgDetail from './components/OrgDetail'
import OrgList from './components/OrgList'
import OrgOverview from './components/OrgOverview'
import ProjectsPage from './components/ProjectsPage'
import RightsDashboard from './components/RightsDashboard'
import SeedUpload from './components/SeedUpload'
import SharedFiles from './components/SharedFiles'
import Sidebar from './components/Sidebar'
import SystemPage from './components/SystemPage'
import { CodeProvider } from './codes/CodeProvider'
import { useCollapsiblePanel } from './hooks/useCollapsiblePanel'

// 화면 4개: Dashboard(전체 기관 현황 - 좌측 기관 목록 없이 전폭으로 쓴다),
// 기관관리(시안 레이아웃의 기관 상세), 채널관리(명부 시드 + 담당자 배정 + 채널 생성),
// 담당자관리(담당자 3종 CRUD - 담당자 정보가 입력되는 유일한 화면).
type Page = 'dashboard' | 'orgs' | 'channels' | 'contacts' | 'projects' | 'rights-check' | 'rights-process' | 'files' | 'system'

const PAGE_TITLE: Record<Page, string> = {
  dashboard: 'Dashboard',
  orgs: '기관관리',
  channels: '채널관리',
  contacts: '담당자관리',
  projects: '사업관리',
  'rights-check': '권리확인',
  'rights-process': '권리처리',
  files: '자료실',
  system: '시스템관리',
}

// 'checking'이 필요하다. true로 시작하면 첫 렌더에서 getOrgs()가 아직 안 끝났는데도
// 로그인한 것처럼 빈 껍데기를 먼저 보여주고, 401이 온 뒤에야 로그인 화면으로 튄다.
//
// 'error'는 401이 아닌 실패(서버 500, 네트워크 단절 등)를 위한 상태다. 이런 오류까지
// '로그아웃'으로 취급해 로그인 화면으로 보내면, 로그인해도 같은 오류가 반복되고
// 원인을 알 수 없게 된다 - 세션은 멀쩡한데 서버/네트워크만 문제인 경우이므로
// 오류 메시지와 재시도 버튼을 보여주는 편이 맞다.
type AuthState = 'checking' | 'authenticated' | 'anonymous' | 'error'

export default function App() {
  const [orgs, setOrgs] = useState<Org[]>([])
  const [selectedId, setSelectedId] = useState<number | null>(null)
  const [auth, setAuth] = useState<AuthState>('checking')
  const [authErrorMessage, setAuthErrorMessage] = useState<string | null>(null)
  const [page, setPage] = useState<Page>('dashboard')
  const [orgInitialTab, setOrgInitialTab] = useState<'권리확인' | '권리처리' | undefined>()
  // 창이 좁아지면 자동으로 접힌다. 사용자의 접기/펼치기 선택은 저장된다.
  const [menuCollapsed, toggleMenu] = useCollapsiblePanel('itnhub.menu', '(max-width: 1023px)')
  const [listCollapsed, toggleList] = useCollapsiblePanel('itnhub.orglist', '(max-width: 1279px)')

  const reload = useCallback(async () => {
    try {
      setOrgs(await getOrgs())
      setAuth('authenticated')
    } catch (e) {
      if (e instanceof ApiError && e.status === 401) {
        setAuth('anonymous')
      } else {
        setAuthErrorMessage((e as Error).message)
        setAuth('error')
      }
    }
  }, [])

  useEffect(() => {
    void reload()
  }, [reload])

  if (auth === 'checking') {
    return <div className="p-8 text-sm text-gray-500">불러오는 중…</div>
  }

  if (auth === 'anonymous') {
    return <LoginPage onSuccess={() => void reload()} />
  }

  if (auth === 'error') {
    return (
      <div className="flex min-h-screen flex-col items-center justify-center gap-3 p-8 text-sm">
        <p className="text-red-600">{authErrorMessage}</p>
        <button
          type="button"
          onClick={() => void reload()}
          className="rounded-md border border-gray-300 px-3 py-1.5 text-sm"
        >
          다시 시도
        </button>
      </div>
    )
  }

  const selected = orgs.find((org) => org.id === selectedId) ?? null

  async function handleLogout() {
    try {
      await logout()
    } finally {
      // 서버 응답과 무관하게 화면은 로그인으로 돌린다. 세션이 이미 만료된 경우에도
      // 사용자를 붙잡아 둘 이유가 없다.
      setOrgs([])
      setSelectedId(null)
      setAuth('anonymous')
    }
  }

  // 화면 선택지(진행단계·처리결과·공공누리유형 등)는 서버에서 한 번 받아 앱 전체가 나눠 쓴다.
  // 로그인 화면에는 필요 없으므로 인증을 통과한 다음부터 감싼다.
  return (
    <CodeProvider>
    <div className="flex h-screen">
      <Sidebar
        activeKey={page}
        collapsed={menuCollapsed}
        onToggle={toggleMenu}
        onSelect={(key) => {
          if (
            key === 'dashboard' ||
            key === 'orgs' ||
            key === 'channels' ||
            key === 'contacts' ||
            key === 'projects' ||
            key === 'rights-check' ||
            key === 'rights-process' ||
            key === 'files' ||
            key === 'system'
          ) {
            if (key === 'orgs') setOrgInitialTab(undefined)
            setPage(key)
          }
        }}
      />

      <div className="flex min-w-0 flex-1 flex-col">
        <header className="flex h-12 shrink-0 items-center justify-between border-b border-gray-200 px-6">
          <span className="text-sm font-medium">{PAGE_TITLE[page]}</span>
          <div className="flex items-center gap-3">
            <span className="text-sm text-gray-500">관리자</span>
            <button
              type="button"
              onClick={() => void handleLogout()}
              className="rounded-md border border-gray-300 px-2.5 py-1 text-xs text-gray-600 hover:bg-gray-50"
            >
              로그아웃
            </button>
          </div>
        </header>

        <div className="flex min-h-0 flex-1">
          {page !== 'contacts' && page !== 'dashboard' && page !== 'system'
            && page !== 'projects' && page !== 'rights-check' && page !== 'rights-process' && page !== 'files' && (
            <div
              className={`flex shrink-0 flex-col border-r border-gray-200 transition-all duration-200 ${
                listCollapsed ? 'w-14' : 'w-80'
              }`}
            >
              <OrgList
                orgs={orgs}
                selectedId={selectedId}
                onSelect={setSelectedId}
                collapsed={listCollapsed}
                onToggle={toggleList}
              />
              {page === 'channels' && !listCollapsed && (
                <SeedUpload onUploaded={() => void reload()} />
              )}
            </div>
          )}

          <main className="min-w-0 flex-1 overflow-y-auto bg-gray-50/50">
            {page === 'dashboard' ? (
              <Dashboard
                onOpenOrg={(orgId) => {
                  setSelectedId(orgId)
                  setOrgInitialTab(undefined)
                  setPage('orgs')
                }}
                // 요청자 요구: 대시보드 하단에서 전체를 볼 때는 사업관리로 넘어간다
                onOpenOrgList={() => setPage('projects')}
              />
            ) : page === 'projects' ? (
              <ProjectsPage
                onOpenOrg={(orgId) => {
                  setSelectedId(orgId)
                  setOrgInitialTab(undefined)
                  setPage('orgs')
                }}
              />
            ) : page === 'rights-check' || page === 'rights-process' ? (
              <RightsDashboard
                mode={page === 'rights-check' ? 'review' : 'process'}
                onOpenOrg={(orgId) => {
                  setSelectedId(orgId)
                  setOrgInitialTab(page === 'rights-check' ? '권리확인' : '권리처리')
                  setPage('orgs')
                }}
              />
            ) : page === 'files' ? (
              <SharedFiles />
            ) : page === 'system' ? (
              <SystemPage onChanged={() => void reload()} />
            ) : page === 'contacts' ? (
              <ContactsPage />
            ) : selected ? (
              page === 'channels' ? (
                <OrgDetail org={selected} onChanged={() => void reload()} />
              ) : (
                <OrgOverview org={selected} onChanged={() => void reload()} initialTab={orgInitialTab} />
              )
            ) : (
              <p className="p-8 text-sm text-gray-500">왼쪽에서 기관을 선택하세요.</p>
            )}
          </main>
        </div>
      </div>
    </div>
    </CodeProvider>
  )
}
