import { Alert, Badge, Box, Button, Card, Drawer, Group, HoverCard, Paper, Stack, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import { IconAlertTriangle, IconInfoCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useEffect, useMemo, useState } from 'react'

import { ReasonHoverHint, type HoverHintReason } from 'dbaas/components/HoverHint/ReasonHoverHint'
import { useAccessDeniedHintReason } from 'dbaas/contexts/access-control'
import { useRequestSupport } from 'dbaas/screens/HelpCenter/RequestSupport/helper'
import { BlockHeader } from 'dbaas/screens/NextGen/premium/networking/shared/BlockHeader'
import { getTidbStateToPassivePhrase } from 'dbaas/screens/NextGen/shared/model/tidb-state'
import { useSharedTiDBContext } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import {
  useByocVpcPeeringServiceGetVpcPeeringAllowlistSetting,
  useByocVpcPeeringServiceListVpcPeerings
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import type { Nextgenv1beta2VpcPeering } from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'

import { AddAllowedAccessCidrModal } from './AddAllowedAccessCidrModal'
import { anywhereCidr } from './AllowedAccessCidrEditor'
import { VpcPeeringStatusBadge } from './VpcPeeringStatusBadge'

const DEFAULT_PAGE_SIZE = 5

export const ByocVpcPeeringPanel = observer(() => {
  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()

  const tidb = useSharedTiDBContext()
  const tidbId = tidb.tidbId!
  const passivePhrase = getTidbStateToPassivePhrase(tidb?.state)
  const [cidrModalOpened, cidrModalHandlers] = useDisclosure(false)
  const [selectedVpcPeering, setSelectedVpcPeering] = useState<Nextgenv1beta2VpcPeering | null>(null)
  const [pagination, setPagination] = useState({
    pageIndex: 0,
    pageSize: DEFAULT_PAGE_SIZE
  })
  const [pageTokens, setPageTokens] = useState<Record<number, string | undefined>>({ 0: undefined })
  const { reason: accessDeniedReason } = useAccessDeniedHintReason({ id: 'TidbxNetworkingUpdate' })
  const notReadyReason = useMemo<HoverHintReason>(
    () => ({
      id: 'notReady',
      when: !tidb?.computed.ready,
      content: `This feature is unavailable while the instance is ${passivePhrase}.`
    }),
    [passivePhrase, tidb?.computed.ready]
  )

  const { data, isFetching } = useByocVpcPeeringServiceListVpcPeerings(
    tidbId,
    {
      orgId,
      projectId,
      pageSize: pagination.pageSize,
      pageToken: pageTokens[pagination.pageIndex]
    },
    {
      query: {
        enabled: !!orgId && !!projectId && !!tidbId,
        refetchOnWindowFocus: false
      }
    }
  )

  useEffect(() => {
    setPageTokens({ 0: undefined })
    setPagination((prev) => ({ ...prev, pageIndex: 0 }))
  }, [pagination.pageSize, orgId, projectId, tidbId])

  useEffect(() => {
    setPageTokens((prev) => {
      if (prev[pagination.pageIndex + 1] === data?.nextPageToken) {
        return prev
      }

      return {
        ...prev,
        [pagination.pageIndex + 1]: data?.nextPageToken
      }
    })
  }, [data?.nextPageToken, pagination.pageIndex])

  const { data: allowlistData, refetch: refetchAllowlist } = useByocVpcPeeringServiceGetVpcPeeringAllowlistSetting(
    tidbId,
    {
      orgId,
      projectId
    },
    {
      query: {
        enabled: !!orgId && !!projectId && !!tidbId,
        refetchOnWindowFocus: false
      }
    }
  )

  const vpcPeerings = useMemo(() => {
    if (!data?.vpcPeerings) {
      return []
    }

    return data.vpcPeerings
  }, [data?.vpcPeerings])

  const allowedAccessCidrs = useMemo(() => allowlistData?.ipAccessList ?? [], [allowlistData?.ipAccessList])
  const hasAnywhereCidr = useMemo(
    () => allowedAccessCidrs.some(({ cidrNotation }) => cidrNotation === anywhereCidr),
    [allowedAccessCidrs]
  )

  const handleOpenVpcPeeringDetail = (vpcPeering: Nextgenv1beta2VpcPeering) => {
    setSelectedVpcPeering(vpcPeering)
  }

  const handleCloseVpcPeeringDetail = () => {
    setSelectedVpcPeering(null)
  }

  const { open: openSupport } = useRequestSupport()

  const handlePaginationChange = (updater: typeof pagination | ((prev: typeof pagination) => typeof pagination)) => {
    setPagination((prev) => {
      const next = typeof updater === 'function' ? updater(prev) : updater

      if (next.pageSize !== prev.pageSize) {
        return { pageIndex: 0, pageSize: next.pageSize }
      }

      if (next.pageIndex === 0 || pageTokens[next.pageIndex] !== undefined) {
        return next
      }

      return prev
    })
  }

  const columns: MRT_ColumnDef<Nextgenv1beta2VpcPeering>[] = [
    {
      header: 'Peering Connection ID',
      accessorFn: (row) => (
        <Typography
          c="peacock.7"
          component="button"
          type="button"
          onClick={() => handleOpenVpcPeeringDetail(row)}
          sx={{
            cursor: 'pointer',
            background: 'transparent',
            border: 0,
            padding: 0,
            textAlign: 'left'
          }}
        >
          {row.vpcPeeringId || '-'}
        </Typography>
      ),
      id: 'peeringConnectionId',
      mantineTableHeadCellProps: {
        pl: 'md'
      },
      mantineTableBodyCellProps: {
        pl: 'md'
      },
      size: 240
    },
    {
      header: 'Status',
      accessorFn: (row) => <VpcPeeringStatusBadge status={row.state} />,
      id: 'status'
    },
    {
      header: 'Your VPC Region',
      accessorKey: 'customerRegionId'
    },
    {
      header: 'Your VPC ID',
      accessorKey: 'customerVpcId'
    },
    {
      header: 'Your Account Id',
      accessorKey: 'customerAccountId'
    },
    {
      header: 'Your VPC CIDR',
      accessorKey: 'customerVpcCidr'
    }
  ]

  return (
    <Paper withBorder p="xl" data-testid="byoc-vpc-peering-panel">
      <Stack>
        <BlockHeader
          heading="AWS VPC Peering"
          desc={
            <Box>
              VPC peering creates a private connection between your VPC and TiDB Cloud, allowing the instance to be
              accessed privately without using the public internet. To ensure a secure connection, create VPC peering
              before your first connection to the instance. For new VPC peering requests,{' '}
              <a
                onClick={() => {
                  openSupport()
                }}
              >
                contact TiDB Support
              </a>
              .
            </Box>
          }
        />
        <BlockHeader
          heading="Allowed Access CIDR"
          desc="Define which IP ranges can access your cluster through VPC peering. These CIDR rules are shared by all VPC peering connections."
          headingProps={{
            variant: 'title-md'
          }}
          rightSection={
            <ReasonHoverHint reasons={[accessDeniedReason, notReadyReason]}>
              {({ matched }) => (
                <Button variant="default" size="sm" disabled={matched} onClick={cidrModalHandlers.open}>
                  {allowedAccessCidrs.length ? 'Edit' : 'Add'} CIDR
                </Button>
              )}
            </ReasonHoverHint>
          }
        />
        {allowedAccessCidrs.length === 0 ? (
          <Alert icon={<IconInfoCircle />}>
            For security reasons, all traffic from the peer VPC is denied by default, regardless of the VPC Peering
            status. You must configure the allowed subnet to sync access rules to the Private NLB's Security Group.
            Please provide your app's subnet CIDR to enable traffic flow via the peering connection.
          </Alert>
        ) : hasAnywhereCidr ? (
          <Alert color="yellow" icon={<IconAlertTriangle size={14} />}>
            Global Access for VPC peering is enabled. This allows traffic from all VPCs that can reach this NLB via
            peering. The <b>0.0.0.0/0</b> rule is applied and overrides existing CIDR restrictions. Existing CIDR rules
            are preserved but temporarily ignored.
          </Alert>
        ) : (
          <>
            <Group gap={4}>
              {allowlistData?.ipAccessList?.map((cird, idx) => {
                return (
                  <Badge key={idx} color="carbon" bg="carbon.3" variant="outline" c="carbon.8" fw={500} tt="none">
                    <Group gap={4}>
                      {cird.cidrNotation}
                      {cird.cidrNotation === anywhereCidr && (
                        <HoverCard width={320} shadow="md">
                          <HoverCard.Target>
                            <IconAlertTriangle size={14} c="yellow" />
                          </HoverCard.Target>
                          <HoverCard.Dropdown>
                            <Typography variant="body-sm" c="carbon.8">
                              Global access is enabled. All reachable peered VPCs can access this cluster. Disable
                              0.0.0.0/0 to restore the previous CIDR restrictions.
                            </Typography>
                          </HoverCard.Dropdown>
                        </HoverCard>
                      )}
                    </Group>
                  </Badge>
                )
              })}
            </Group>
          </>
        )}

        {(isFetching || vpcPeerings.length > 0) && (
          <ProTable
            columns={columns}
            data={vpcPeerings}
            loading={isFetching}
            emptyMessage="No Data"
            manualPagination
            enablePagination
            state={{ pagination }}
            onPaginationChange={handlePaginationChange}
            rowCount={data?.totalSize || 0}
            pagination={{
              showRowsPerPage: true,
              showTotal: true
            }}
          />
        )}
      </Stack>

      <AddAllowedAccessCidrModal
        tidbId={tidbId}
        cidrList={allowedAccessCidrs}
        opened={cidrModalOpened}
        onClose={cidrModalHandlers.close}
        onConfirm={() => {
          cidrModalHandlers.close()
          refetchAllowlist()
        }}
      />

      <Drawer
        title="AWS VPC Peering Detail"
        size={560}
        position="right"
        opened={!!selectedVpcPeering}
        onClose={handleCloseVpcPeeringDetail}
      >
        <Stack gap="lg" pr={160}>
          <Group justify="space-between" align="flex-start" wrap="nowrap">
            <Typography variant="body-md" c="carbon.7" fw={500}>
              Peering Connection ID
            </Typography>
            <Typography variant="body-md" c="carbon.9" ta="right">
              {selectedVpcPeering?.vpcPeeringId || '-'}
            </Typography>
          </Group>
          <Group justify="space-between" align="center" wrap="nowrap">
            <Typography variant="body-md" c="carbon.7" fw={500}>
              Status
            </Typography>
            {selectedVpcPeering ? <VpcPeeringStatusBadge status={selectedVpcPeering.state} /> : null}
          </Group>
        </Stack>

        <Card bg="carbon.2" p="xl" radius="md" mt="xl" withBorder={false}>
          <Group align="flex-start" grow wrap="nowrap">
            <Stack gap="lg">
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  TiDB Cloud VPC Region
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.tidbCloudRegionId || '-'}
                </Typography>
              </div>
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  TiDB Cloud VPC ID
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.tidbCloudVpcId || '-'}
                </Typography>
              </div>
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  TiDB Cloud AWS Account ID
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.tidbCloudAccountId || '-'}
                </Typography>
              </div>
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  TiDB Cloud VPC CIDR
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.tidbCloudVpcCidr || '-'}
                </Typography>
              </div>
            </Stack>

            <Stack
              gap="lg"
              pl="xl"
              sx={(theme) => ({
                borderLeft: `1px solid ${theme.colors['carbon'][4]}`
              })}
            >
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  Your VPC Region
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.customerRegionId || '-'}
                </Typography>
              </div>
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  Your VPC ID
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.customerVpcId || '-'}
                </Typography>
              </div>
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  Your Account ID
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.customerAccountId || '-'}
                </Typography>
              </div>
              <div>
                <Typography variant="body-sm" c="carbon.7" mb="xs">
                  Your VPC CIDR
                </Typography>
                <Typography variant="body-md" c="carbon.9" fw={500}>
                  {selectedVpcPeering?.customerVpcCidr || '-'}
                </Typography>
              </div>
            </Stack>
          </Group>
        </Card>
      </Drawer>
    </Paper>
  )
})
