import { ActionIcon, Menu, notifier } from '@tidbcloud/uikit'
import { Box, Button, Badge, Flex, Grid, Modal, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { Form } from '@tidbcloud/uikit/biz'
import { IconDotsHorizontal } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'
import { useForm } from 'react-hook-form'

import { AccessGuard, useAccessCheck } from 'dbaas/contexts/access-control'
import { PageShell } from 'dbaas/layouts/v5/page'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import { deleteVercelConnection, useGetAllVercelConnections, deleteVercelDataappLink } from 'dbaas/services/vercel'
import { VercelTiDBVercelConnectionVO } from 'dbaas/services/vercel/interface'
import useQuery from 'dbaas/utils/useQuery'

import EnvTips from './EnvTips'
import Footer from './Footer'
import Header from './Header'
import { useAddVercelLink, CONFIG_DEFAULT_VALUES } from './helpers'
import Step1 from './Step1'
import Step2 from './Step2'
import { VercelntegrationFormValues, AppType, ENV_LIST } from './types.d'

interface VercelConfigurationTableProps {
  data: VercelTiDBVercelConnectionVO[]

  /**
   * Refresh data after operations.
   */
  refresh: () => void
  isLoadingList: boolean
}

export const VercelConfigurationTable = ({ data, refresh, isLoadingList }: VercelConfigurationTableProps) => {
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(false)
  const [connection, setConnection] = useState<VercelTiDBVercelConnectionVO | null>(null)

  const handleOpenRemoveModal = (connection: VercelTiDBVercelConnectionVO) => () => {
    setConnection(connection)
    setOpen(true)
  }

  const handleRemoveConnection = async () => {
    setLoading(true)

    const {
      target_type,
      tidb_org_id,
      tidb_project_id,
      vercel_project_id,
      vercel_project_name,
      target_id = ''
    } = connection!

    try {
      if (target_type === 'cluster') {
        await deleteVercelConnection(tidb_org_id, tidb_project_id, target_id, {
          vercel_project_id,
          vercel_project_name
        })
      } else {
        await deleteVercelDataappLink(tidb_org_id, tidb_project_id, target_id, {
          vercel_project_id,
          vercel_project_name
        })
      }

      refresh()
      setOpen(false)
      setLoading(false)
    } catch (err) {
      notifier.error(getErrorMessage(err))
      setLoading(false)
    }
  }

  const columns = useMemo<MRT_ColumnDef<VercelTiDBVercelConnectionVO>[]>(
    () => [
      {
        header: 'Vercel Project',
        accessorKey: 'vercel_project_name'
      },
      {
        header: 'TiDB Cloud Organization',
        size: 200,
        accessorKey: 'tidb_org_name'
      },
      {
        header: 'TiDB Cloud Project',
        accessorKey: 'tidb_project_name'
      },
      {
        header: 'Connection Type',
        accessorFn: (column) => (
          <Typography>
            {column.target_type === 'cluster' ? 'Cluster' : 'Data App'} / {column.target_name}
          </Typography>
        )
      },
      {
        header: 'Branching',
        accessorFn: (column) => (
          <Badge color={column.branch_enabled ? 'green' : 'carbon.6'} variant="dot" size="lg" sx={{ padding: 0 }}>
            {column.branch_enabled ? 'Enabled' : 'Disabled'}
          </Badge>
        )
      },
      {
        header: 'Action',
        accessorFn: (column) => (
          <AccessGuard
            id="ProjectIntegrationAction"
            scopeProps={{
              projectId: column.tidb_project_id
            }}
            fallback="-"
          >
            <Menu position="bottom">
              <Menu.Target>
                <ActionIcon size={32}>
                  <IconDotsHorizontal size={16} />
                </ActionIcon>
              </Menu.Target>
              <Menu.Dropdown>
                <Menu.Item onClick={handleOpenRemoveModal(column)}>Remove</Menu.Item>
              </Menu.Dropdown>
            </Menu>
          </AccessGuard>
        )
      }
    ],
    []
  )

  return (
    <>
      <ProTable
        columns={columns}
        loading={isLoadingList}
        data={data}
        emptyMessage="No Data"
        mantinePaperProps={{
          sx: {
            overflow: 'hidden'
          },
          mx: 24
        }}
      />

      <Modal size={500} centered opened={open} title="Remove connection" onClose={() => setOpen(false)}>
        <Typography mb={24}>The operation will take effect immediately.</Typography>
        <Flex justify="flex-end" gap={24}>
          <Button
            variant="default"
            onClick={() => setOpen(false)}
            disabled={loading}
            data-mp-event="mp-cancel-1691461012460"
          >
            Cancel
          </Button>
          <Button
            variant="light"
            data-mp-event="Vercel Remove Connection Button Clicked"
            color="red"
            loading={loading}
            onClick={handleRemoveConnection}
          >
            Confirm
          </Button>
        </Flex>
      </Modal>
    </>
  )
}

const Configuration = () => {
  const [selectedProject, setSelectedProject] = useState('')
  const actionEnabled = useAccessCheck('ProjectIntegrationAction', {
    projectId: selectedProject
  })

  const query = useQuery()
  const { submit } = useAddVercelLink()

  const configurationID = query.get('configurationId')! // Vercel will ensure that this query param exists.
  const [type, setType] = useState('cluster')
  const [vercelPros, setVercelPros] = useState<string[]>([])
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(false)
  const [frameworkType, setFrameworkType] = useState(ENV_LIST[0].value)

  const handleSubmit = (values: VercelntegrationFormValues) => {
    setLoading(true)
    submit(
      values,
      type,
      () => {
        setOpen(false)
        setLoading(false)
        connectionList.refetch()
      },
      () => {
        setLoading(false)
      }
    )
  }

  const connectionList = useGetAllVercelConnections(configurationID, {
    query: {
      enabled: !!configurationID,
      refetchInterval: false,
      refetchOnWindowFocus: false,
      onError: (err) => {
        notifier.error(getErrorMessage(err))
      }
    }
  })

  const form = useForm({
    mode: 'all',
    reValidateMode: 'onChange',
    defaultValues: CONFIG_DEFAULT_VALUES
  })

  return (
    <PageShell
      bodyProps={{
        pt: 0,
        pb: 0,
        pl: 0,
        pr: 0,
        p: 0
      }}
    >
      <Box>
        <Flex gap={24} direction="column" h={`calc(100vh - 81px)`} sx={{ overflowY: 'auto', paddingBottom: 24 }}>
          <Header />
          <Box
            sx={(theme) => ({
              borderRadius: theme.defaultRadius,
              maxWidth: 1000,
              margin: '40px auto'
            })}
          >
            <VercelConfigurationTable
              data={connectionList.data?.connections || []}
              isLoadingList={connectionList.isLoading || connectionList.isRefetching}
              refresh={() => connectionList.refetch()}
            />

            {!open && (
              <Flex justify="flex-end" align="center" mt={40}>
                <Button size="md" data-mp-event="Add Link Button Clicked " onClick={() => setOpen(true)}>
                  Add Link
                </Button>
              </Flex>
            )}
          </Box>

          {open && (
            <Form form={form} withActions={false} layout="none" onSubmit={handleSubmit}>
              <Grid
                gutter={48}
                maw={1000}
                m="0 auto"
                sx={(theme) => ({
                  border: `1px solid ${theme.colors.carbon[4]}`,
                  borderRadius: theme.defaultRadius,
                  padding: 24
                })}
              >
                <Grid.Col
                  span={6}
                  sx={(theme) => ({
                    padding: '24px 24px 0',
                    borderRight: `1px solid ${theme.colors.carbon[4]}}`
                  })}
                >
                  <Step1 vercelProChanged={(values) => setVercelPros(values)} />
                  <EnvTips env={frameworkType} type={type as AppType} />
                </Grid.Col>
                <Grid.Col
                  span={6}
                  sx={() => ({
                    padding: '24px 24px 0'
                  })}
                >
                  <Step2
                    hasTips={false}
                    onProjectChange={setSelectedProject}
                    onTypeChange={(type) => setType(type)}
                    onFrameworkChange={(type) => setFrameworkType(type)}
                  />

                  <Flex align="center" justify="space-between" gap={24} my={24}>
                    <Button
                      variant="default"
                      sx={() => ({ flex: 1 })}
                      onClick={() => setOpen(false)}
                      data-mp-event="mp-cancel-1691461012463"
                    >
                      Cancel
                    </Button>
                    <Button
                      type="submit"
                      data-mp-event="Add Link Confirm Button Clicked"
                      sx={() => ({ flex: 1 })}
                      disabled={!actionEnabled || !vercelPros.length || !form.getValues('cluster')}
                      loading={loading}
                    >
                      Add Link
                    </Button>
                  </Flex>
                </Grid.Col>
              </Grid>
            </Form>
          )}
        </Flex>
        <Footer />
      </Box>
    </PageShell>
  )
}

export default observer(Configuration)
