import { useState, useMemo, useCallback } from 'react'
import { useParams, useNavigate, useSearchParams } from 'react-router'
import { AlertTriangle, X, Search } from 'lucide-react'
import {
  DataTable,
  StatusDot,
  MonoText,
  Badge,
  useGlobalFilters,
} from '@cameleer/design-system'
import type { Column } from '@cameleer/design-system'
import {
  useSearchExecutions,
} from '../../api/queries/executions'
import type { ExecutionSummary } from '../../api/types'
import { attributeBadgeColor } from '../../utils/attribute-color'
import styles from './Dashboard.module.css'

// Row type extends ExecutionSummary with an `id` field for DataTable
interface Row extends ExecutionSummary {
  id: string
}

// ─── Helpers ─────────────────────────────────────────────────────────────────

function formatDuration(ms: number): string {
  if (ms >= 60_000) return `${(ms / 1000).toFixed(0)}s`
  if (ms >= 1000) return `${(ms / 1000).toFixed(2)}s`
  return `${ms}ms`
}

function formatTimestamp(iso: string): string {
  const date = new Date(iso)
  const y = date.getFullYear()
  const mo = String(date.getMonth() + 1).padStart(2, '0')
  const d = String(date.getDate()).padStart(2, '0')
  const h = String(date.getHours()).padStart(2, '0')
  const mi = String(date.getMinutes()).padStart(2, '0')
  const s = String(date.getSeconds()).padStart(2, '0')
  return `${y}-${mo}-${d} ${h}:${mi}:${s}`
}

function statusToVariant(status: string): 'success' | 'error' | 'running' | 'warning' {
  switch (status) {
    case 'COMPLETED': return 'success'
    case 'FAILED': return 'error'
    case 'RUNNING': return 'running'
    default: return 'warning'
  }
}

function statusLabel(status: string): string {
  switch (status) {
    case 'COMPLETED': return 'OK'
    case 'FAILED': return 'ERR'
    case 'RUNNING': return 'RUN'
    default: return 'WARN'
  }
}

function durationClass(ms: number, status: string): string {
  if (status === 'FAILED') return styles.durBreach
  if (ms < 100) return styles.durFast
  if (ms < 200) return styles.durNormal
  if (ms < 300) return styles.durSlow
  return styles.durBreach
}

// ─── Table columns (base, without inspect action) ────────────────────────────

function buildBaseColumns(): Column<Row>[] {
  return [
    {
      key: 'status',
      header: 'Status',
      width: '80px',
      render: (_: unknown, row: Row) => (
        <span className={styles.statusCell}>
          <StatusDot variant={statusToVariant(row.status)} />
          <MonoText size="xs">{statusLabel(row.status)}</MonoText>
        </span>
      ),
    },
    {
      key: 'routeId',
      header: 'Route',
      sortable: true,
      render: (_: unknown, row: Row) => (
        <span className={styles.routeName}>{row.routeId}</span>
      ),
    },
    {
      key: 'applicationName',
      header: 'Application',
      sortable: true,
      render: (_: unknown, row: Row) => (
        <span className={styles.appName}>{row.applicationName ?? ''}</span>
      ),
    },
    {
      key: 'attributes',
      header: 'Attributes',
      render: (_, row) => {
        const attrs = row.attributes;
        if (!attrs || Object.keys(attrs).length === 0) return <span className={styles.muted}>—</span>;
        const entries = Object.entries(attrs);
        const shown = entries.slice(0, 2);
        const overflow = entries.length - 2;
        return (
          <div className={styles.attrCell}>
            {shown.map(([k, v]) => (
              <span key={k} title={k}>
                <Badge label={String(v)} color={attributeBadgeColor(String(v))} />
              </span>
            ))}
            {overflow > 0 && <span className={styles.attrOverflow}>+{overflow}</span>}
          </div>
        );
      },
    },
    {
      key: 'executionId',
      header: 'Exchange ID',
      sortable: true,
      render: (_: unknown, row: Row) => (
        <MonoText size="xs">{row.executionId}</MonoText>
      ),
    },
    {
      key: 'startTime',
      header: 'Started',
      sortable: true,
      render: (_: unknown, row: Row) => (
        <MonoText size="xs">{formatTimestamp(row.startTime)}</MonoText>
      ),
    },
    {
      key: 'durationMs',
      header: 'Duration',
      sortable: true,
      render: (_: unknown, row: Row) => (
        <MonoText size="sm" className={durationClass(row.durationMs, row.status)}>
          {formatDuration(row.durationMs)}
        </MonoText>
      ),
    },
    {
      key: 'agentId',
      header: 'Agent',
      render: (_: unknown, row: Row) => (
        <span className={styles.agentBadge}>
          <span className={styles.agentDot} />
          {row.agentId}
        </span>
      ),
    },
  ]
}

// ─── Dashboard component ─────────────────────────────────────────────────────

export interface SelectedExchange {
  executionId: string;
  applicationName: string;
  routeId: string;
}

interface DashboardProps {
  onExchangeSelect?: (exchange: SelectedExchange) => void;
}

export default function Dashboard({ onExchangeSelect }: DashboardProps = {}) {
  const { appId, routeId } = useParams<{ appId: string; routeId: string }>()
  const navigate = useNavigate()
  const [searchParams, setSearchParams] = useSearchParams()
  const textFilter = searchParams.get('text') || undefined
  const [selectedId, setSelectedId] = useState<string | undefined>()
  const [sortField, setSortField] = useState<string>('startTime')
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')

  const { timeRange, statusFilters } = useGlobalFilters()
  const timeFrom = timeRange.start.toISOString()
  const timeTo = timeRange.end.toISOString()
  const handleSortChange = useCallback((key: string, dir: 'asc' | 'desc') => {
    setSortField(key)
    setSortDir(dir)
  }, [])

  // ─── API hooks ───────────────────────────────────────────────────────────
  // Convert design-system status filters (lowercase) to API status param (uppercase)
  const statusParam = statusFilters.size > 0
    ? [...statusFilters].map(s => s.toUpperCase()).join(',')
    : undefined

  const { data: searchResult } = useSearchExecutions(
    {
      timeFrom,
      timeTo,
      routeId: routeId || undefined,
      application: appId || undefined,
      status: statusParam,
      text: textFilter,
      sortField,
      sortDir,
      offset: 0,
      limit: textFilter ? 200 : 50,
    },
    !textFilter,
  )

  // ─── Rows ────────────────────────────────────────────────────────────────
  const rows: Row[] = useMemo(
    () => (searchResult?.data || []).map((e: ExecutionSummary) => ({ ...e, id: e.executionId })),
    [searchResult],
  )

  // ─── Table columns ──────────────────────────────────────────────────────
  const columns: Column<Row>[] = useMemo(() => buildBaseColumns(), [])

  // ─── Row click → navigate to diagram view ────────────────────────────────

  function handleRowClick(row: Row) {
    setSelectedId(row.id)
    if (onExchangeSelect) {
      onExchangeSelect({
        executionId: row.executionId,
        applicationName: row.applicationName ?? '',
        routeId: row.routeId,
      })
    }
  }

  function handleRowAccent(row: Row): 'error' | 'warning' | undefined {
    if (row.status === 'FAILED') return 'error'
    return undefined
  }

  return (
    <div className={styles.content}>
      <div className={styles.tableHeader}>
        <span className={styles.tableTitle}>
          {textFilter ? (
            <>
              <Search size={14} style={{ marginRight: 4, verticalAlign: -2 }} />
              Search: &ldquo;{textFilter}&rdquo;
              <button
                className={styles.clearSearch}
                onClick={() => setSearchParams({})}
                title="Clear search"
              >
                <X size={12} />
              </button>
            </>
          ) : 'Recent Exchanges'}
        </span>
        <div className={styles.tableRight}>
          <span className={styles.tableMeta}>
            {rows.length.toLocaleString()} of {(searchResult?.total ?? 0).toLocaleString()} exchanges
          </span>
          {!textFilter && <Badge label="LIVE" color="success" />}
        </div>
      </div>

      <DataTable
        columns={columns}
        data={rows}
        onRowClick={handleRowClick}
        selectedId={selectedId}
        sortable
        flush
        fillHeight
        onSortChange={handleSortChange}
        rowAccent={handleRowAccent}
        expandedContent={(row: Row) =>
          row.errorMessage ? (
            <div className={styles.inlineError}>
              <span className={styles.inlineErrorIcon}><AlertTriangle size={14} /></span>
              <div>
                <div className={styles.inlineErrorText}>{row.errorMessage}</div>
                <div className={styles.inlineErrorHint}>Click to view full stack trace</div>
              </div>
            </div>
          ) : null
        }
      />
    </div>
  )
}
