import { BellOutlined, SyncOutlined } from '@ant-design/icons'
import { Button, Modal, Space, Table, Tag, Typography, message } from 'antd'
import type { ColumnsType } from 'antd/lib/table'
import { useCallback, useMemo, useState } from 'react'

import {
  k8sCalendarControllerListLifecycles,
  k8sCalendarControllerResetNotificationFlags,
  k8sCalendarControllerSyncNow
} from 'apiClient/services/devops'
import type { K8scalendarVersionLifecycle } from 'apiClient/services/devops/interface'
import { ListK8SInformationCloudProvider } from 'apiClient/services/devops/interface'
import { ListToolBar, useTable } from 'components/Table'

import { toLocal } from '../Maintenance/Detail'

import ResetNotificationModal, {
  getSetNotificationFlags,
  NOTIFICATION_FLAG_OPTIONS,
  type NotificationFlagValue
} from './ResetNotificationModal'

import './index.less'

type LifecycleRowStatus =
  | 'not_started'
  | 'active'
  | 'ending_soon'
  | 'standard_expired'

const CLOUD_PROVIDER_ORDER: Record<string, number> = {
  aws: 0,
  gcp: 1
}

const ROW_BACKGROUND: Record<LifecycleRowStatus, string> = {
  not_started: '#ffccc7',
  active: '#b7eb8f',
  ending_soon: '#ffe58f',
  standard_expired: '#f5f5f5'
}

const STATUS_FILTER_OPTIONS: {
  text: string
  value: LifecycleRowStatus
}[] = [
  { text: 'Standard support active', value: 'active' },
  { text: 'Standard support ends within 2 months', value: 'ending_soon' },
  { text: 'Lifecycle not started', value: 'not_started' },
  { text: 'Standard support expired', value: 'standard_expired' }
]

const DEFAULT_STATUS_FILTERED_VALUE: LifecycleRowStatus[] = [
  'active',
  'ending_soon',
  'not_started'
]

type TextHighlightStyle = {
  color: string
  background: string
  borderColor: string
}

const CLOUD_HIGHLIGHT_STYLES: Record<string, TextHighlightStyle> = {
  EKS: { color: '#c45500', background: '#fff7e6', borderColor: '#ff9900' },
  GKE: { color: '#389e0d', background: '#f6ffed', borderColor: '#b7eb8f' },
  AKS: { color: '#0958d9', background: '#e6f4ff', borderColor: '#91caff' },
  ACK: { color: '#d46b08', background: '#fff7e6', borderColor: '#ffd591' }
}

const CLOUD_HIGHLIGHT_FALLBACK: TextHighlightStyle[] = [
  { color: '#531dab', background: '#f9f0ff', borderColor: '#d3adf7' },
  { color: '#08979c', background: '#e6fffb', borderColor: '#87e8de' },
  { color: '#1d39c4', background: '#f0f5ff', borderColor: '#adc6ff' }
]

const getCloudHighlightIndex = (cloud: string): number => {
  let hash = 0
  for (let i = 0; i < cloud.length; i += 1) {
    hash = (hash * 31 + cloud.charCodeAt(i)) >>> 0
  }
  return hash % CLOUD_HIGHLIGHT_FALLBACK.length
}

const getCloudHighlightStyle = (cloud: string): TextHighlightStyle => {
  const normalized = cloud.trim().toUpperCase()
  return (
    CLOUD_HIGHLIGHT_STYLES[normalized] ??
    CLOUD_HIGHLIGHT_FALLBACK[getCloudHighlightIndex(normalized)]
  )
}

const CloudHighlight = ({ cloud }: { cloud: string }) => {
  const { color, background, borderColor } = getCloudHighlightStyle(cloud)
  return (
    <span
      className="k8s-calendar-cloud"
      style={{ color, background, borderColor }}
    >
      {cloud}
    </span>
  )
}

const parseLifecycleDate = (value?: string): Date | undefined => {
  if (!value) {
    return undefined
  }
  const date = new Date(value)
  return Number.isNaN(date.getTime()) ? undefined : date
}

const formatLifecycleDate = (value?: string): string | undefined => {
  const date = parseLifecycleDate(value)
  if (!date) {
    return undefined
  }
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}/${month}/${day}`
}

const parseVersionParts = (version?: string): number[] => {
  if (!version) {
    return []
  }
  return version.split('.').map((part) => parseInt(part, 10) || 0)
}

const compareCloudProvider = (left?: string, right?: string): number => {
  const leftOrder = CLOUD_PROVIDER_ORDER[(left ?? '').toLowerCase()] ?? 99
  const rightOrder = CLOUD_PROVIDER_ORDER[(right ?? '').toLowerCase()] ?? 99
  if (leftOrder !== rightOrder) {
    return leftOrder - rightOrder
  }
  return (left ?? '').localeCompare(right ?? '')
}

const compareVersionDesc = (left?: string, right?: string): number => {
  const leftParts = parseVersionParts(left)
  const rightParts = parseVersionParts(right)
  const length = Math.max(leftParts.length, rightParts.length)

  for (let i = 0; i < length; i += 1) {
    const diff = (rightParts[i] ?? 0) - (leftParts[i] ?? 0)
    if (diff !== 0) {
      return diff
    }
  }

  return (right ?? '').localeCompare(left ?? '')
}

const isStandardSupportEndingWithinTwoMonths = (
  endOfStandardSupport: Date,
  now: Date
): boolean => {
  if (now >= endOfStandardSupport) {
    return false
  }
  const twoMonthsLater = new Date(now)
  twoMonthsLater.setMonth(twoMonthsLater.getMonth() + 2)
  return endOfStandardSupport <= twoMonthsLater
}

const getLifecycleRowStatus = (
  record: K8scalendarVersionLifecycle
): LifecycleRowStatus => {
  const now = new Date()
  const lifecycleStart = parseLifecycleDate(record.lifecycle_start)
  const endOfStandardSupport = parseLifecycleDate(
    record.end_of_standard_support
  )

  if (lifecycleStart && now < lifecycleStart) {
    return 'not_started'
  }

  if (endOfStandardSupport && now > endOfStandardSupport) {
    return 'standard_expired'
  }

  if (
    endOfStandardSupport &&
    isStandardSupportEndingWithinTwoMonths(endOfStandardSupport, now)
  ) {
    return 'ending_soon'
  }

  return 'active'
}

const sortLifecycles = (items: K8scalendarVersionLifecycle[]) =>
  [...items].sort((left, right) => {
    const providerCmp = compareCloudProvider(
      left.cloud_provider,
      right.cloud_provider
    )
    if (providerCmp !== 0) {
      return providerCmp
    }
    return compareVersionDesc(left.version, right.version)
  })

const K8sCalendar = () => {
  const [syncing, setSyncing] = useState(false)
  const [resetRecord, setResetRecord] =
    useState<K8scalendarVersionLifecycle | null>(null)
  const [resetting, setResetting] = useState(false)

  const getData = () => k8sCalendarControllerListLifecycles()

  const { dataSource, loading, reload } = useTable<
    ListData<K8scalendarVersionLifecycle>
  >(getData, [], {
    pagination: false
  })

  const sortedDataSource = useMemo(
    () => sortLifecycles(dataSource ?? []),
    [dataSource]
  )

  const handleSync = useCallback(() => {
    Modal.confirm({
      title: 'Sync K8s Release Calendar',
      content:
        'Fetch the latest Kubernetes version lifecycle data from cloud providers (EKS/GKE)?',
      okText: 'Sync',
      onOk: async () => {
        setSyncing(true)
        try {
          await k8sCalendarControllerSyncNow({})
          message.success('K8s release calendar synced successfully')
          await reload()
        } finally {
          setSyncing(false)
        }
      }
    })
  }, [reload])

  const handleResetNotification = useCallback(
    async (flags: NotificationFlagValue[]) => {
      if (!resetRecord?.cloud || !resetRecord.version) return
      setResetting(true)
      try {
        await k8sCalendarControllerResetNotificationFlags({
          cloud: resetRecord.cloud,
          version: resetRecord.version,
          flags
        })
        message.success('Notification flags reset successfully')
        setResetRecord(null)
        await reload()
      } finally {
        setResetting(false)
      }
    },
    [resetRecord, reload]
  )

  const renderNotificationFlags = useCallback(
    (record: K8scalendarVersionLifecycle) => {
      const setFlags = getSetNotificationFlags(record)
      if (setFlags.length === 0) {
        return <span className="k8s-calendar-notify-none">—</span>
      }
      return (
        <Space size={4} wrap>
          {setFlags.map((flag) => {
            const opt = NOTIFICATION_FLAG_OPTIONS.find((o) => o.value === flag)
            return (
              <Tag key={flag} className="k8s-calendar-notify-tag">
                {opt?.label ?? flag}
              </Tag>
            )
          })}
        </Space>
      )
    },
    []
  )

  const renderResetAction = useCallback(
    (_: unknown, record: K8scalendarVersionLifecycle) => {
      const hasFlags = getSetNotificationFlags(record).length > 0
      return (
        <Button
          type="link"
          size="small"
          icon={<BellOutlined />}
          disabled={!record.cloud || !record.version || !hasFlags}
          onClick={() => setResetRecord(record)}
        >
          Reset Notification
        </Button>
      )
    },
    []
  )

  const cloudFilterOptions = useMemo(() => {
    const clouds = new Set<string>()
    ;(dataSource ?? []).forEach((item) => {
      if (item.cloud) {
        clouds.add(item.cloud)
      }
    })
    return Array.from(clouds)
      .sort((a, b) => a.localeCompare(b))
      .map((cloud) => ({ text: cloud, value: cloud }))
  }, [dataSource])

  const versionFilterOptions = useMemo(() => {
    const versions = new Set<string>()
    ;(dataSource ?? []).forEach((item) => {
      if (item.version) {
        versions.add(item.version)
      }
    })
    return Array.from(versions)
      .sort(compareVersionDesc)
      .map((version) => ({ text: version, value: version }))
  }, [dataSource])

  const columns = useMemo<ColumnsType<K8scalendarVersionLifecycle>>(
    () => [
      {
        title: '',
        key: 'status',
        width: 16,
        fixed: 'left',
        className: 'k8s-calendar-status-cell',
        filterMultiple: true,
        filters: STATUS_FILTER_OPTIONS,
        defaultFilteredValue: DEFAULT_STATUS_FILTERED_VALUE,
        onFilter: (value, record) => getLifecycleRowStatus(record) === value,
        render: () => null
      },
      {
        title: 'Cloud Provider',
        dataIndex: 'cloud_provider',
        width: 140,
        fixed: 'left',
        filterMultiple: true,
        filters: [
          {
            text: ListK8SInformationCloudProvider.aws,
            value: ListK8SInformationCloudProvider.aws
          },
          {
            text: ListK8SInformationCloudProvider.gcp,
            value: ListK8SInformationCloudProvider.gcp
          }
        ],
        onFilter: (value, record) => record.cloud_provider === value,
        render: (value: string) => value || '-'
      },
      {
        title: 'Cloud',
        dataIndex: 'cloud',
        width: 110,
        filterMultiple: true,
        filters: cloudFilterOptions,
        onFilter: (value, record) => record.cloud === value,
        render: (value: string) =>
          value ? <CloudHighlight cloud={value} /> : '-'
      },
      {
        title: 'Version',
        dataIndex: 'version',
        width: 130,
        filterMultiple: true,
        filters: versionFilterOptions,
        onFilter: (value, record) => record.version === value,
        render: (value: string) =>
          value ? <span className="k8s-calendar-version">{value}</span> : '-'
      },
      {
        title: 'Lifecycle Start',
        dataIndex: 'lifecycle_start',
        width: 130,
        render: (value: string) => formatLifecycleDate(value) || '-'
      },
      {
        title: 'End of Standard Support',
        dataIndex: 'end_of_standard_support',
        width: 170,
        render: (value: string) => formatLifecycleDate(value) || '-'
      },
      {
        title: 'End of Extended Support',
        dataIndex: 'end_of_extended_support',
        width: 170,
        render: (value: string) => formatLifecycleDate(value) || '-'
      },
      {
        title: 'Release Precision',
        dataIndex: 'release_precision',
        width: 140,
        render: (value: string) => value || '-'
      },
      {
        title: 'Scraped At',
        dataIndex: 'scraped_at',
        width: 170,
        render: (value: string) => toLocal(value) || '-'
      },
      {
        title: 'Source',
        dataIndex: 'source_url',
        width: 200,
        render: (url: string) =>
          url ? (
            <Typography.Link href={url} target="_blank" rel="noreferrer">
              <Typography.Text
                ellipsis={{ tooltip: url }}
                style={{ maxWidth: 180 }}
              >
                {url}
              </Typography.Text>
            </Typography.Link>
          ) : (
            '-'
          )
      },
      {
        title: 'Notifications',
        key: 'notifications',
        width: 200,
        render: (_: unknown, record) => renderNotificationFlags(record)
      },
      {
        title: 'Actions',
        key: 'actions',
        width: 150,
        fixed: 'right',
        render: renderResetAction
      }
    ],
    [
      cloudFilterOptions,
      versionFilterOptions,
      renderNotificationFlags,
      renderResetAction
    ]
  )

  const toolbarLegend = useMemo(
    () => (
      <Space size="small" wrap className="k8s-calendar-toolbar-legend">
        <Space size={4}>
          <span
            className="k8s-calendar-legend-swatch"
            style={{ background: ROW_BACKGROUND.active }}
          />
          <span>Standard support active</span>
        </Space>
        <Space size={4}>
          <span
            className="k8s-calendar-legend-swatch"
            style={{ background: ROW_BACKGROUND.ending_soon }}
          />
          <span>Standard support ends within 2 months</span>
        </Space>
        <Space size={4}>
          <span
            className="k8s-calendar-legend-swatch"
            style={{ background: ROW_BACKGROUND.not_started }}
          />
          <span>Lifecycle not started</span>
        </Space>
        <Space size={4}>
          <span
            className="k8s-calendar-legend-swatch"
            style={{ background: ROW_BACKGROUND.standard_expired }}
          />
          <span>Standard support expired</span>
        </Space>
      </Space>
    ),
    []
  )

  const toolbarActions = useMemo(
    () => [
      <Button
        key="sync"
        type="primary"
        icon={<SyncOutlined />}
        loading={syncing}
        onClick={handleSync}
      >
        Sync Calendar
      </Button>
    ],
    [syncing, handleSync]
  )

  return (
    <>
      <ListToolBar
        className="k8s-calendar-toolbar"
        title={toolbarLegend}
        reload={reload}
        actions={toolbarActions}
      />
      <Table<K8scalendarVersionLifecycle>
        className="k8s-calendar-table"
        columns={columns}
        rowKey={(record) =>
          String(record.id ?? `${record.cloud_provider}-${record.version}`)
        }
        dataSource={sortedDataSource}
        loading={loading}
        size="small"
        scroll={{ x: 1854 }}
        rowClassName={(record) =>
          `k8s-calendar-row--${getLifecycleRowStatus(record)}`
        }
        pagination={{
          showSizeChanger: true,
          defaultPageSize: 20,
          pageSizeOptions: ['10', '20', '50', '100'],
          showTotal: (total) => `Total ${total} versions`
        }}
      />
      <ResetNotificationModal
        record={resetRecord}
        loading={resetting}
        onSubmit={handleResetNotification}
        onCancel={() => setResetRecord(null)}
      />
    </>
  )
}

export default K8sCalendar
