import { useMemo } from 'react'
import ReactECharts from 'echarts-for-react'

import type { MachineTelemetryInterval } from '../../../../entities/machine/model/types'
import {
  analyticsStateMeta,
  formatAnalyticsDateTime,
  formatDetailedDuration,
} from './utils'

type MachineStateTimelineChartProps = {
  intervals: MachineTelemetryInterval[]
  machineName: string
}

type RectShape = {
  x: number
  y: number
  width: number
  height: number
}

type CustomRenderParams = {
  coordSys: RectShape
}

type CustomRenderApi = {
  value: (index: number) => number
  coord: (value: [number, number]) => [number, number]
  style: () => Record<string, unknown>
}

type TimelineSeriesItem = {
  value: [number, number, number]
  itemStyle: {
    color: string
  }
  meta: MachineTelemetryInterval
}

type TimelineTooltipParam = {
  data?: TimelineSeriesItem
}

const fontFamily = 'Montserrat Variable, Montserrat, sans-serif'
const fallbackTimelineStart = Date.UTC(2026, 6, 9, 0, 0, 0)

function clipRectByRect(shape: RectShape, rect: RectShape) {
  const x = Math.max(shape.x, rect.x)
  const y = Math.max(shape.y, rect.y)
  const x2 = Math.min(shape.x + shape.width, rect.x + rect.width)
  const y2 = Math.min(shape.y + shape.height, rect.y + rect.height)

  if (x2 < x || y2 < y) return null

  return {
    x,
    y,
    width: x2 - x,
    height: y2 - y,
  }
}

function renderTimelineItem(
  params: CustomRenderParams,
  api: CustomRenderApi,
) {
  const rowIndex = api.value(0)
  const start = api.coord([api.value(1), rowIndex])
  const end = api.coord([api.value(2), rowIndex])
  const height = 22
  const rectShape = clipRectByRect(
    {
      x: start[0],
      y: start[1] - height / 2,
      width: Math.max(1, end[0] - start[0]),
      height,
    },
    {
      x: params.coordSys.x,
      y: params.coordSys.y,
      width: params.coordSys.width,
      height: params.coordSys.height,
    },
  )

  if (!rectShape) return null

  return {
    type: 'rect',
    transition: ['shape', 'style'],
    shape: {
      ...rectShape,
      r: 999,
    },
    style: api.style(),
  }
}

function formatTimelineTick(value: number | string, rangeMs: number) {
  const date = new Date(Number(value))

  if (rangeMs > 2 * 24 * 60 * 60 * 1000) {
    return new Intl.DateTimeFormat('ru-RU', {
      day: '2-digit',
      month: '2-digit',
    }).format(date)
  }

  return new Intl.DateTimeFormat('ru-RU', {
    hour: '2-digit',
    minute: '2-digit',
  }).format(date)
}

export function MachineStateTimelineChart({
  intervals,
  machineName,
}: MachineStateTimelineChartProps) {
  const option = useMemo(() => {
    const lastInterval = intervals.at(-1)
    const firstStart = intervals[0]
      ? new Date(intervals[0].startedAt).getTime()
      : fallbackTimelineStart
    const lastEnd = lastInterval
      ? new Date(lastInterval.endedAt).getTime()
      : firstStart + 60 * 60 * 1000
    const rangeMs = Math.max(60 * 60 * 1000, lastEnd - firstStart)
    const padding = Math.min(60 * 60 * 1000, Math.floor(rangeMs * 0.04))
    const data: TimelineSeriesItem[] = intervals.map((interval) => ({
      value: [
        0,
        new Date(interval.startedAt).getTime(),
        new Date(interval.endedAt).getTime(),
      ],
      itemStyle: {
        color: analyticsStateMeta[interval.state].color,
      },
      meta: interval,
    }))

    return {
      animation: true,
      animationDuration: 220,
      textStyle: {
        fontFamily,
        fontWeight: 500,
      },
      tooltip: {
        trigger: 'item',
        borderWidth: 0,
        backgroundColor: '#20263a',
        padding: 12,
        textStyle: {
          color: '#ffffff',
          fontSize: 13,
          fontFamily,
        },
        extraCssText:
          'border-radius: 14px; box-shadow: 0 12px 32px rgba(16, 24, 40, 0.22);',
        formatter: (params: TimelineTooltipParam) => {
          const interval = params.data?.meta

          if (!interval) return ''

          const stateMeta = analyticsStateMeta[interval.state]

          return `
            <div style="min-width:260px;">
              <div style="color:#aeb8cc;font-size:12px;margin-bottom:8px;">
                ${formatAnalyticsDateTime(interval.startedAt)} — ${formatAnalyticsDateTime(interval.endedAt)}
              </div>

              <div style="display:flex;align-items:center;justify-content:space-between;gap:18px;">
                <div style="display:flex;align-items:center;gap:8px;">
                  <span style="width:10px;height:10px;border-radius:999px;background:${stateMeta.color};display:inline-block;"></span>
                  <span>${stateMeta.label}</span>
                </div>

                <strong>${formatDetailedDuration(interval.durationSeconds)}</strong>
              </div>
            </div>
          `
        },
      },
      grid: {
        left: 132,
        right: 28,
        top: 28,
        bottom: 54,
        height: 92,
      },
      dataZoom: [
        {
          type: 'slider',
          height: 22,
          bottom: 12,
          borderColor: 'transparent',
          backgroundColor: '#eff2f7',
          fillerColor: 'rgba(3, 28, 154, 0.15)',
          showDataShadow: false,
          showDetail: false,
          brushSelect: false,
        },
        {
          type: 'inside',
        },
      ],
      xAxis: {
        type: 'time',
        min: firstStart - padding,
        max: lastEnd + padding,
        axisLabel: {
          color: '#738098',
          fontSize: 12,
          fontFamily,
          hideOverlap: true,
          formatter: (value: number | string) => formatTimelineTick(value, rangeMs),
        },
        axisLine: {
          lineStyle: {
            color: '#dbe2ee',
          },
        },
        axisTick: {
          show: false,
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#edf0f5',
          },
        },
      },
      yAxis: {
        type: 'category',
        inverse: true,
        data: [machineName],
        axisLabel: {
          color: '#738098',
          fontSize: 12,
          fontFamily,
          width: 110,
          overflow: 'truncate',
        },
        axisLine: {
          show: false,
        },
        axisTick: {
          show: false,
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#edf0f5',
          },
        },
      },
      series: [
        {
          type: 'custom',
          name: 'Состояния',
          renderItem: renderTimelineItem,
          encode: {
            x: [1, 2],
            y: 0,
          },
          data,
        },
      ],
    }
  }, [intervals, machineName])

  if (intervals.length === 0) {
    return (
      <div className="machine-chart-empty">
        Нет телеметрии за выбранный период
      </div>
    )
  }

  return (
    <div className="machine-state-timeline-chart">
      <ReactECharts
        option={option}
        notMerge
        lazyUpdate
        style={{ height: 210 }}
      />
    </div>
  )
}
