import { Divider, List, Flex, Typography, Alert, Box, Button, Group, Badge } from '@tidbcloud/uikit'
import { FormTextInput, FormSelect } from '@tidbcloud/uikit/biz'
import { IconInfoCircle, IconLinkExternal01 } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import React from 'react'

import { CardContainer as Card, ActionSteps, DeleteModal } from 'dbaas/components/IntegrationCard'
import { CardForm } from 'dbaas/components/IntegrationCard/form'
import { VendorLogo } from 'dbaas/components/Logo'
import { AccessGuard, useAccessCheck } from 'dbaas/contexts/access-control'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import type { CentralIntegrationStatusResp, CentralNewrelicSite } from 'dbaas/services'
import {
  CentralIntegrationPayload,
  CentralIntegrationType,
  CentralUserProject,
  validateNewrelicAPIKey
} from 'dbaas/services'
import { createIntegration, deleteIntegration } from 'dbaas/services'
import {
  integrationServiceCreateIntegration,
  integrationServiceDeleteIntegration,
  integrationServiceValidateNewrelicAPIKey
} from 'dbaas/services/metricsIntegration'
import {
  IntegrationServiceDeleteIntegrationType,
  V1IntegrationPayload,
  V1IntegrationStatusResp,
  V1IntegrationType,
  V1NewrelicSite
} from 'dbaas/services/metricsIntegration/interface'
import useStores from 'dbaas/stores/useStores'
import { len100StrRegexp } from 'dbaas/utils/regex'
import { eventTracking } from 'dbaas/utils/tracking'

type NewRelicFormSite = '' | CentralNewrelicSite | V1NewrelicSite

const newRelicSiteLabelMap = {
  NEWRELIC_SITE_US_OTLP: 'US',
  NEWRELIC_SITE_EU_OTLP: 'EU',
  NEWRELIC_SITE_UNSPECIFIED: ''
} as const satisfies Record<Exclude<NewRelicFormSite, ''>, string>

const newRelicSiteOptions = Object.entries(newRelicSiteLabelMap)
  .filter(([, label]) => {
    return !!label
  })
  .map(([value, label]) => {
    return {
      value,
      label
    }
  })

const getNewRelicSiteLabel = (site?: NewRelicFormSite) => {
  if (!site) {
    return ''
  }
  return newRelicSiteLabelMap[site]
}

const stepTexts: Record<ActionSteps, string> = {
  initial: 'Test Integration',
  passed: 'Confirm',
  confirmed: 'Confirmed'
}

type NewRelicFormData = {
  newrelic_api_key: string
  newrelic_site: NewRelicFormSite
}

export const NewRelicForm = observer(
  ({
    onCancel,
    projectId,
    onConfirmed,
    cluster
  }: {
    onCancel?: () => void
    projectId: string
    onConfirmed?: () => void
    cluster?: SharedCluster
  }) => {
    const {
      store: { tenantData }
    } = useStores()

    const accessible = useAccessCheck('ProjectIntegrationAction')

    const onTest = (data: NewRelicFormData) => {
      eventTracking('Integration New Relic Test Button Clicked')
      if (cluster) {
        return integrationServiceValidateNewrelicAPIKey(tenantData.id, projectId, cluster.id!, {
          newrelic_api_key: data.newrelic_api_key,
          newrelic_site: data.newrelic_site as V1NewrelicSite
        })
      }
      return validateNewrelicAPIKey(tenantData.id, projectId, {
        newrelic_api_key: data.newrelic_api_key,
        newrelic_site: data.newrelic_site as CentralNewrelicSite
      })
    }

    const onConfirm = (data: NewRelicFormData) => {
      eventTracking('Integration New Relic Confirm Button Clicked')
      if (cluster) {
        return integrationServiceCreateIntegration(tenantData.id, projectId, cluster.id!, {
          type: V1IntegrationType.INTEGRATION_TYPE_NEWRELIC,
          payloads: [V1IntegrationPayload.INTEGRATION_PAYLOAD_METRICS],
          newrelic_api_key: data.newrelic_api_key,
          newrelic_site: data.newrelic_site as V1NewrelicSite
        })
      }
      return createIntegration(tenantData.id, projectId, {
        org_id: tenantData.id,
        project_id: projectId,
        type: CentralIntegrationType.INTEGRATION_TYPE_NEWRELIC,
        payloads: [CentralIntegrationPayload.INTEGRATION_PAYLOAD_METRICS],
        newrelic_api_key: data.newrelic_api_key,
        newrelic_site: data.newrelic_site as CentralNewrelicSite
      })
    }

    const styles = {
      root: {
        display: 'flex',
        alignItems: 'center',
        flexWrap: 'wrap'
      },
      label: {
        minWidth: 144,
        marginBottom: 0
      },
      wrapper: {
        flex: 1
      },
      error: {
        marginLeft: 144,
        width: '100%'
      }
    } as const

    return (
      <CardForm<NewRelicFormData>
        type="New Relic"
        onTest={onTest}
        onConfrim={onConfirm}
        onConfirmed={onConfirmed}
        stepTexts={stepTexts}
        onCancel={onCancel}
        defaultValues={{ newrelic_api_key: '', newrelic_site: '' }}
      >
        {(_, readOnly) => {
          return (
            <>
              <FormTextInput
                name="newrelic_api_key"
                readOnly={readOnly as any} // TODO:
                label="API Key"
                styles={styles}
                disabled={!accessible}
                rules={{
                  required: 'Required',
                  pattern: {
                    value: len100StrRegexp,
                    message: 'New Relic API key is invalid'
                  }
                }}
              />
              <FormSelect
                name="newrelic_site"
                placeholder="Choose Site"
                data={newRelicSiteOptions}
                label="Site"
                readOnly={readOnly as any} // TODO:
                disabled={!accessible}
                styles={{
                  ...styles,
                  root: {
                    display: 'flex',
                    alignItems: 'center',
                    flexWrap: 'wrap',
                    '& > div:first-of-type': {
                      flex: 1
                    }
                  }
                }}
                rules={{
                  required: 'Required'
                }}
              />
            </>
          )
        }}
      </CardForm>
    )
  }
)

export const NewRelicDetail: React.FC<
  React.PropsWithChildren<{
    integration: CentralIntegrationStatusResp | null
    integrationInfoForCluster?: V1IntegrationStatusResp
  }>
> = ({ integration, integrationInfoForCluster }) => {
  return (
    <Box w="50%" m="0 auto" mt={24}>
      <List listStyleType={'none'} withPadding styles={{ item: { marginBottom: 16 } }}>
        <List.Item>
          <Typography w={100} display="inline-block" variant="action-lg" c="carbon.9">
            API Key
          </Typography>
          <Typography ml={64} display="inline-block">
            {integration?.newrelic_masked_api_key || integrationInfoForCluster?.newrelic_masked_api_key}
          </Typography>
        </List.Item>
        <List.Item>
          <Typography w={100} display="inline-block" variant="action-lg" c="carbon.9">
            Site
          </Typography>
          <Typography ml={64} display="inline-block">
            {getNewRelicSiteLabel(integration?.newrelic_site || integrationInfoForCluster?.newrelic_site)}
          </Typography>
        </List.Item>
      </List>
      {(!!integration?.status_reason || !!integrationInfoForCluster?.status_reason) && (
        <Alert icon={<IconInfoCircle size={16} />} color="red">
          {integration?.status_reason || integrationInfoForCluster?.status_reason}
        </Alert>
      )}
    </Box>
  )
}

export const NewRelic: React.FC<
  React.PropsWithChildren<{
    integration: CentralIntegrationStatusResp | null
    integrationInfoForCluster?: V1IntegrationStatusResp
    open?: boolean
    project: CentralUserProject
    onConfirmed?: () => void
    cluster?: SharedCluster
  }>
> = observer(({ integration, integrationInfoForCluster, open = false, project, onConfirmed, cluster }) => {
  const {
    store: { tenantData }
  } = useStores()
  const isClusterLevel = !!cluster

  const onDelete = async () => {
    eventTracking('Integration New Relic Delete Button Clicked')
    if (isClusterLevel) {
      await integrationServiceDeleteIntegration(tenantData.id, project.id, cluster.id!, {
        type: IntegrationServiceDeleteIntegrationType.INTEGRATION_TYPE_NEWRELIC
      })
    } else {
      await deleteIntegration(tenantData.id, project.id, {
        type: CentralIntegrationType.INTEGRATION_TYPE_NEWRELIC
      })
    }
    onConfirmed?.()
  }

  const Content = () => {
    return (
      <Flex sx={{ flex: 1 }} justify="space-between" align="center">
        <Group gap={8}>
          <Typography variant="title-md">Integration to New Relic</Typography>
          {!isClusterLevel && (
            <Badge variant="outline" size="sm" color="carbon" c="carbon.7" fw={500}>
              Preview
            </Badge>
          )}
        </Group>

        {(integration !== null || !!integrationInfoForCluster) && (
          <Flex onClick={(e) => e.stopPropagation()} align="center" gap={16}>
            <Button
              component="a"
              target="_blank"
              variant="subtle"
              href={integration?.newrelic_dashboard_url || integrationInfoForCluster?.newrelic_dashboard_url || ''}
              data-mp-event="Integration New Relic Dashboard Link Clicked"
              rightSection={<IconLinkExternal01 size={18} />}
            >
              Dashboard
            </Button>
            <AccessGuard id="ProjectIntegrationAction">
              <DeleteModal
                title="Delete New Relic Integration"
                content="By clicking delete you will delete the New Relic Integration."
                onSubmit={onDelete}
              />
            </AccessGuard>
          </Flex>
        )}
      </Flex>
    )
  }

  return (
    <Card
      open={open}
      left={<VendorLogo name="newrelic" size={64} />}
      content={<Content />}
      isEmpty={!integration && !integrationInfoForCluster}
      onClick={(status) => eventTracking('Integration New Relic Card Clicked', { closed: status === 'closed' })}
    >
      {(status, setStatus) => {
        if (status === 'detail' && (integration !== null || !!integrationInfoForCluster)) {
          return (
            <>
              <Divider />
              <NewRelicDetail integration={integration} integrationInfoForCluster={integrationInfoForCluster} />
            </>
          )
        }
        if (status === 'editing') {
          return (
            <>
              <Divider />
              <NewRelicForm
                onCancel={() => setStatus('closed')}
                onConfirmed={onConfirmed}
                projectId={project.id}
                cluster={cluster}
              />
            </>
          )
        }
        return null
      }}
    </Card>
  )
})

export default NewRelic
