import { CalendarOutlined } from '@ant-design/icons'
import { Button, Modal, Spin, Tooltip, Typography } from 'antd'
import moment from 'moment'
import React, { useEffect, useMemo, useRef, useState } from 'react'

import {
  buildDailyScheduleCounts,
  buildHeatmapGrid,
  getHeatmapColorLevel,
  HEATMAP_COLORS
} from './heatmapUtils'
import type { ClusterSummaryRow, MaintenanceCache } from './types'

const CELL_GAP = 4
const WEEKDAY_LABEL_WIDTH = 36
const MONTH_LABEL_HEIGHT = 20
const MIN_CELL_SIZE = 10
const MAX_CELL_SIZE = 36
const WEEKDAY_LABELS = ['', 'Mon', '', 'Wed', '', 'Fri', '']

type UpgradeScheduleHeatmapTriggerProps = {
  rows: ClusterSummaryRow[]
  maintenanceCache: MaintenanceCache
  loading?: boolean
  disabled?: boolean
}

function UpgradeScheduleHeatmapContent({
  rows,
  maintenanceCache,
  loading = false
}: Omit<UpgradeScheduleHeatmapTriggerProps, 'disabled'>) {
  const gridContainerRef = useRef<HTMLDivElement>(null)
  const [cellSize, setCellSize] = useState(16)

  const dailyCounts = useMemo(
    () => buildDailyScheduleCounts(rows, maintenanceCache),
    [maintenanceCache, rows]
  )

  const grid = useMemo(() => buildHeatmapGrid(dailyCounts), [dailyCounts])
  const weekCount = grid.weeks.length
  const weekWidth = cellSize + CELL_GAP
  const today = moment().format('YYYY-MM-DD')

  useEffect(() => {
    const container = gridContainerRef.current
    if (!container || weekCount === 0) return

    const updateCellSize = () => {
      const availableWidth = container.clientWidth - WEEKDAY_LABEL_WIDTH - 8
      const nextSize = Math.floor(
        (availableWidth - CELL_GAP * (weekCount - 1)) / weekCount
      )
      setCellSize(Math.min(MAX_CELL_SIZE, Math.max(MIN_CELL_SIZE, nextSize)))
    }

    updateCellSize()
    const observer = new ResizeObserver(updateCellSize)
    observer.observe(container)
    return () => observer.disconnect()
  }, [weekCount])

  return (
    <div ref={gridContainerRef} style={{ width: '100%' }}>
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
          marginBottom: 12,
          gap: 12,
          flexWrap: 'wrap'
        }}
      >
        <Typography.Text>
          <Typography.Text strong>{grid.totalScheduled}</Typography.Text>{' '}
          scheduled clusters between {grid.rangeStart} and {grid.rangeEnd}
        </Typography.Text>
        {loading ? <Spin size="small" /> : null}
      </div>

      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          width: '100%'
        }}
      >
        <div style={{ display: 'flex', gap: 8 }}>
          <div
            style={{
              width: WEEKDAY_LABEL_WIDTH,
              flexShrink: 0,
              display: 'flex',
              flexDirection: 'column',
              gap: CELL_GAP,
              paddingTop: MONTH_LABEL_HEIGHT
            }}
          >
            {WEEKDAY_LABELS.map((label, index) => (
              <Typography.Text
                key={`${label || 'blank'}-${index}`}
                type="secondary"
                style={{
                  fontSize: 11,
                  lineHeight: `${cellSize}px`,
                  height: cellSize,
                  visibility: label ? 'visible' : 'hidden'
                }}
              >
                {label || 'Mon'}
              </Typography.Text>
            ))}
          </div>

          <div
            style={{
              width: weekCount * weekWidth - CELL_GAP,
              maxWidth: `calc(100vw - ${WEEKDAY_LABEL_WIDTH + 80}px)`,
              overflowX: 'auto'
            }}
          >
            <div
              style={{
                position: 'relative',
                height: MONTH_LABEL_HEIGHT,
                marginBottom: 4,
                minWidth: weekCount * weekWidth - CELL_GAP
              }}
            >
              {grid.monthLabels.map((month) => (
                <Typography.Text
                  key={`${month.label}-${month.weekIndex}`}
                  type="secondary"
                  style={{
                    position: 'absolute',
                    left: month.weekIndex * weekWidth,
                    fontSize: 11,
                    lineHeight: `${MONTH_LABEL_HEIGHT}px`
                  }}
                >
                  {month.label}
                </Typography.Text>
              ))}
            </div>

            <div
              style={{
                display: 'flex',
                gap: CELL_GAP,
                minWidth: weekCount * weekWidth - CELL_GAP
              }}
            >
              {grid.weeks.map((week, weekIndex) => (
                <div
                  key={weekIndex}
                  style={{
                    display: 'flex',
                    flexDirection: 'column',
                    gap: CELL_GAP,
                    width: cellSize,
                    flexShrink: 0
                  }}
                >
                  {week.map((cell, dayIndex) => {
                    if (!cell) {
                      return (
                        <span
                          key={`empty-${weekIndex}-${dayIndex}`}
                          style={{
                            width: cellSize,
                            height: cellSize
                          }}
                        />
                      )
                    }

                    const level = getHeatmapColorLevel(
                      cell.count,
                      grid.maxCount
                    )
                    const isToday = cell.date === today
                    const title =
                      cell.count > 0
                        ? `${moment(cell.date).format('YYYY-MM-DD')}: ${
                            cell.count
                          } scheduled cluster${cell.count > 1 ? 's' : ''}`
                        : `${moment(cell.date).format(
                            'YYYY-MM-DD'
                          )}: no scheduled clusters`

                    return (
                      <Tooltip key={cell.date} title={title}>
                        <span
                          aria-label={title}
                          style={{
                            width: cellSize,
                            height: cellSize,
                            borderRadius: 3,
                            background: HEATMAP_COLORS[level],
                            display: 'block',
                            boxSizing: 'border-box',
                            border: isToday
                              ? '3px solid #cf1322'
                              : '3px solid transparent'
                          }}
                        />
                      </Tooltip>
                    )
                  })}
                </div>
              ))}
            </div>

            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'flex-end',
                gap: 5,
                marginTop: 12
              }}
            >
              <Typography.Text type="secondary" style={{ fontSize: 11 }}>
                Less
              </Typography.Text>
              {HEATMAP_COLORS.map((color) => (
                <span
                  key={color}
                  style={{
                    width: cellSize,
                    height: cellSize,
                    borderRadius: 3,
                    background: color,
                    display: 'inline-block'
                  }}
                />
              ))}
              <Typography.Text type="secondary" style={{ fontSize: 11 }}>
                More
              </Typography.Text>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export function UpgradeScheduleHeatmapTrigger({
  rows,
  maintenanceCache,
  loading = false,
  disabled = false
}: UpgradeScheduleHeatmapTriggerProps) {
  const [open, setOpen] = useState(false)

  return (
    <>
      <Button
        icon={<CalendarOutlined />}
        onClick={() => setOpen(true)}
        disabled={disabled}
      >
        Schedule Heatmap
      </Button>

      <Modal
        title="Upgrade Schedule Heatmap"
        visible={open}
        onCancel={() => setOpen(false)}
        footer={null}
        width={920}
        destroyOnClose
        bodyStyle={{ padding: '16px 20px 20px' }}
      >
        {rows.length ? (
          <UpgradeScheduleHeatmapContent
            rows={rows}
            maintenanceCache={maintenanceCache}
            loading={loading}
          />
        ) : (
          <Typography.Text type="secondary">
            No data to display.
          </Typography.Text>
        )}
      </Modal>
    </>
  )
}
