import React from 'react'
import { createFileRoute, useNavigate } from '@tanstack/react-router'
import { SubBar } from '../shell/SubBar'
import { Sub, EmptyState, Spark, ToolDot, StackedBars, Heatmap, HorizontalBars, HourBars } from '../primitives'
import { useStats } from '../features/stats/useStats'
import { AuthError, APIError } from '../api/client'
import '../styles/stats.css'

// ── Color palette ──────────────────────────────────────────────────────────────

const TOOL_COLORS: Record<string, string> = {
  'claude-code': '#c96442',
  opencode: '#3b6e3b',
  crush: '#7a4ea8',
  pi: '#b8902a',
  kimi: '#2a6e9c',
}

// Stable fallback palette for unknown tool names.
const FALLBACK_COLORS = [
  '#4e7a6b', '#7a4e6b', '#6b7a4e', '#4e6b7a', '#7a6b4e', '#6b4e7a', '#4e7a6b',
]

function toolColor(tool: string): string {
  if (TOOL_COLORS[tool]) return TOOL_COLORS[tool]
  // Simple hash mod palette for unknown tools.
  let hash = 0
  for (let i = 0; i < tool.length; i++) {
    hash = ((hash << 5) - hash + tool.charCodeAt(i)) | 0
  }
  return FALLBACK_COLORS[Math.abs(hash) % FALLBACK_COLORS.length]
}

// ── Route ──────────────────────────────────────────────────────────────────────

type StatsSearch = {
  range: '7d' | '30d' | '90d' | 'all'
}

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

export const Route = createFileRoute('/stats')({
  validateSearch: (search: Record<string, unknown>): StatsSearch => {
    const range =
      typeof search['range'] === 'string' && VALID_RANGE.has(search['range'])
        ? (search['range'] as StatsSearch['range'])
        : '30d'
    return { range }
  },
  component: StatsRoute,
})

// ── Range button group ─────────────────────────────────────────────────────────

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

// ── Main component ─────────────────────────────────────────────────────────────

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

  const { data: stats, isLoading, error } = useStats(range)

  function handleRangeChange(next: StatsSearch['range']) {
    void navigate({ to: '/stats', search: { range: next } })
  }

  const subBar = (
    <SubBar>
      <span className="mono muted">stats</span>
      <span style={{ flex: 1 }} />
      <RangeButtonGroup value={range} onChange={handleRangeChange} />
    </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 stats.</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>
    )
  }

  const s = stats!

  // ── Per-tool rollup card ────────────────────────────────────────────────────
  const perToolCard = (
    <div className="full">
      <div className="uppercase-mono" style={{ marginBottom: 6 }}>per tool · last {range}</div>
      <div className="card" style={{ padding: 0 }}>
        {s.perTool.length === 0 ? (
          <EmptyState glyph="∅" copy="no tool activity in this range" />
        ) : (
          s.perTool.map((r, i) => (
            <div
              key={r.tool}
              className="per-tool-row"
              style={{
                gridTemplateColumns: '140px 70px 70px 1fr 60px',
                background: i % 2 ? 'var(--paper-3)' : 'var(--paper-4)',
              }}
            >
              <span style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
                <ToolDot tool={r.tool} />
                <span className="mono">{r.tool}</span>
              </span>
              <span className="right mono">{r.turns.toLocaleString()} turns</span>
              <span className="right mono muted">
                {Math.round((r.tokensIn + r.tokensOut) / 1000)}k tok
              </span>
              <span style={{ paddingLeft: 12 }}>
                <Spark
                  points={r.dailySparkline.map(Number)}
                  w={100}
                  h={16}
                  accent={i === 0}
                />
              </span>
              <span className="right mono muted">{r.sessions} ses</span>
            </div>
          ))
        )}
      </div>
    </div>
  )

  // ── Daily stacked bars card ─────────────────────────────────────────────────
  // Project daily DailyBucket[] into { tools: Record<string, number> }[] for StackedBars.
  const dailyDays = s.daily.map(b => ({ tools: b.perTool }))
  const dailyCard = (
    <div className="card full">
      <div className="card-head">
        <span>turns/day · stacked by tool</span>
        <span style={{ flex: 1 }} />
        <span style={{ display: 'flex', gap: 10, fontSize: 10 }}>
          {s.perTool.slice(0, 4).map(r => (
            <span key={r.tool} style={{ display: 'flex', gap: 4, alignItems: 'center' }}>
              <span
                className="tooldot"
                style={{ background: toolColor(r.tool), width: 8, height: 8, borderRadius: '50%', display: 'inline-block' }}
              />
              {r.tool}
            </span>
          ))}
        </span>
      </div>
      <div className="card-body">
        {dailyDays.length === 0 ? (
          <EmptyState glyph="∅" copy="no daily activity in this range" />
        ) : (
          <>
            <StackedBars days={dailyDays} toolColor={toolColor} h={130} />
            <div
              className="flex"
              style={{ justifyContent: 'space-between', marginTop: 4, fontSize: 9.5 }}
            >
              <span className="mono muted">{dailyDays.length}d ago</span>
              <span className="mono muted">today</span>
            </div>
          </>
        )}
      </div>
    </div>
  )

  // ── Heatmap card ────────────────────────────────────────────────────────────
  const heatmapMax = Math.max(...s.heatmap.map(c => c.count), 1)
  const heatmapCard = (
    <div className="card">
      <div className="card-head">activity · 12 weeks</div>
      <div className="card-body">
        <Heatmap cells={s.heatmap} max={heatmapMax} />
        <div className="flex muted mono" style={{ marginTop: 6, fontSize: 9.5, gap: 4, alignItems: 'center' }}>
          <span>less</span>
          {[0.15, 0.35, 0.55, 0.8, 1].map(o => (
            <span
              key={o}
              style={{
                width: 10,
                height: 10,
                background: 'var(--accent)',
                opacity: o,
                borderRadius: 1,
                display: 'inline-block',
              }}
            />
          ))}
          <span>more</span>
        </div>
      </div>
    </div>
  )

  // ── Top cwd card ────────────────────────────────────────────────────────────
  const topCwdMax = s.topCwd.length > 0 ? Math.max(...s.topCwd.map(r => r.count)) : 1
  const topCwdRows = s.topCwd.map(r => ({
    label: r.cwd,
    count: r.count,
    href: `/project/${encodeURIComponent(r.cwd)}`,
  }))
  const topCwdCard = (
    <div className="card">
      <div className="card-head">top cwd</div>
      <div className="card-body">
        {s.topCwd.length === 0 ? (
          <EmptyState glyph="∅" copy="no cwd data in this range" />
        ) : (
          <HorizontalBars rows={topCwdRows} max={topCwdMax} />
        )}
      </div>
    </div>
  )

  // ── Hour-of-day card ────────────────────────────────────────────────────────
  const hourCard = (
    <div className="card">
      <div className="card-head">turns by hour</div>
      <div className="card-body">
        {s.hourOfDay.length === 0 ? (
          <EmptyState glyph="∅" copy="no hour data in this range" />
        ) : (
          <HourBars hours={s.hourOfDay} />
        )}
      </div>
    </div>
  )

  // ── Host split card ─────────────────────────────────────────────────────────
  const hostMax = s.hostSplit.length > 0 ? Math.max(...s.hostSplit.map(r => r.count)) : 1
  const hostRows = s.hostSplit.map(r => ({ label: r.host, count: r.count }))
  const hostCard = (
    <div className="card">
      <div className="card-head">by host</div>
      <div className="card-body">
        {s.hostSplit.length === 0 ? (
          <EmptyState glyph="∅" copy="no host data in this range" />
        ) : (
          <HorizontalBars rows={hostRows} max={hostMax} />
        )}
      </div>
    </div>
  )

  return (
    <>
      {subBar}
      <div className="body" style={{ overflow: 'auto' }}>
        <div className="stats-grid">
          {perToolCard}
          {dailyCard}
          {heatmapCard}
          {topCwdCard}
          {hourCard}
          {hostCard}
        </div>
      </div>
    </>
  )
}
