import { Box, ButtonProps, Typography, Button, Flex, List, HoverCard } from '@tidbcloud/uikit'
import { CSSObject } from '@tidbcloud/uikit/emotion'
import { mergeSxList } from '@tidbcloud/uikit/utils'
import React, { useState } from 'react'

import TimeComponent from 'dbaas/components/TimeComponent'
import { useAccessCheck } from 'dbaas/contexts/access-control'
import { CentralUserProfileOrgOrgTag } from 'dbaas/services/account/interface'
import { FormsBindedSupportPlan, FormsSupportPlan } from 'dbaas/services/billing/interface'
import useStores from 'dbaas/stores/useStores'
import countriesData from 'dbaas/utils/countriesData'
import { precision } from 'dbaas/utils/format'
import { eventTracking } from 'dbaas/utils/tracking'

import { mayParseFloat } from '../../Billing/CostExplorer/utils'

export enum PlanLevels {
  BASIC = 'Basic',
  // deprecated
  STANDARD = 'Standard',
  DEVELOPER = 'Developer',
  ENTERPRISE = 'Enterprise',
  PREMIUM = 'Premium'
}

export enum PlanCostType {
  FIXED_PRICE = 'fixed_price',
  PERCENTAGE_PRICE = 'percentage_price',
  TIERED_PRICE = 'tiered_price'
}

interface PlanFeature {
  title: string
  features: (React.ReactNode | boolean)[]
}

export interface PlanTier {
  title: string
  titleTips?: string
  subtitle: string
  intro: string
  level: PlanLevels
  price: React.ReactNode
  withoutUnit?: boolean
  pricingTips?: React.ReactNode
  features: PlanFeature[]
  contentStyles?: CSSObject
  button: {
    tips?: string
    text: string
    link?: string
    external?: boolean
    onClick?: () => void
    disabled?: boolean
  } & ButtonProps
}

export const useContactUs = () => {
  const {
    store: { userProfile }
  } = useStores()
  const params = [
    { key: 'company', value: userProfile.company },
    { key: 'firstname', value: userProfile.first_name },
    { key: 'lastname', value: userProfile.last_name },
    { key: 'email', value: userProfile.email },
    { key: 'phone', value: userProfile.phone_number },
    {
      key: 'contact_country',
      value:
        countriesData.find((it) => {
          return it.value === userProfile.country
        })?.text || ''
    }
  ]
    .map((it) => {
      return `${it.key}=${encodeURIComponent(it.value || '')}`
    })
    .join('&')
  return `https://en.pingcap.com/contact-us/?${params}`
}

export const PlanFeatureNames = {
  INITIAL_RESPONSE_TIME: 'Initial Response Time',
  SERVICES: 'Services',
  CUSTOMER_RESOURCE: 'Customer Resource'
} as const

export const PlanFeaturesMap = {
  [PlanFeatureNames.INITIAL_RESPONSE_TIME]: ['S1', 'S2', 'S3', 'S4'],
  [PlanFeatureNames.SERVICES]: [
    'Billing and Account Support ',
    'Ticket-based Technical Support',
    'End-to-end Database Guidance',
    'Connected: AI Chat in IM',
    'Connected: IM Subscription for TiDB Cloud Alerts',
    'Connected: IM Subscription for Support Ticket Updates',
    'Connected: IM Ticket creation',
    'Connected: Clinic Service for Advanced Monitoring',
    'Connected: IM Interaction for Support Tickets',
    'Technical Account Management'
  ],
  [PlanFeatureNames.CUSTOMER_RESOURCE]: ['Documentations', 'FAQ', 'Community Workspace', 'TiDB.AI', 'Knowledge Base']
} as const

const LEVEL_MAP = {
  [PlanLevels.BASIC]: 1,
  [PlanLevels.STANDARD]: 2,
  [PlanLevels.DEVELOPER]: 2,
  [PlanLevels.ENTERPRISE]: 3,
  [PlanLevels.PREMIUM]: 4
} as const

export const PlanFeatures = Object.keys(PlanFeaturesMap).map((key) => ({
  title: key,
  items: PlanFeaturesMap[key] as string[]
}))

export interface PurchaseParams {
  level: string
  action?: 'downgrade'
}

export const useOpenPurchase = () => {
  const [purchaseParams, setPurchaseParams] = useState<{ opened: boolean } & PurchaseParams>({
    opened: false,
    level: '',
    action: undefined
  })

  return {
    purchaseParams,
    openPurchase: (params: PurchaseParams) => {
      setPurchaseParams({ ...params, opened: true })
    },
    closePurchase: () => {
      setPurchaseParams({ opened: false, level: '', action: undefined })
    }
  }
}

export const usePlanTiers = (
  bindedPlan: FormsBindedSupportPlan,
  publicPlan: Record<string, FormsSupportPlan>,
  data: {
    isMSPCustomer?: boolean
    eligibleForFreeTrial?: boolean
    onPurchaseClick: (params: PurchaseParams) => void
    orgTag?: CentralUserProfileOrgOrgTag
    disabled?: boolean
    titleTips?: Record<string, string>
  }
) => {
  const contactLink = useContactUs()
  const isActive = bindedPlan.level !== PlanLevels.BASIC
  const { isMSPCustomer, eligibleForFreeTrial, onPurchaseClick, orgTag, disabled: actionDisabled, titleTips } = data

  const actionAccessible = useAccessCheck('BillingPaymentCreation')

  const developerPlan = publicPlan[PlanLevels.DEVELOPER]

  const getPricingTips = (currentPlan: FormsSupportPlan | undefined) => {
    return currentPlan?.type === PlanCostType.PERCENTAGE_PRICE
      ? `${percentagePriceExtra(currentPlan.fixed_charge_price, currentPlan.support_price_percentage)}`
      : ''
  }

  const shouldDowngrade = (currentPlan: PlanTier) => {
    if (LEVEL_MAP[currentPlan.level] < LEVEL_MAP[bindedPlan.level || '']) {
      return true
    }
    return false
  }

  const upgradeTips = 'Please contact the Owner or Billing Manager to upgrade.'
  const downgradeTips = 'Please contact the Owner or Billing Manager to downgrade.'

  const contentStyles: CSSObject | undefined = isMSPCustomer
    ? {
        paddingBottom: 36
      }
    : undefined
  const actionEnabledButtonProps: ButtonProps = {
    variant: 'default',
    // color: 'peacock',
    // bg: 'peacock.1',
    sx: isMSPCustomer
      ? {
          display: 'none'
        }
      : undefined
  }
  const disabledButtonProps: ButtonProps = {
    variant: 'default',
    c: 'carbon.6',
    bg: 'carbon.2',
    sx: (theme) => ({ '&[data-disabled]': { borderColor: theme.colors.carbon[5] } })
  }

  const defaultButtonProps: ButtonProps =
    actionAccessible && !actionDisabled ? actionEnabledButtonProps : disabledButtonProps

  const getPriceDetails = (
    tier: FormsSupportPlan | undefined
  ): { subtitle?: string; price: React.ReactNode; pricingTips?: React.ReactNode; withoutUnit?: boolean } => {
    if (tier?.level === bindedPlan?.level && orgTag !== 'msp_customer') {
      if (bindedPlan.is_in_free_trial) {
        return {
          subtitle: '30-day free trial',
          price: (
            <Box>
              <Typography variant="headline-lg" fz={28} display="inline-block">
                Free
              </Typography>
              <Typography variant="body-lg" display="inline-block" ml={4}>
                {bindedPlan.rest_days_of_free_trial} day{(bindedPlan.rest_days_of_free_trial || 0) > 1 ? 's' : ''} left
              </Typography>
            </Box>
          ),
          pricingTips: '',
          withoutUnit: true
        }
      }
      if (bindedPlan?.type === PlanCostType.TIERED_PRICE) {
        return {
          subtitle: 'Greater of',
          price: bindedPlan.fixed_charge_price,
          pricingTips: (
            <List styles={{ root: { listStyle: 'none' } }}>
              {bindedPlan.tiered_price_rules?.map((it, index, array) => {
                const content = it.upper_bound
                  ? `${convertPercentage(it.support_price_percentage || '')}% on the ${index ? 'next' : 'first'} $${
                      index !== 0 && index !== array.length - 1
                        ? mayParseFloat(it.upper_bound) - mayParseFloat(it.lower_bound)
                        : it.upper_bound
                    }`
                  : `${convertPercentage(it.support_price_percentage || '')}% on usage over $${it.lower_bound} per month`
                return (
                  <List.Item key={index.toString()} fz={13}>
                    {content}
                  </List.Item>
                )
              })}
            </List>
          )
        }
      }
    }

    return {
      price: tier?.fixed_charge_price,
      pricingTips: getPricingTips(tier)
    }
  }
  const planTiers: PlanTier[] = [
    {
      title: 'Basic',
      subtitle: 'Free',
      titleTips: titleTips?.[PlanLevels.BASIC],
      intro:
        'Great for personal starter projects, this plan connects you with an active community and AI-powered assistance for essential support needs.',
      level: PlanLevels.BASIC,
      price: '0',
      features: [
        {
          title: PlanFeatureNames.INITIAL_RESPONSE_TIME,
          features: []
        },
        {
          title: PlanFeatureNames.SERVICES,
          features: [true]
        },
        {
          title: PlanFeatureNames.CUSTOMER_RESOURCE,
          features: [true, true, true, true]
        }
      ],
      contentStyles,
      button: {
        ...defaultButtonProps,
        ...(actionDisabled ? disabledButtonProps : {}),
        disabled: actionDisabled,
        text: actionDisabled ? 'Basic' : 'Upgrade'
      }
    },
    {
      title: 'Developer',
      subtitle: 'Starting at',
      titleTips: titleTips?.[PlanLevels.DEVELOPER],
      intro:
        'Ideal for development and testing phases, offering direct connections with unlimited access to tech support, to kickstart your cloud journey.',
      level: PlanLevels.DEVELOPER,
      ...getPriceDetails(developerPlan),
      features: [
        {
          title: PlanFeatureNames.INITIAL_RESPONSE_TIME,
          features: ['S1: 4 business hours', 'S2: 8 business hours', 'S3: 12 business hours', 'S4: 24 business hours']
        },
        {
          title: PlanFeatureNames.SERVICES,
          features: [true, true, true]
        },
        {
          title: PlanFeatureNames.CUSTOMER_RESOURCE,
          features: [true, true, true, true, true]
        }
      ],
      contentStyles,
      button: {
        ...defaultButtonProps,
        text: eligibleForFreeTrial ? 'Start 30-Day Free Trial' : 'Upgrade',
        disabled: !actionAccessible || actionDisabled,
        tips: !actionAccessible ? upgradeTips : '',
        onClick: () => {
          onPurchaseClick({ level: PlanLevels.DEVELOPER })
          eventTracking('Select Standard Plan')
        }
      }
    },
    {
      title: 'Enterprise',
      subtitle: 'Starting at',
      titleTips: titleTips?.[PlanLevels.ENTERPRISE],
      intro:
        'Designed for production workloads, this plan connects your operations with advanced monitoring, prompt alerts, and fast 7x24 response times for a seamless experience.',
      level: PlanLevels.ENTERPRISE,
      ...getPriceDetails(publicPlan[PlanLevels.ENTERPRISE]),
      features: [
        {
          title: PlanFeatureNames.INITIAL_RESPONSE_TIME,
          features: ['S1: 1 hour', 'S2: 2 hours', 'S3: 8 business hours', 'S4: 24 business hours']
        },
        {
          title: PlanFeatureNames.SERVICES,
          features: [true, true, true, true, true, true, true, true]
        },
        {
          title: PlanFeatureNames.CUSTOMER_RESOURCE,
          features: [true, true, true, true, true]
        }
      ],
      contentStyles,
      button: {
        ...defaultButtonProps,
        text: 'Upgrade',
        disabled: !actionAccessible || actionDisabled,
        tips: !actionAccessible ? upgradeTips : '',
        onClick: () => {
          onPurchaseClick({ level: PlanLevels.ENTERPRISE })
          eventTracking('Contact us for Enterprise plan')
        }
      }
    },
    {
      title: 'Premium',
      subtitle: 'For Pricing',
      titleTips: titleTips?.[PlanLevels.PREMIUM],
      intro:
        'Built for enterprises with mission-critical workloads, offering the fastest response times, proactive support, and dedicated connections through named Technical Account Managers.',
      level: PlanLevels.PREMIUM,
      withoutUnit: true,
      price: "Let's Chat",
      pricingTips: 'Monthly cost is determined by the usage.',
      features: [
        {
          title: PlanFeatureNames.INITIAL_RESPONSE_TIME,
          features: ['S1: 30 minutes', 'S2: 1 hour', 'S3: 4 business hours', 'S4: 24 business hours']
        },
        {
          title: PlanFeatureNames.SERVICES,
          features: [true, true, true, true, true, true, true, true, true, true]
        },
        {
          title: PlanFeatureNames.CUSTOMER_RESOURCE,
          features: [true, true, true, true, true]
        }
      ],
      contentStyles,
      button: {
        ...actionEnabledButtonProps,
        ...(actionDisabled ? disabledButtonProps : {}),
        text: 'Contact Sales',
        link: contactLink,
        disabled: actionDisabled,
        external: true,
        onClick: () => {
          if (isActive) {
            return
          }
          eventTracking('Contact us for Premium plan')
        }
      }
    }
  ]

  return planTiers.map((tier) => {
    if (shouldDowngrade(tier)) {
      tier.button.variant = 'outline'
      tier.button.text = 'Downgrade'
      tier.button.onClick = () => {
        onPurchaseClick({ level: tier.level, action: 'downgrade' })
        eventTracking('Click to Downgrade', { from: bindedPlan.level, to: tier.level })
      }

      if (tier.button.disabled && !actionAccessible) {
        tier.button.tips = downgradeTips
      }

      // for private plan should contact sales for downgrade
      if (!bindedPlan.public) {
        tier.button.external = true
        tier.button.text = 'Contact Sales for Downgrade'
        tier.button.link = contactLink
        tier.button.onClick = () => {
          eventTracking('Contact Sales for Downgrade', {
            from: bindedPlan.level,
            to: tier.level
          })
        }
      }
    } else {
      if (!bindedPlan.public && tier.button.text === 'Upgrade') {
        tier.button.text = 'Contact Sales for Upgrade'
        tier.button.external = true
        tier.button.link = contactLink
        tier.button.onClick = () => {
          eventTracking('Contact Sales for Upgrade', {
            from: bindedPlan.level,
            to: tier.level
          })
        }
      }
    }
    return tier
  })
}

export const PlansContent: React.FC<
  React.PropsWithChildren<{
    tier: PlanTier
    active?: boolean
    activeDate?: string
    tipsWidth?: string | number
  }>
> = ({ tier, active, activeDate }) => {
  const onClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = (e) => {
    if (tier.button.disabled) {
      e.preventDefault()
      return
    }
    tier.button.onClick?.()
  }

  const renderLink = () => {
    const defaultProps: ButtonProps = {
      fz: 14,
      fw: 600,
      lh: '20px',
      h: 32,
      px: 12,
      w: 'fit-content',
      ...tier.button,
      variant: tier.button.variant,
      sx: mergeSxList([
        (theme) => {
          return {
            ':hover': {
              textDecoration: 'none'
            },
            '&[data-disabled]': {
              color: `${theme.colors.carbon[3]}`,
              backgroundColor: `${theme.colors.carbon[6]}`,
              pointerEvents: tier.button.tips ? 'auto' : undefined
            }
          }
        },
        tier.button.sx
      ])
    }

    let LinkButton = (
      <Button {...defaultProps} disabled={tier.button.disabled} onClick={onClick}>
        {tier.button.text}
      </Button>
    )

    if (active && activeDate) {
      if (tier.level === PlanLevels.BASIC) {
        return <Box h={32}></Box>
      }
      return (
        <Typography variant="title-lg" c="carbon.9" fw={600} h={32} lh={'32px'} ta="left">
          Activation date: <TimeComponent time={activeDate} format="YYYY-MM-DD"></TimeComponent>
        </Typography>
      )
    }
    if (tier.button.external) {
      LinkButton = (
        <Button
          {...defaultProps}
          component="a"
          href={tier.button.link}
          target="_blank"
          rel="noreferrer"
          onClick={onClick}
          disabled={tier.button.disabled}
        >
          {tier.button.text}
        </Button>
      )
    }

    return tier.button.tips ? (
      <HoverCard withArrow width={240} position="top">
        <HoverCard.Target>
          <Box w="fit-content">{LinkButton}</Box>
        </HoverCard.Target>
        <HoverCard.Dropdown>{tier.button.tips}</HoverCard.Dropdown>
      </HoverCard>
    ) : (
      LinkButton
    )
  }

  const PriceItem = (
    <Typography variant="headline-lg" fz={28}>
      {tier.price}
    </Typography>
  )

  return (
    <Box
      sx={mergeSxList([
        () => ({
          display: 'flex',
          flexDirection: 'column',
          flex: 1,
          padding: '16px',
          height: '100%'
        }),
        tier.contentStyles
      ])}
    >
      <Typography variant="body-lg" c="carbon.9" ta="left">
        {tier.subtitle}
      </Typography>
      <Flex align="flex-end" mt={4}>
        {tier.withoutUnit ? (
          PriceItem
        ) : (
          <>
            <Typography variant="headline-lg" fw={400}>
              $
            </Typography>
            {PriceItem}
            <Typography variant="headline-lg" fw={400}>
              /
            </Typography>
            <Typography variant="title-lg" fw={400}>
              month
            </Typography>
          </>
        )}
      </Flex>
      <Typography variant="body-sm" fz={13} sx={{ flex: 1 }} lh="16px" mt={16} mb={24} ta="left" miw={180} maw={300}>
        {tier.pricingTips}
      </Typography>
      {renderLink()}
    </Box>
  )
}

export const convertPercentage = (percentage: string) => {
  if (!percentage) {
    return '-'
  }
  return precision(parseFloat(percentage) * 100).toString()
}

export const percentagePriceExtra = (price?: string, percentage?: string) => {
  return `Monthly cost is based on the greater of $${price} or ${convertPercentage(
    percentage || ''
  )}% of total monthly charges.`
}
