import React, { useEffect, useCallback } from 'react'
import { createFileRoute, useNavigate } from '@tanstack/react-router'
import { SubBar } from '../shell/SubBar'
import { Sub } from '../primitives'
import { ProjectsTable } from '../features/projects/ProjectsTable'
import { useProjects } from '../features/projects/useProjects'
import { useProjectsCursor } from '../features/projects/useProjectsCursor'
import { useKeyboardCursor } from './__root'
import { AuthError, APIError } from '../api/client'
import type { ProjectFilters } from '../features/projects/useProjects'
import type { Project } from '../api/adapters'
import '../styles/projects.css'

type ProjectsSearch = {
  since?: '7d' | '30d' | '90d' | 'all'
}

const VALID_SINCE = new Set<string>(['7d', '30d', '90d', 'all'])

export const Route = createFileRoute('/projects')({
  validateSearch: (search: Record<string, unknown>): ProjectsSearch => {
    const since =
      typeof search['since'] === 'string' && VALID_SINCE.has(search['since'])
        ? (search['since'] as ProjectsSearch['since'])
        : undefined
    return { since }
  },
  component: ProjectsRoute,
})

function SinceButtonGroup({
  value,
  onChange,
}: {
  value: string
  onChange: (v: ProjectsSearch['since']) => void
}): React.JSX.Element {
  const options = ['7d', '30d', '90d', 'all'] as const
  return (
    <div className="since-btn-group">
      {options.map(o => (
        <button
          key={o}
          className={'since-btn' + (value === o ? ' active' : '')}
          onClick={() => onChange(o)}
          type="button"
        >
          {o}
        </button>
      ))}
    </div>
  )
}

function ProjectsRoute(): React.JSX.Element {
  const navigate = useNavigate()
  const search = Route.useSearch()

  const since = search.since ?? '30d'

  const filters: ProjectFilters = { since }

  const { data: projects, isLoading, error } = useProjects(filters)

  const handleOpen = useCallback(
    (p: Project) => {
      // Route /project/$ is added in Phase 4; cast needed until routeTree is regenerated.
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      void (navigate as any)({ to: '/project/$', params: { _splat: encodeURIComponent(p.cwd) } })
    },
    [navigate],
  )

  const { cursor, move, activate, jumpTo } = useProjectsCursor(
    projects?.length ?? 0,
    useCallback(
      (idx: number) => {
        if (projects && projects[idx]) handleOpen(projects[idx])
      },
      [projects, handleOpen],
    ),
  )

  const cursorRef = useKeyboardCursor()
  useEffect(() => {
    cursorRef.current = { move, activate }
    return () => {
      cursorRef.current = {
        move: (_d: 1 | -1) => { /* no-op */ },
        activate: () => { /* no-op */ },
      }
    }
  }, [cursorRef, move, activate])

  function handleSinceChange(next: ProjectsSearch['since']) {
    void navigate({ to: '/projects', search: { since: next } })
  }

  const subBar = (
    <SubBar>
      <span className="mono muted">
        {projects != null ? `${projects.length} projects` : '…'} · ranked by recent activity
      </span>
      <span style={{ flex: 1 }} />
      <SinceButtonGroup value={since} onChange={handleSinceChange} />
    </SubBar>
  )

  if (isLoading) {
    return (
      <>
        {subBar}
        <div className="body body-pad">
          <Sub>loading…</Sub>
        </div>
      </>
    )
  }

  if (error != null) {
    if (error instanceof AuthError) {
      return (
        <div className="body body-pad" style={{ display: 'flex', justifyContent: 'center', paddingTop: 60 }}>
          <div className="card" style={{ padding: '24px 32px', textAlign: 'center' }}>
            <div className="uppercase-mono" style={{ marginBottom: 8 }}>not authenticated</div>
            <div className="muted">Sign in to view your projects.</div>
          </div>
        </div>
      )
    }
    const detail = error instanceof APIError ? error.message : String(error)
    return (
      <div className="body body-pad" style={{ display: 'flex', justifyContent: 'center', paddingTop: 60 }}>
        <div className="card" style={{ padding: '24px 32px', textAlign: 'center' }}>
          <div className="uppercase-mono" style={{ marginBottom: 8 }}>error</div>
          <div className="muted">{detail}</div>
        </div>
      </div>
    )
  }

  return (
    <>
      {subBar}
      <ProjectsTable
        projects={projects ?? []}
        cursor={cursor}
        onCursor={jumpTo}
        onOpen={handleOpen}
      />
    </>
  )
}
