import { Alert, Card, Descriptions, Space, Spin, Table, Tag, Typography } from 'antd'
import type { ColumnsType } from 'antd/es/table'
import { ApartmentOutlined } from '@ant-design/icons'
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'

import apiClient, { isEnvelope } from '../../api/client'
import PageHeader from '../../components/PageHeader'

const { Text } = Typography

interface HANode {
  id: string
  name: string
  fqdn: string
  api_url: string
  public_ip?: string | null
  internal_ip?: string | null
  mgmt_ip?: string | null
  role: string
  version?: string | null
  config_hash?: string | null
  status: 'online' | 'offline' | 'joining' | 'leaving' | 'unknown'
  last_seen?: string | null
  joined_at: string
}

interface ClusterStatus {
  local_id: string
  local_node?: HANode | null
  peers: HANode[]
  mode: 'single-node' | 'cluster'
  health: 'ok' | 'degraded' | 'split-brain'
  drift_found: boolean
  updated_at: string
}

function statusTag(s: HANode['status']) {
  switch (s) {
    case 'online':  return <Tag color="green">online</Tag>
    case 'offline': return <Tag color="red">offline</Tag>
    case 'joining': return <Tag color="blue">joining</Tag>
    case 'leaving': return <Tag color="orange">leaving</Tag>
    default:        return <Tag>unknown</Tag>
  }
}

function lastSeenRelative(iso?: string | null): string {
  if (!iso) return '—'
  const ms = Date.now() - new Date(iso).getTime()
  if (ms < 60_000) return `${Math.round(ms / 1000)}s`
  if (ms < 3_600_000) return `${Math.round(ms / 60_000)}m`
  return `${Math.round(ms / 3_600_000)}h`
}

export default function ClusterPage() {
  const { t } = useTranslation()

  const { data, isLoading } = useQuery({
    queryKey: ['cluster', 'status'],
    queryFn: async () => {
      const r = await apiClient.get('/cluster/status')
      return isEnvelope(r.data) ? (r.data.data as ClusterStatus) : null
    },
    refetchInterval: 30_000,
  })

  if (isLoading) return <Spin />
  if (!data) return null

  const peerColumns: ColumnsType<HANode> = [
    {
      title: t('cluster.col.node'), key: 'node',
      render: (_, r) => (
        <div>
          <div><Text strong>{r.fqdn}</Text></div>
          <div><Text type="secondary" style={{ fontFamily: 'monospace', fontSize: 11 }}>{r.id}</Text></div>
        </div>
      ),
    },
    {
      title: t('cluster.col.status'), dataIndex: 'status', width: 110,
      render: (s: HANode['status']) => statusTag(s),
    },
    { title: t('cluster.col.role'), dataIndex: 'role', width: 110,
      render: (v: string) => <Tag color={v === 'primary' ? 'gold' : 'default'}>{v}</Tag> },
    { title: t('cluster.col.apiUrl'), dataIndex: 'api_url', width: 240,
      render: (v: string) => <Text style={{ fontFamily: 'monospace', fontSize: 11 }}>{v}</Text> },
    {
      title: t('cluster.col.configHash'), dataIndex: 'config_hash', width: 160,
      render: (v: string | null | undefined) => {
        if (!v) return <Text type="secondary">—</Text>
        const localHash = data.local_node?.config_hash
        const drifts = localHash && v !== localHash
        return (
          <Space size={4}>
            <Text code style={{ fontSize: 11 }}>{v.slice(0, 12)}…</Text>
            {drifts && <Tag color="red">{t('cluster.drift')}</Tag>}
          </Space>
        )
      },
    },
    { title: t('cluster.col.version'), dataIndex: 'version', width: 100,
      render: (v?: string | null) => v ? <Tag>{v}</Tag> : <Text type="secondary">—</Text> },
    {
      title: t('cluster.col.lastSeen'), dataIndex: 'last_seen', width: 100,
      render: (v?: string | null) => (
        <Text type="secondary" style={{ fontSize: 12 }}>{lastSeenRelative(v)}</Text>
      ),
    },
  ]

  return (
    <div>
      <PageHeader
        icon={<ApartmentOutlined />}
        title={t('cluster.title')}
        subtitle={t('cluster.intro', { count: 1 + data.peers.length })}
        extra={
          <Space>
            <Tag color={data.mode === 'cluster' ? 'blue' : 'default'}>
              {data.mode === 'cluster' ? t('cluster.modeCluster') : t('cluster.modeSingle')}
            </Tag>
            <Tag color={data.health === 'ok' ? 'green' : data.health === 'degraded' ? 'orange' : 'red'}>
              {t(`cluster.health.${data.health}`)}
            </Tag>
          </Space>
        }
      />

      {data.drift_found && (
        <Alert
          type="warning"
          showIcon
          banner
          className="mb-16"
          message={t('cluster.driftBanner')}
          description={t('cluster.driftBannerDesc')}
        />
      )}

      {data.mode === 'single-node' && (
        <Alert
          type="info"
          showIcon
          className="mb-16"
          message={t('cluster.singleNodeTitle')}
          description={t('cluster.singleNodeDesc')}
        />
      )}

      <Card size="small" title={t('cluster.selfTitle')} className="mb-16">
        {data.local_node ? (
          <Descriptions size="small" column={2} bordered>
            <Descriptions.Item label={t('cluster.col.node')} span={2}>
              <Space direction="vertical" size={2}>
                <Text strong>{data.local_node.fqdn}</Text>
                <Text type="secondary" style={{ fontFamily: 'monospace', fontSize: 11 }}>
                  {data.local_node.id}
                </Text>
              </Space>
            </Descriptions.Item>
            <Descriptions.Item label={t('cluster.col.status')}>
              {statusTag(data.local_node.status)}
            </Descriptions.Item>
            <Descriptions.Item label={t('cluster.col.role')}>
              <Tag color={data.local_node.role === 'primary' ? 'gold' : 'default'}>
                {data.local_node.role}
              </Tag>
            </Descriptions.Item>
            <Descriptions.Item label={t('cluster.col.version')}>
              {data.local_node.version ? <Tag>{data.local_node.version}</Tag> : '—'}
            </Descriptions.Item>
            <Descriptions.Item label={t('cluster.col.mgmtIp')}>
              <Text style={{ fontFamily: 'monospace' }}>
                {data.local_node.mgmt_ip || '—'}
              </Text>
            </Descriptions.Item>
            <Descriptions.Item label={t('cluster.col.apiUrl')} span={2}>
              <Text style={{ fontFamily: 'monospace', fontSize: 12 }}>
                {data.local_node.api_url}
              </Text>
            </Descriptions.Item>
            <Descriptions.Item label={t('cluster.col.configHash')} span={2}>
              <Text code>{data.local_node.config_hash || '—'}</Text>
            </Descriptions.Item>
          </Descriptions>
        ) : (
          <Text type="secondary">{t('cluster.noSelf')}</Text>
        )}
      </Card>

      {data.peers.length > 0 && (
        <Card size="small" title={t('cluster.peersTitle', { count: data.peers.length })}>
          <Table
            size="small"
            rowKey="id"
            dataSource={data.peers}
            columns={peerColumns}
            pagination={false}
          />
        </Card>
      )}
    </div>
  )
}
