import {
  ControlOutlined,
  DatabaseOutlined,
  PlayCircleOutlined,
  ThunderboltOutlined,
  WifiOutlined,
} from '@ant-design/icons'
import {
  Breadcrumb,
  Button,
  Col,
  Descriptions,
  Form,
  Input,
  Modal,
  Row,
  Segmented,
  Select,
  Space,
  Spin,
  Table,
  Tag,
  Tooltip,
  Typography,
  message,
} from 'antd'
import { useQueryClient } from '@tanstack/react-query'
import { useEffect, useMemo, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { useDevices, useObject, type DeviceItem } from '../api/objects'
import { useRacks } from '../api/racks'
import { useActions, useCreateTask, useTask } from '../api/tasks'
import { CategoryTag, DeviceStatusBadge } from '../components/StatusBadge'
import dayjs from 'dayjs'

function PingButton({
  scope,
  objId,
  size = 'small',
  children,
}: {
  scope: object
  objId: number
  size?: 'small' | 'middle' | 'large'
  children?: React.ReactNode
}) {
  const [taskId, setTaskId] = useState<string | null>(null)
  const queryClient = useQueryClient()
  const createTask = useCreateTask()
  const { data: task } = useTask(taskId ?? undefined)

  useEffect(() => {
    if (task && ['success', 'failed', 'partial', 'stale', 'cancelled'].includes(task.status)) {
      queryClient.invalidateQueries({ queryKey: ['devices', objId] })
      setTaskId(null)
    }
  }, [task?.status, queryClient, objId])

  const handlePing = async () => {
    try {
      const t = await createTask.mutateAsync({ type: 'ping', target_scope: scope, params: {} })
      setTaskId(t.id)
    } catch {
      message.error('Ошибка запуска пинга')
    }
  }

  return (
    <Button
      size={size}
      loading={createTask.isPending || !!taskId}
      icon={<WifiOutlined />}
      onClick={handlePing}
    >
      {children}
    </Button>
  )
}

const SERVER_CATEGORIES = new Set(['main_server', 'vm', 'router'])
const COL_SPAN = 7

type GroupRow = { _type: 'group'; _key: string; label: string; count: number; onlineCount: number; rackScope?: object }
type DeviceRow = DeviceItem & { _type: 'device' }
type TableRow = GroupRow | DeviceRow

export function WorkObjectDetailPage() {
  const { id } = useParams<{ id: string }>()
  const objId = Number(id)
  const navigate = useNavigate()

  const { data: obj, isLoading: objLoading } = useObject(objId)
  const { data: devices, isLoading: devLoading } = useDevices(objId)
  const { data: racks } = useRacks(objId)
  const { data: actions } = useActions()
  const createTask = useCreateTask()

  const [taskModal, setTaskModal] = useState<{ scope: object; title: string } | null>(null)
  const [selectedAction, setSelectedAction] = useState<string>('')
  const [searchText, setSearchText] = useState('')
  const [form] = Form.useForm()

  const currentAction = actions?.find((a) => a.name === selectedAction)

  const openTaskModal = (scope: object, title: string) => {
    setTaskModal({ scope, title })
    setSelectedAction('')
    form.resetFields()
  }

  const submitTask = async () => {
    const values = await form.validateFields()
    const { action, ...params } = values
    try {
      const task = await createTask.mutateAsync({
        type: action,
        target_scope: taskModal!.scope,
        params,
      })
      message.success('Задача создана')
      setTaskModal(null)
      navigate(`/tasks/${task.id}`)
    } catch {
      message.error('Ошибка создания задачи')
    }
  }

  const filteredDevices = useMemo(() => {
    if (!searchText) return devices ?? []
    const q = searchText.toLowerCase()
    return (devices ?? []).filter(
      (d) => d.ip.toLowerCase().includes(q) || (d.hostname ?? '').toLowerCase().includes(q)
    )
  }, [devices, searchText])

  const groupedTableData = useMemo((): TableRow[] => {
    const servers = filteredDevices.filter((d) => SERVER_CATEGORIES.has(d.category))
    const rest = filteredDevices.filter((d) => !SERVER_CATEGORIES.has(d.category))

    const rackMap = new Map<string | null, { id: number | null; items: DeviceItem[] }>()
    for (const d of rest) {
      const key = d.rack_name ?? null
      if (!rackMap.has(key)) rackMap.set(key, { id: d.rack_id, items: [] })
      rackMap.get(key)!.items.push(d)
    }

    const rows: TableRow[] = []

    const addGroup = (label: string, key: string, items: DeviceItem[], rackScope?: object) => {
      rows.push({
        _type: 'group',
        _key: key,
        label,
        count: items.length,
        onlineCount: items.filter((d) => d.status === 'online').length,
        rackScope,
      })
      items.forEach((d) => rows.push({ ...d, _type: 'device' }))
    }

    if (servers.length > 0) {
      addGroup('Серверная инфраструктура', '__servers__', servers, {
        type: 'category',
        object_id: objId,
        category: 'main_server',
      })
    }

    // Sort racks by name
    const rackEntries = [...rackMap.entries()].filter(([k]) => k !== null) as [string, { id: number | null; items: DeviceItem[] }][]
    rackEntries.sort(([a], [b]) => a.localeCompare(b))

    for (const [rackName, { id: rackId, items }] of rackEntries) {
      addGroup(
        rackName,
        `rack:${rackName}`,
        items,
        rackId != null ? { type: 'device_list', ids: items.map((d) => d.id) } : undefined,
      )
    }

    const noRack = rackMap.get(null)?.items ?? []
    if (noRack.length > 0) addGroup('Без привязки', '__norack__', noRack)

    return rows
  }, [filteredDevices, objId])

  if (objLoading) return <Spin />

  const deviceColumns = [
    {
      title: 'IP',
      dataIndex: 'ip',
      key: 'ip',
      onCell: (row: TableRow) =>
        row._type === 'group'
          ? { colSpan: COL_SPAN, style: { background: '#f5f5f5', padding: '6px 16px', borderBottom: '1px solid #e8e8e8' } }
          : {},
      render: (_: unknown, row: TableRow) => {
        if (row._type === 'group') {
          return (
            <Space size={8}>
              <Typography.Text strong style={{ fontSize: 13 }}>{row.label}</Typography.Text>
              <Tag style={{ marginLeft: 2 }}>{row.count} устройств</Tag>
              {row.onlineCount > 0 && <Tag color="green">Online: {row.onlineCount}</Tag>}
              {row.rackScope && (
                <>
                  <PingButton scope={row.rackScope} objId={objId}>
                    Пинг
                  </PingButton>
                  <Button
                    size="small"
                    icon={<PlayCircleOutlined />}
                    onClick={() => openTaskModal(row.rackScope!, `Задача: ${row.label}`)}
                  >
                    Задача на группу
                  </Button>
                </>
              )}
            </Space>
          )
        }
        return <code>{(row as DeviceRow).ip}</code>
      },
    },
    {
      title: 'Hostname',
      dataIndex: 'hostname',
      key: 'hostname',
      onCell: (row: TableRow) => row._type === 'group' ? { colSpan: 0 } : {},
      render: (_: unknown, row: TableRow) =>
        row._type === 'group' ? null : ((row as DeviceRow).hostname ?? '—'),
    },
    {
      title: 'Категория',
      dataIndex: 'category',
      key: 'category',
      onCell: (row: TableRow) => row._type === 'group' ? { colSpan: 0 } : {},
      render: (_: unknown, row: TableRow) =>
        row._type === 'group' ? null : <CategoryTag category={(row as DeviceRow).category} />,
    },
    {
      title: 'Статус',
      dataIndex: 'status',
      key: 'status',
      onCell: (row: TableRow) => row._type === 'group' ? { colSpan: 0 } : {},
      render: (_: unknown, row: TableRow) =>
        row._type === 'group' ? null : <DeviceStatusBadge status={(row as DeviceRow).status} />,
    },
    {
      title: 'Последний ping',
      dataIndex: 'last_seen',
      key: 'last_seen',
      onCell: (row: TableRow) => row._type === 'group' ? { colSpan: 0 } : {},
      render: (_: unknown, row: TableRow) => {
        if (row._type === 'group') return null
        const d = row as DeviceRow
        return d.last_seen ? (
          <Tooltip title={dayjs(d.last_seen).format('DD.MM.YYYY HH:mm:ss')}>
            <span>{d.last_ping_ms}ms</span>
          </Tooltip>
        ) : '—'
      },
    },
    {
      title: '',
      key: 'actions',
      width: 110,
      onCell: (row: TableRow) => row._type === 'group' ? { colSpan: 0 } : {},
      render: (_: unknown, row: TableRow) => {
        if (row._type === 'group') return null
        const d = row as DeviceRow
        return (
          <Button
            size="small"
            icon={<PlayCircleOutlined />}
            onClick={() => openTaskModal({ type: 'device', id: d.id }, `Задача: ${d.hostname ?? d.ip}`)}
          >
            Задача
          </Button>
        )
      },
    },
  ]

  // Breadcrumb: Работа → [City →] Object
  const breadcrumbItems = [
    { title: <a onClick={() => navigate('/work/objects')}>Работа</a> },
    ...(obj?.city ? [{ title: <a onClick={() => navigate('/work/objects')}>{obj.city}</a> }] : []),
    { title: obj?.name },
  ]

  return (
    <div>
      <Row justify="space-between" align="middle" style={{ marginBottom: 16 }}>
        <Col><Breadcrumb items={breadcrumbItems} /></Col>
        <Col>
          {/* TODO (Вариант В): заменить Segmented на <Tabs> с вкладками Устройства / Задачи / Снапшоты */}
          <Segmented
            value="work"
            options={[
              { label: 'Инвентарь', value: 'inventory', icon: <DatabaseOutlined /> },
              { label: 'Работа',    value: 'work',      icon: <ControlOutlined /> },
            ]}
            onChange={(val) => { if (val === 'inventory') navigate(`/inventory/objects/${objId}`) }}
          />
        </Col>
      </Row>

      <Row gutter={16} style={{ marginBottom: 16 }}>
        <Col flex="auto">
          <Descriptions size="small" bordered column={3}>
            <Descriptions.Item label="Сервер">{obj?.server_ip ?? '—'}</Descriptions.Item>
            <Descriptions.Item label="Клиент">{obj?.client ?? '—'}</Descriptions.Item>
            <Descriptions.Item label="SSH">{obj?.ssh_user ?? '—'}</Descriptions.Item>
          </Descriptions>
        </Col>
        <Col>
          <Space>
            <PingButton scope={{ type: 'object', id: objId }} objId={objId} size="middle">
              Пинг объекта
            </PingButton>
            <Button
              icon={<ThunderboltOutlined />}
              onClick={() => openTaskModal({ type: 'object', id: objId }, 'Задача на весь объект')}
            >
              Задача на объект
            </Button>
            <Button
              onClick={() =>
                openTaskModal(
                  { type: 'category', object_id: objId, category: 'main_server' },
                  'Задача: все серверы'
                )
              }
            >
              Все серверы
            </Button>
            <Button
              onClick={() =>
                openTaskModal(
                  { type: 'category', object_id: objId, category: 'bank_terminal' },
                  'Задача: все терминалы'
                )
              }
            >
              Все терминалы
            </Button>
          </Space>
        </Col>
      </Row>

      <Input.Search
        placeholder="Поиск по IP или hostname..."
        allowClear
        style={{ marginBottom: 12, maxWidth: 360 }}
        onChange={(e) => setSearchText(e.target.value)}
      />

      <Table
        dataSource={groupedTableData}
        columns={deviceColumns}
        rowKey={(row) => (row._type === 'group' ? `group:${row._key}` : `dev:${(row as DeviceRow).id}`)}
        loading={devLoading}
        size="middle"
        pagination={false}
        showHeader={groupedTableData.some((r) => r._type === 'device')}
      />

      {/* Task Modal */}
      <Modal
        title={taskModal?.title ?? 'Создать задачу'}
        open={!!taskModal}
        onCancel={() => setTaskModal(null)}
        onOk={submitTask}
        confirmLoading={createTask.isPending}
        okText="Запустить"
      >
        <Form form={form} layout="vertical" style={{ marginTop: 16 }}>
          <Form.Item name="action" label="Действие" rules={[{ required: true }]}>
            <Select
              placeholder="Выберите действие"
              options={actions?.map((a) => ({ value: a.name, label: a.display_name }))}
              onChange={setSelectedAction}
            />
          </Form.Item>
          {currentAction?.params_schema.map((p) => (
            <Form.Item key={p.name} name={p.name} label={p.label} rules={p.required ? [{ required: true }] : []}>
              <Input />
            </Form.Item>
          ))}
        </Form>
      </Modal>
    </div>
  )
}
