import { render as renderApp } from 'hono/jsx/dom'
import { define, Styles } from 'forge'
import type { App, AppState } from '../shared/types'
import { theme } from './themes'

// UI state (survives re-renders)
let selectedApp: string | null = localStorage.getItem('selectedApp')
let sidebarCollapsed: boolean = localStorage.getItem('sidebarCollapsed') === 'true'

// Server state (from SSE)
let apps: App[] = []

// Layout
const Layout = define('Layout', {
  display: 'flex',
  height: '100vh',
  fontFamily: theme('fonts-sans'),
  background: theme('colors-bg'),
  color: theme('colors-text'),
})

const Sidebar = define('Sidebar', {
  width: 220,
  borderRight: `1px solid ${theme('colors-border')}`,
  display: 'flex',
  flexDirection: 'column',
  flexShrink: 0,
})

const Logo = define('Logo', {
  height: 64,
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-between',
  padding: '0 16px',
  fontSize: 20,
  fontWeight: 'bold',
  borderBottom: `1px solid ${theme('colors-border')}`,
})

const HamburgerButton = define('HamburgerButton', {
  base: 'button',
  background: 'none',
  border: 'none',
  cursor: 'pointer',
  padding: 4,
  display: 'flex',
  flexDirection: 'column',
  justifyContent: 'center',
  gap: 4,
  selectors: {
    '&:hover span': { background: theme('colors-text') },
  },
})

const HamburgerLine = define('HamburgerLine', {
  width: 18,
  height: 2,
  background: theme('colors-textMuted'),
  borderRadius: 1,
  transition: 'background 0.15s',
})

const SectionLabel = define('SectionLabel', {
  padding: '16px 16px 8px',
  fontSize: 12,
  fontWeight: 600,
  color: theme('colors-textFaint'),
  textTransform: 'uppercase',
  letterSpacing: '0.05em',
})

const AppList = define('AppList', {
  flex: 1,
  overflow: 'auto',
})

const AppItem = define('AppItem', {
  display: 'flex',
  flexDirection: 'row',
  alignItems: 'center',
  gap: 8,
  padding: '8px 16px',
  color: theme('colors-textMuted'),
  textDecoration: 'none',
  fontSize: 14,
  cursor: 'pointer',
  selectors: {
    '&:hover': { background: theme('colors-bgHover'), color: theme('colors-text') },
  },
  variants: {
    selected: { background: theme('colors-bgSelected'), color: theme('colors-text'), fontWeight: 500 },
  },
})

const StatusDot = define('StatusDot', {
  width: 8,
  height: 8,
  borderRadius: '50%',
  flexShrink: 0,
  variants: {
    state: {
      invalid: { background: theme('colors-statusInvalid') },
      stopped: { background: theme('colors-statusStopped') },
      starting: { background: theme('colors-statusStarting') },
      running: { background: theme('colors-statusRunning') },
      stopping: { background: theme('colors-statusStarting') },
    },
    inline: {
      display: 'inline'
    }
  },
})

const SidebarFooter = define('SidebarFooter', {
  padding: 16,
  borderTop: `1px solid ${theme('colors-border')}`,
})

const NewAppButton = define('NewAppButton', {
  display: 'block',
  padding: '8px 12px',
  background: theme('colors-bgElement'),
  border: `1px solid ${theme('colors-border')}`,
  borderRadius: theme('radius-md'),
  color: theme('colors-textMuted'),
  textDecoration: 'none',
  fontSize: 14,
  textAlign: 'center',
  cursor: 'pointer',
  selectors: {
    '&:hover': { background: theme('colors-bgHover'), color: theme('colors-text') },
  },
})

// Main pane
const Main = define('Main', {
  flex: 1,
  display: 'flex',
  flexDirection: 'column',
  overflow: 'hidden',
})

const MainHeader = define('MainHeader', {
  height: 64,
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-between',
  padding: '0 24px',
  borderBottom: `1px solid ${theme('colors-border')}`,
})

const MainTitle = define('MainTitle', {
  display: 'flex',
  alignItems: 'center',
  gap: 8,
  fontSize: 20,
  fontWeight: 600,
  margin: 0,
})

const HeaderActions = define('HeaderActions', {
  display: 'flex',
  gap: 8,
})

const MainContent = define('MainContent', {
  flex: 1,
  padding: '10px 24px',
  overflow: 'auto',
})

const Section = define('Section', {
  marginBottom: 32,
})

const SectionTitle = define('SectionTitle', {
  fontSize: 12,
  fontWeight: 600,
  color: theme('colors-textFaint'),
  textTransform: 'uppercase',
  letterSpacing: '0.05em',
  marginBottom: 12,
  paddingBottom: 8,
  borderBottom: `1px solid ${theme('colors-border')}`,
})

const InfoRow = define('InfoRow', {
  display: 'flex',
  alignItems: 'center',
  gap: 12,
  marginBottom: 12,
  fontSize: 14,
})

const InfoLabel = define('InfoLabel', {
  color: theme('colors-textFaint'),
  width: 80,
  flexShrink: 0,
})

const InfoValue = define('InfoValue', {
  color: theme('colors-text'),
  display: 'flex',
  alignItems: 'center',
  gap: 8,
})

const Link = define('Link', {
  base: 'a',
  color: theme('colors-link'),
  textDecoration: 'none',
  selectors: {
    '&:hover': { textDecoration: 'underline' },
  },
})

const Button = define('Button', {
  base: 'button',
  padding: '6px 12px',
  background: theme('colors-bgElement'),
  border: `1px solid ${theme('colors-border')}`,
  borderRadius: theme('radius-md'),
  color: theme('colors-text'),
  fontSize: 13,
  cursor: 'pointer',
  selectors: {
    '&:hover': { background: theme('colors-bgHover') },
  },
  variants: {
    variant: {
      danger: { borderColor: theme('colors-dangerBorder'), color: theme('colors-dangerText') },
      primary: { background: theme('colors-primary'), borderColor: theme('colors-primary'), color: theme('colors-primaryText') },
    },
  },
})

const ActionBar = define('ActionBar', {
  display: 'flex',
  gap: 8,
  marginTop: 24,
  paddingTop: 24,
  borderTop: `1px solid ${theme('colors-border')}`,
})

const EmptyState = define('EmptyState', {
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  height: '100%',
  color: theme('colors-textFaint'),
  fontSize: 14,
})

const LogsContainer = define('LogsContainer', {
  background: theme('colors-bgSubtle'),
  borderRadius: theme('radius-md'),
  padding: 12,
  fontFamily: theme('fonts-mono'),
  fontSize: 12,
  color: theme('colors-textMuted'),
  maxHeight: 200,
  overflow: 'auto',
})

const LogLine = define('LogLine', {
  marginBottom: 4,
  selectors: {
    '&:last-child': { marginBottom: 0 },
  },
})

const LogTime = define('LogTime', {
  color: theme('colors-textFaintest'),
  marginRight: 12,
  display: 'inline',
})

let selectedTab: 'overview' | 'todo' = 'overview'

const TabContent = define('TabContent', {
  display: 'none',

  variants: {
    active: {
      display: 'block'
    }
  }
})

const NavButton = define('NavButton', {
  render({ props }) {
    return (
      <Button onClick={props.onClick} style={{ marginRight: 10, marginBottom: 20 }}>
        {props.children}
      </Button>
    )
  }
})

function setSelectedTab(tab: 'overview' | 'todo') {
  selectedTab = tab
  render()
}

const Nav = () => {
  return <>
    <NavButton onClick={() => setSelectedTab('overview')}>Overview</NavButton>
    <NavButton onClick={() => setSelectedTab('todo')}>TODO</NavButton>
  </>
}

const stateLabels: Record<AppState, string> = {
  invalid: 'Invalid',
  stopped: 'Stopped',
  starting: 'Starting',
  running: 'Running',
  stopping: 'Stopping',
}

// Actions - call API then let SSE update the state
const startApp = (name: string) => fetch(`/api/apps/${name}/start`, { method: 'POST' })
const stopApp = (name: string) => fetch(`/api/apps/${name}/stop`, { method: 'POST' })
const restartApp = (name: string) => fetch(`/api/apps/${name}/restart`, { method: 'POST' })

const selectApp = (name: string) => {
  selectedApp = name
  localStorage.setItem('selectedApp', name)
  render()
}

const toggleSidebar = () => {
  sidebarCollapsed = !sidebarCollapsed
  localStorage.setItem('sidebarCollapsed', String(sidebarCollapsed))
  render()
}

const AppDetail = ({ app }: { app: App }) => (
  <>
    <MainHeader>
      <MainTitle>
        {app.icon ?? <StatusDot state={app.state} />}
        &nbsp;
        {app.name}
      </MainTitle>
      <HeaderActions>
        <Button>Settings</Button>
        <Button variant="danger">Delete</Button>
      </HeaderActions>
    </MainHeader>
    <MainContent>
      <Nav />

      <TabContent active={selectedTab === 'overview'}>
        <Section>
          <SectionTitle>Status</SectionTitle>
          <InfoRow>
            <InfoLabel>State</InfoLabel>
            <InfoValue>
              <StatusDot state={app.state} />
              {stateLabels[app.state]}
              {app.port ? ` on :${app.port}` : ''}
            </InfoValue>
          </InfoRow>
          {app.state === 'running' && app.port && (
            <InfoRow>
              <InfoLabel>URL</InfoLabel>
              <InfoValue>
                <Link href={`http://localhost:${app.port}`} target="_blank">
                  http://localhost:{app.port}
                </Link>
              </InfoValue>
            </InfoRow>
          )}
          {app.started && (
            <InfoRow>
              <InfoLabel>Started</InfoLabel>
              <InfoValue>{new Date(app.started).toLocaleString()}</InfoValue>
            </InfoRow>
          )}
          {app.error && (
            <InfoRow>
              <InfoLabel>Error</InfoLabel>
              <InfoValue style={{ color: theme('colors-error') }}>
                {app.error}
              </InfoValue>
            </InfoRow>
          )}
        </Section>

        <Section>
          <SectionTitle>Logs</SectionTitle>
          <LogsContainer>
            {app.logs?.length ? (
              app.logs.map((line, i) => (
                <LogLine key={i}>
                  <LogTime>{new Date(line.time).toLocaleTimeString()}</LogTime>
                  <span>{line.text}</span>
                </LogLine>
              ))
            ) : (
              <LogLine>
                <LogTime>--:--:--</LogTime>
                <span style={{ color: theme('colors-textFaint') }}>No logs yet</span>
              </LogLine>
            )}
          </LogsContainer>
        </Section>

        <ActionBar>
          {app.state === 'stopped' && (
            <Button variant="primary" onClick={() => startApp(app.name)}>
              Start
            </Button>
          )}
          {app.state === 'running' && (
            <>
              <Button onClick={() => restartApp(app.name)}>Restart</Button>
              <Button variant="danger" onClick={() => stopApp(app.name)}>
                Stop
              </Button>
            </>
          )}
          {(app.state === 'starting' || app.state === 'stopping') && (
            <Button disabled>{stateLabels[app.state]}...</Button>
          )}
        </ActionBar>
      </TabContent>

      <TabContent active={selectedTab === 'todo'}>
        <h1>hardy har har</h1>
      </TabContent>
    </MainContent>
  </>
)

const Dashboard = () => {
  const selected = apps.find(a => a.name === selectedApp)

  return (
    <Layout>
      <Styles />
      <Sidebar style={sidebarCollapsed ? { width: 'auto' } : undefined}>
        <Logo>
          {!sidebarCollapsed && <span>🐾 Toes</span>}
          <HamburgerButton onClick={toggleSidebar} title={sidebarCollapsed ? 'Show sidebar' : 'Hide sidebar'}>
            <HamburgerLine />
            <HamburgerLine />
            <HamburgerLine />
          </HamburgerButton>
        </Logo>
        {!sidebarCollapsed && <SectionLabel>Apps</SectionLabel>}
        <AppList>
          {apps.map(app => (
            <AppItem
              key={app.name}
              onClick={() => selectApp(app.name)}
              selected={app.name === selectedApp ? true : undefined}
              style={sidebarCollapsed ? { justifyContent: 'center', padding: '10px 12px' } : undefined}
              title={sidebarCollapsed ? app.name : undefined}
            >
              {app.state === 'running' && app.icon ? (
                <span style={{ fontSize: sidebarCollapsed ? 18 : 14 }}>{app.icon}</span>
              ) : (
                <StatusDot state={app.state} />
              )}
              {!sidebarCollapsed && app.name}
            </AppItem>
          ))}
        </AppList>
        {!sidebarCollapsed && (
          <SidebarFooter>
            <NewAppButton>+ New App</NewAppButton>
          </SidebarFooter>
        )}
      </Sidebar>
      <Main>
        {selected ? (
          <AppDetail app={selected} />
        ) : (
          <EmptyState>Select an app to view details</EmptyState>
        )}
      </Main>
    </Layout>
  )
}

const render = () => {
  renderApp(<Dashboard />, document.getElementById('app')!)
}

// Set theme based on system preference
const setTheme = () => {
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
  document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light')
}

// Listen for system theme changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
  setTheme()
  render()
})

// Set initial theme
setTheme()

// SSE connection
const events = new EventSource('/api/apps/stream')
events.onmessage = e => {
  apps = JSON.parse(e.data)
  const valid = selectedApp && apps.some(a => a.name === selectedApp)
  if (!valid && apps.length) selectedApp = apps[0]!.name
  render()
}
