import React, { useMemo, useState } from 'react'

import { showNotification } from '@mantine/notifications'
import {
  ActionIcon,
  Button,
  Card,
  Group,
  Menu,
  Modal,
  Stack,
  Text,
  Title,
  openConfirmModal
} from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { IconArrowCircleLeft, IconDotsHorizontal } from '@tidbcloud/uikit/icons'
import { useNavigate, useParams } from 'react-router-dom'
import useSWR from 'swr'

import { useCurCluster, useCurOrg } from '~/hooks/state'
import { useMutation } from '~/hooks/use-mutation'
import { formatDateTime } from '~/utils/date-time'

import {
  deleteStrategy,
  getStrategy,
  listStrategies,
  updateStrategy
} from '../api'
import { CheckItemBadge } from '../components/CheckItemBadge'
import { formatWindowSuffix } from '../scheduleDisplay'
import type {
  HealthcheckHealthCheckStrategyReq,
  HealthcheckHealthCheckStrategyResp
} from '../types'
import { StrategyForm } from './StrategyForm'

const StrategyManagementPage: React.FC = () => {
  const navigate = useNavigate()
  const { orgId, cid } = useParams<'orgId' | 'cid'>()

  const { curOrg } = useCurOrg()
  const { curCluster } = useCurCluster()

  const oid = curOrg!.id!
  const clusterId = curCluster!.id!
  const [editingStrategyUuid, setEditingStrategyUuid] = useState<string | null>(
    null
  )

  const {
    data: strategiesRes,
    error: strategiesError,
    mutate: reloadStrategies
  } = useSWR(`/healthcheck/strategies/${oid}/${clusterId}`, () =>
    listStrategies(oid, clusterId)
  )
  const strategies = strategiesRes?.data?.strategies ?? []
  const strategiesLoading = !strategiesRes && !strategiesError

  const {
    data: editingStrategyRes,
    error: editingStrategyError,
    mutate: reloadEditingStrategy
  } = useSWR(
    editingStrategyUuid
      ? `/healthcheck/strategies/${oid}/${clusterId}/${editingStrategyUuid}`
      : null,
    () => getStrategy(oid, clusterId, editingStrategyUuid!)
  )
  const editingStrategy = editingStrategyRes?.data
  const editingStrategyLoading =
    editingStrategyUuid != null && !editingStrategyRes && !editingStrategyError

  const { loading: updating, run: runUpdate } = useMutation(
    (req: { uuid: string; strategy: HealthcheckHealthCheckStrategyReq }) =>
      updateStrategy(oid, clusterId, req.uuid, req.strategy)
  )

  const closeEditModal = () => {
    setEditingStrategyUuid(null)
    reloadEditingStrategy(undefined, false)
  }

  const handleEditSubmit = (strategy: HealthcheckHealthCheckStrategyReq) => {
    if (!editingStrategyUuid) return

    runUpdate(
      { uuid: editingStrategyUuid, strategy },
      () => {
        showNotification({
          color: 'green',
          message: `Strategy "${strategy.name}" updated successfully.`
        })
        closeEditModal()
        reloadStrategies()
      },
      () => {
        showNotification({
          color: 'red',
          message: `Failed to update strategy "${strategy.name}".`
        })
      }
    )
  }

  const handleDelete = (uuid: string, name?: string) => {
    openConfirmModal({
      title: 'Delete Strategy',
      centered: true,
      labels: { confirm: 'Delete', cancel: 'Cancel' },
      confirmProps: { color: 'red' },
      children: (
        <Text size='sm'>
          Are you sure you want to delete strategy{' '}
          <Text span fw={600}>
            {name || uuid}
          </Text>
          ? This action cannot be undone.
        </Text>
      ),
      onConfirm: () => {
        deleteStrategy(oid, clusterId, uuid).then(() => {
          showNotification({
            color: 'green',
            message: `Strategy "${name || uuid}" deleted successfully.`
          })
          reloadStrategies()
        })
      }
    })
  }

  const columns = useStrategyColumns(
    curCluster?.provider,
    setEditingStrategyUuid,
    handleDelete
  )

  return (
    <div>
      <Group justify='space-between' mb='lg' align='center'>
        <Group gap='xs' align='center'>
          <ActionIcon
            variant='subtle'
            aria-label='back'
            onClick={() =>
              navigate(`/orgs/${orgId}/clusters/${cid}/health-check`)
            }
            title='Back to Health Check'
          >
            <IconArrowCircleLeft size={20} />
          </ActionIcon>
          <Title order={3}>Strategy Management</Title>
        </Group>
        <Button
          onClick={() =>
            navigate(
              `/orgs/${orgId}/clusters/${cid}/health-check/strategies/create`
            )
          }
        >
          Create Strategy
        </Button>
      </Group>

      <Card withBorder p='lg'>
        <ProTable<HealthcheckHealthCheckStrategyResp>
          columns={columns}
          data={strategies}
          state={{ isLoading: strategiesLoading }}
          enableColumnPinning
          initialState={{ columnPinning: { right: ['actions'] } }}
        />
      </Card>

      <Modal
        opened={editingStrategyUuid != null}
        onClose={closeEditModal}
        title='Edit Strategy'
        size={1080}
      >
        {editingStrategyLoading && (
          <Stack py='md'>
            <Text size='sm' c='dimmed'>
              Loading strategy...
            </Text>
          </Stack>
        )}
        {editingStrategyError && (
          <Stack py='md'>
            <Text size='sm' c='red'>
              Failed to load strategy detail.
            </Text>
          </Stack>
        )}
        {editingStrategy && (
          <StrategyForm
            key={editingStrategy.uuid ?? editingStrategyUuid}
            initialStrategy={editingStrategy}
            provider={curCluster?.provider}
            submitLabel='Save'
            submitting={updating}
            onCancel={closeEditModal}
            onSubmit={handleEditSubmit}
          />
        )}
      </Modal>
    </div>
  )
}

function useStrategyColumns(
  provider: string | undefined,
  onEdit: (uuid: string) => void,
  onDelete: (uuid: string, name?: string) => void
): MRT_ColumnDef<HealthcheckHealthCheckStrategyResp>[] {
  return useMemo(
    () => [
      {
        id: 'name',
        header: 'Name',
        accessorFn: (row) => row.name ?? '-'
      },
      {
        id: 'description',
        header: 'Description',
        accessorFn: (row) => row.description || '-'
      },
      {
        id: 'scheduleType',
        header: 'Trigger',
        accessorFn: (row) => {
          if (!row.scheduleType || row.scheduleType === 'manual')
            return 'Manual Only'
          if (row.scheduleType === 'cron') {
            const cronMatch = row.scheduleExpr?.match(
              /^(?:CRON_TZ=(\S+)\s+)?(\d+)\s+(\d+)\s+\*\s+\*\s+\*$/
            )
            if (cronMatch) {
              const tz = cronMatch[1] || 'UTC'
              const minute = cronMatch[2].padStart(2, '0')
              const hour = cronMatch[3].padStart(2, '0')
              return `Daily at ${hour}:${minute} (${tz})${formatWindowSuffix(
                row.timeRangeAStart,
                row.timeRangeAEnd
              )}`
            }
            return `Cron (${row.scheduleExpr})`
          }
          return row.scheduleType
        }
      },
      {
        id: 'items',
        header: 'Enabled Items',
        accessorFn: (row) => {
          const shouldHideDiskCheck = provider != null && provider !== 'aws'
          const enabled =
            row.items?.filter(
              (item) =>
                item.enabled !== false &&
                (!shouldHideDiskCheck || item.name !== 'disk_check')
            ) ?? []
          if (enabled.length === 0) return '-'
          return (
            <Group gap={4}>
              {enabled.map((item) => (
                <CheckItemBadge key={item.name} item={item} />
              ))}
            </Group>
          )
        }
      },
      {
        id: 'createdAt',
        header: `Created At (GMT${
          new Date().getTimezoneOffset() <= 0 ? '+' : '-'
        }${Math.abs(new Date().getTimezoneOffset() / 60)})`,
        accessorFn: (row) => {
          const raw = row.createdAt ?? (row as any).created_at
          if (!raw) return '-'
          return formatDateTime(new Date(raw).getTime() / 1000)
        }
      },
      {
        id: 'actions',
        header: 'Actions',
        size: 50,
        accessorFn: (row) => (
          <Menu position='bottom'>
            <Menu.Target>
              <ActionIcon size={32}>
                <IconDotsHorizontal size={16} />
              </ActionIcon>
            </Menu.Target>
            <Menu.Dropdown>
              <Menu.Item
                disabled={!row.uuid}
                onClick={() => row.uuid && onEdit(row.uuid)}
              >
                Edit
              </Menu.Item>
              <Menu.Item
                color='red'
                onClick={() => row.uuid && onDelete(row.uuid, row.name)}
              >
                Delete
              </Menu.Item>
            </Menu.Dropdown>
          </Menu>
        )
      }
    ],
    [onDelete, onEdit, provider]
  )
}

export default StrategyManagementPage
