import {
  ActionIcon,
  Badge,
  Box,
  Button,
  Flex,
  Group,
  Modal,
  SegmentedControl,
  SimpleGrid,
  Stack,
  Tooltip,
  Typography,
  notifier
} from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import {
  IconEye,
  IconPlus,
  IconRefreshCcw01,
  IconSwitchHorizontal01,
  IconTrash01
} from '@tidbcloud/uikit/icons'
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'

import {
  TenantReservedCapacityTemplateScope,
  TenantReservedCapacityTemplateStatus,
  TenantUpdateReservedCapacityTemplateStatusReqStatus
} from 'apiClient/services/devops/interface'

import {
  buildCreateReservedCapacityTemplateReq,
  createPremiumReservedCapacityTemplate,
  deletePremiumReservedCapacityTemplate,
  listPremiumReservedCapacityTemplates,
  PremiumReservedCapacityTemplate,
  updatePremiumReservedCapacityTemplateStatus
} from './api'
import {
  DEFAULT_RESERVED_CAPACITY_CALCULATOR_INPUT,
  RESERVED_CAPACITY_FIXED_ASSUMPTIONS,
  ReservedCapacityCalculationResult,
  ReservedCapacityCalculatorInput
} from './calculator'
import PremiumReservedCapacityCalculator, {
  PremiumReservedCapacityCalculatorFormValues
} from './TemplateCalculator'

type PremiumReservedCapacityProps = {
  orgId: string
}

type PageMode = 'list' | 'calculator'

type DeleteTarget = PremiumReservedCapacityTemplate | undefined
type DetailTarget = PremiumReservedCapacityTemplate | undefined
type StatusTarget = PremiumReservedCapacityTemplate | undefined
type TemplateStatus = TenantUpdateReservedCapacityTemplateStatusReqStatus
type TopologyComponent = NonNullable<
  NonNullable<PremiumReservedCapacityTemplate['fixed_topology']>['components']
>[number]
type TopologyNodeSpec = NonNullable<
  NonNullable<TopologyComponent['node_quota']>['node_spec']
>

const formatTime = (time?: string) => {
  if (!time) {
    return '-'
  }

  return new Date(time).toLocaleString(undefined, { hour12: false })
}

const renderStatus = (status?: TenantReservedCapacityTemplateStatus) => {
  const value = status || TenantReservedCapacityTemplateStatus.ACTIVE
  const color =
    value === TenantReservedCapacityTemplateStatus.ACTIVE ? 'green' : 'orange'

  return (
    <Badge color={color} variant="dot" size="lg">
      {value}
    </Badge>
  )
}

const getTemplateStatus = (status?: TenantReservedCapacityTemplateStatus) =>
  (status || TenantReservedCapacityTemplateStatus.ACTIVE) as TemplateStatus

const isDefaultTemplate = (record?: PremiumReservedCapacityTemplate) =>
  record?.scope === TenantReservedCapacityTemplateScope.DEFAULT

const formatNumber = (value?: number, suffix = '') =>
  typeof value === 'number' ? `${value}${suffix}` : '-'

const formatLatencyP99 = (value?: number) =>
  typeof value === 'number' ? `P99 ${value}ms` : '-'

const formatRatio = (value?: number) =>
  typeof value === 'number' ? value.toString() : '-'

const renderOverflowText = (value?: string, width = 160) => {
  const content = value || '-'

  return (
    <Tooltip label={content} disabled={content === '-'}>
      <Typography
        variant="body-sm"
        style={{
          maxWidth: width,
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          whiteSpace: 'nowrap'
        }}
      >
        {content}
      </Typography>
    </Tooltip>
  )
}

const getErrorContent = (error: any) =>
  error?.response?.data?.errmsg || error?.message || String(error)

const notifyOperationSubmitted = (
  message: string,
  operationId?: string | number
) => {
  notifier.success(
    operationId ? (
      <>
        {message}. Click{' '}
        <a href={`/operations/${operationId}`} target="_blank" rel="noreferrer">
          operation detail
        </a>{' '}
        to check the progress.
      </>
    ) : (
      message
    ),
    { autoClose: 10000 }
  )
}

const formatNodeSpec = (nodeSpec?: TopologyNodeSpec) => {
  const cpu = nodeSpec?.cpu
  const memory = nodeSpec?.memory_gi

  return typeof cpu === 'number' && typeof memory === 'number'
    ? `${cpu}c${memory}g`
    : '-'
}

const renderStorages = (component: TopologyComponent) => {
  if (!component.storages?.length) {
    return '-'
  }

  return component.storages
    .map(
      (storage) =>
        `${storage.name}: ${storage.size_gi} GiB, ${storage.iops} IOPS, ${storage.throughput_mbs} Mbps`
    )
    .join('; ')
}

const getCalculatorInput = (
  record?: PremiumReservedCapacityTemplate
): ReservedCapacityCalculatorInput => {
  const workloadType = record?.workload?.workload_type?.toLowerCase()
  const latencyRequirement =
    record?.workload?.p99_response_latency_max === 100
      ? 'p99_100ms'
      : 'p99_300ms'

  return {
    ...DEFAULT_RESERVED_CAPACITY_CALCULATOR_INPUT,
    customerDataSizeGb:
      record?.workload?.data_size_gib_max ??
      DEFAULT_RESERVED_CAPACITY_CALCULATOR_INPUT.customerDataSizeGb,
    latencyRequirement,
    qps:
      record?.workload?.qps_max ??
      DEFAULT_RESERVED_CAPACITY_CALCULATOR_INPUT.qps,
    workloadPattern:
      workloadType === 'read' || workloadType === 'write'
        ? workloadType
        : DEFAULT_RESERVED_CAPACITY_CALCULATOR_INPUT.workloadPattern
  }
}

const DetailItem = ({ label, value }: { label: string; value: ReactNode }) => (
  <Stack gap={2}>
    <Typography variant="label-sm" c="carbon.6">
      {label}
    </Typography>
    <Typography variant="body-sm">{value || '-'}</Typography>
  </Stack>
)

const topologyColumns: MRT_ColumnDef<TopologyComponent>[] = [
  {
    header: 'Component',
    accessorKey: 'component_type',
    size: 120
  },
  {
    header: 'Spec',
    accessorFn: (component) => formatNodeSpec(component.node_quota?.node_spec),
    size: 80
  },
  {
    header: 'Nodes',
    accessorFn: (component) => component.node_quota?.node_count || '-',
    size: 72
  },
  {
    header: 'Total vCPU',
    size: 96,
    accessorFn: (component) => {
      const nodeCount = component.node_quota?.node_count
      const cpu = component.node_quota?.node_spec?.cpu

      return typeof nodeCount === 'number' && typeof cpu === 'number'
        ? nodeCount * cpu
        : '-'
    }
  },
  {
    header: 'Disks',
    accessorFn: renderStorages,
    Cell: ({ row }) => (
      <Typography
        variant="body-sm"
        style={{ whiteSpace: 'normal', wordBreak: 'break-word' }}
      >
        {renderStorages(row.original)}
      </Typography>
    ),
    size: 360
  }
]

const renderTopology = (record: PremiumReservedCapacityTemplate) => {
  const components = record.fixed_topology?.components || []

  if (!components.length) {
    return (
      <Typography variant="body-sm" c="carbon.6">
        No topology
      </Typography>
    )
  }

  return (
    <Box py="xs">
      <ProTable<TopologyComponent>
        columns={topologyColumns}
        data={components}
        enablePagination={false}
        withBorder={false}
        getRowId={(component) => component.component_type || ''}
        mantineTableHeadCellProps={{
          sx: {
            padding: '6px 8px !important'
          }
        }}
        mantineTableBodyCellProps={{
          sx: {
            padding: '6px 8px !important',
            verticalAlign: 'top'
          }
        }}
      />
    </Box>
  )
}

export default function PremiumReservedCapacity({
  orgId
}: PremiumReservedCapacityProps) {
  const [mode, setMode] = useState<PageMode>('list')
  const [templates, setTemplates] = useState<PremiumReservedCapacityTemplate[]>(
    []
  )
  const [loading, setLoading] = useState(false)
  const [saving, setSaving] = useState(false)
  const [deleteTarget, setDeleteTarget] = useState<DeleteTarget>()
  const [detailTarget, setDetailTarget] = useState<DetailTarget>()
  const [mutatingTemplateId, setMutatingTemplateId] = useState<string>()
  const [statusTarget, setStatusTarget] = useState<StatusTarget>()
  const [nextStatus, setNextStatus] = useState<TemplateStatus>(
    TenantUpdateReservedCapacityTemplateStatusReqStatus.ACTIVE
  )

  const loadTemplates = useCallback(async () => {
    setLoading(true)

    try {
      const resp = await listPremiumReservedCapacityTemplates({
        organization_id: orgId
      })
      setTemplates(resp.data.reserved_capacity_templates || [])
    } catch (error) {
      notifier.error(
        `Failed to load premium reserved capacity templates: ${getErrorContent(
          error
        )}`
      )
    } finally {
      setLoading(false)
    }
  }, [orgId])

  useEffect(() => {
    loadTemplates()
  }, [loadTemplates])

  const handleSave = async (
    values: PremiumReservedCapacityCalculatorFormValues,
    calculation: ReservedCapacityCalculationResult
  ) => {
    setSaving(true)

    try {
      const resp = await createPremiumReservedCapacityTemplate(
        buildCreateReservedCapacityTemplateReq(
          orgId,
          values.name.trim(),
          values.description.trim(),
          calculation
        )
      )
      notifyOperationSubmitted(
        'Premium reserved capacity template creation submitted',
        resp.data.instance_id
      )
      setMode('list')
      await loadTemplates()
    } catch (error) {
      notifier.error(
        `Failed to create premium reserved capacity template: ${getErrorContent(
          error
        )}`
      )
    } finally {
      setSaving(false)
    }
  }

  const handleStatusChange = async (
    record: PremiumReservedCapacityTemplate,
    status: TenantUpdateReservedCapacityTemplateStatusReqStatus
  ) => {
    if (isDefaultTemplate(record)) {
      notifier.error('Default templates do not support status changes')
      return false
    }

    if (!record.id || status === getTemplateStatus(record.status)) {
      return true
    }

    setMutatingTemplateId(record.id)

    try {
      const resp = await updatePremiumReservedCapacityTemplateStatus(
        record.id,
        status,
        'Update premium reserved capacity template status'
      )
      notifyOperationSubmitted(
        'Premium reserved capacity template status update submitted',
        resp.data.instance_id
      )
      await loadTemplates()
      return true
    } catch (error) {
      notifier.error(
        `Failed to update template status: ${getErrorContent(error)}`
      )
      return false
    } finally {
      setMutatingTemplateId(undefined)
    }
  }

  const openStatusModal = (record: PremiumReservedCapacityTemplate) => {
    if (isDefaultTemplate(record)) {
      return
    }

    setStatusTarget(record)
    setNextStatus(getTemplateStatus(record.status))
  }

  const handleStatusConfirm = async () => {
    if (!statusTarget) {
      return
    }

    const succeeded = await handleStatusChange(statusTarget, nextStatus)
    if (succeeded) {
      setStatusTarget(undefined)
    }
  }

  const handleDelete = async (record: PremiumReservedCapacityTemplate) => {
    if (isDefaultTemplate(record)) {
      notifier.error('Default templates do not support deletion')
      return
    }

    if (!record.id) {
      return
    }

    setMutatingTemplateId(record.id)

    try {
      const resp = await deletePremiumReservedCapacityTemplate(
        record.id,
        'Delete premium reserved capacity template'
      )
      notifyOperationSubmitted(
        'Premium reserved capacity template deletion submitted',
        resp.data.instance_id
      )
      setDeleteTarget(undefined)
      await loadTemplates()
    } catch (error) {
      notifier.error(`Failed to delete template: ${getErrorContent(error)}`)
    } finally {
      setMutatingTemplateId(undefined)
    }
  }

  const detailInput = getCalculatorInput(detailTarget)

  const actions = useMemo(
    () => [
      <Button
        key="create"
        leftSection={<IconPlus size={16} />}
        onClick={() => setMode('calculator')}
      >
        Create Template
      </Button>
    ],
    []
  )

  const columns: MRT_ColumnDef<PremiumReservedCapacityTemplate>[] = [
    {
      header: 'Template ID',
      accessorKey: 'id',
      Cell: ({ row }) => renderOverflowText(row.original.id, 160),
      size: 176
    },
    {
      header: 'Name',
      accessorFn: (record) => record.template_code || '-',
      Cell: ({ row }) => renderOverflowText(row.original.template_code, 180),
      size: 200
    },
    {
      header: 'Scope',
      accessorFn: (record) => record.scope || '-',
      size: 120
    },
    {
      header: 'Status',
      Cell: ({ row }) => renderStatus(row.original.status),
      size: 120
    },
    {
      header: 'Purchased vCPU',
      accessorKey: 'purchased_vcpu',
      size: 130
    },
    {
      header: 'Peak QPS',
      accessorFn: (record) => formatNumber(record.workload?.qps_max),
      size: 105
    },
    {
      header: 'Workload',
      accessorFn: (record) => record.workload?.workload_type || '-',
      size: 105
    },
    {
      header: 'Latency P99',
      accessorFn: (record) =>
        formatLatencyP99(record.workload?.p99_response_latency_max),
      size: 115
    },
    {
      header: 'Disk Size',
      accessorFn: (record) =>
        formatNumber(record.workload?.data_size_gib_max, ' GiB'),
      size: 105
    },
    {
      header: 'Created Time',
      accessorFn: (record) => formatTime(record.create_time),
      size: 170
    },
    {
      id: 'action',
      header: 'Action',
      size: 132,
      Cell: ({ row }) => {
        const record = row.original
        const isDefault = isDefaultTemplate(record)

        return (
          <Group gap={8} wrap="nowrap">
            <Tooltip label="View details">
              <ActionIcon
                variant="subtle"
                onClick={() => setDetailTarget(record)}
                aria-label="View template details"
              >
                <IconEye size={16} />
              </ActionIcon>
            </Tooltip>
            {!isDefault && (
              <>
                <Tooltip label="Change status">
                  <ActionIcon
                    variant="subtle"
                    loading={mutatingTemplateId === record.id}
                    onClick={() => openStatusModal(record)}
                    aria-label="Change template status"
                  >
                    <IconSwitchHorizontal01 size={16} />
                  </ActionIcon>
                </Tooltip>
                <Tooltip label="Delete">
                  <ActionIcon
                    variant="subtle"
                    color="red"
                    loading={mutatingTemplateId === record.id}
                    onClick={() => setDeleteTarget(record)}
                    aria-label="Delete template"
                  >
                    <IconTrash01 size={16} />
                  </ActionIcon>
                </Tooltip>
              </>
            )}
          </Group>
        )
      }
    }
  ]

  if (mode === 'calculator') {
    return (
      <PremiumReservedCapacityCalculator
        loading={saving}
        onCancel={() => setMode('list')}
        onSave={handleSave}
      />
    )
  }

  return (
    <Stack gap="md">
      <Group justify="flex-end">
        {actions}
        <Tooltip label="Reload">
          <ActionIcon
            variant="default"
            loading={loading}
            onClick={loadTemplates}
            aria-label="Reload templates"
          >
            <IconRefreshCcw01 size={16} />
          </ActionIcon>
        </Tooltip>
      </Group>
      <ProTable<PremiumReservedCapacityTemplate>
        columns={columns}
        data={templates}
        getRowId={(record) => record.id || record.template_code || ''}
        loading={loading}
        enablePagination={false}
        enableColumnPinning
        initialState={{ columnPinning: { right: ['action'] } }}
      />

      <Modal
        opened={!!detailTarget}
        centered
        size="xl"
        title="Premium Reserved Capacity Template Details"
        onClose={() => setDetailTarget(undefined)}
      >
        <Stack gap="md">
          <SimpleGrid cols={{ base: 1, md: 2 }} spacing="md">
            <DetailItem label="Template ID" value={detailTarget?.id} />
            <DetailItem label="Name" value={detailTarget?.template_code} />
            <DetailItem
              label="Status"
              value={renderStatus(detailTarget?.status)}
            />
            <DetailItem
              label="Purchased vCPU"
              value={formatNumber(detailTarget?.purchased_vcpu)}
            />
            <DetailItem
              label="Created Time"
              value={formatTime(detailTarget?.create_time)}
            />
            <DetailItem
              label="Updated Time"
              value={formatTime(detailTarget?.update_time)}
            />
            <DetailItem
              label="Description"
              value={detailTarget?.description || '-'}
            />
          </SimpleGrid>

          <Box>
            <Typography variant="title-sm">Calculator Inputs</Typography>
            <SimpleGrid cols={{ base: 1, md: 2, lg: 4 }} spacing="md" mt="sm">
              <DetailItem label="QPS" value={formatNumber(detailInput.qps)} />
              <DetailItem
                label="Workload"
                value={detailInput.workloadPattern}
              />
              <DetailItem
                label="Latency Requirement"
                value={formatLatencyP99(
                  detailInput.latencyRequirement === 'p99_100ms' ? 100 : 300
                )}
              />
              <DetailItem
                label="Customer Data Size"
                value={formatNumber(detailInput.customerDataSizeGb, ' GiB')}
              />
              <DetailItem
                label="Compression Factor"
                value={formatRatio(
                  RESERVED_CAPACITY_FIXED_ASSUMPTIONS.compressionFactor
                )}
              />
              <DetailItem
                label="Replica"
                value={formatNumber(
                  RESERVED_CAPACITY_FIXED_ASSUMPTIONS.replica
                )}
              />
              <DetailItem
                label="Storage Water Level"
                value={formatRatio(
                  RESERVED_CAPACITY_FIXED_ASSUMPTIONS.storageWaterLevel
                )}
              />
            </SimpleGrid>
          </Box>

          <Box>
            <Typography variant="title-sm">Topology</Typography>
            {detailTarget ? renderTopology(detailTarget) : null}
          </Box>
        </Stack>
      </Modal>

      <Modal
        opened={!!statusTarget}
        centered
        title="Change Template Status"
        onClose={() => setStatusTarget(undefined)}
      >
        <Stack>
          <Stack gap={4}>
            <Typography variant="label-sm" c="carbon.6">
              Template
            </Typography>
            {renderOverflowText(
              statusTarget?.template_code || statusTarget?.id,
              420
            )}
          </Stack>

          <Group justify="space-between" align="center">
            <Typography variant="label-sm" c="carbon.6">
              Current Status
            </Typography>
            {renderStatus(statusTarget?.status)}
          </Group>

          <Stack gap={4}>
            <Typography variant="label-sm">New Status</Typography>
            <SegmentedControl
              value={nextStatus}
              data={[
                {
                  label: 'Active',
                  value:
                    TenantUpdateReservedCapacityTemplateStatusReqStatus.ACTIVE
                },
                {
                  label: 'Deprecated',
                  value:
                    TenantUpdateReservedCapacityTemplateStatusReqStatus.DEPRECATED
                }
              ]}
              onChange={(value) => setNextStatus(value as TemplateStatus)}
            />
          </Stack>

          <Flex justify="flex-end" gap={16}>
            <Button
              variant="outline"
              onClick={() => setStatusTarget(undefined)}
            >
              Cancel
            </Button>
            <Button
              loading={
                !!statusTarget?.id && mutatingTemplateId === statusTarget.id
              }
              disabled={nextStatus === getTemplateStatus(statusTarget?.status)}
              onClick={handleStatusConfirm}
            >
              Update Status
            </Button>
          </Flex>
        </Stack>
      </Modal>

      <Modal
        opened={!!deleteTarget}
        centered
        title="Delete Premium Reserved Capacity Template"
        onClose={() => setDeleteTarget(undefined)}
      >
        <Stack>
          <Typography variant="body-lg">
            Delete template {deleteTarget?.id || '-'}?
          </Typography>
          <Flex justify="flex-end" gap={16}>
            <Button
              variant="outline"
              onClick={() => setDeleteTarget(undefined)}
            >
              Cancel
            </Button>
            <Button
              color="red"
              loading={
                !!deleteTarget?.id && mutatingTemplateId === deleteTarget.id
              }
              onClick={() => deleteTarget && handleDelete(deleteTarget)}
            >
              Delete
            </Button>
          </Flex>
        </Stack>
      </Modal>
    </Stack>
  )
}
