import { Button, Group, Typography, Flex, Box, Alert, HoverCard, Anchor, notifier, ActionIcon } from '@tidbcloud/uikit'
import { Form, FormSelect, FormTextInput, FormSwitch, FormCheckbox, FormMultiSelect } from '@tidbcloud/uikit/biz'
import { IconInfoCircle } from '@tidbcloud/uikit/icons'
import { useEffect, useMemo, useState } from 'react'
import { useForm, useFormContext } from 'react-hook-form'

import { useHelpCenterContext } from 'dbaas/screens/HelpCenter/context'
import { DATA_SERVICE_BASE_PATH } from 'dbaas/screens/HelpCenter/DataService'
import { UserSetting } from 'dbaas/screens/SqlEditor/types'
import { useUpdateAIUserSetting } from 'dbaas/services'
import { useCreateDataApp } from 'dbaas/services/dataservice'
import { EntityCreateDataAppParam } from 'dbaas/services/dataservice/interface'
import history from 'dbaas/services/history'
import useQuery from 'dbaas/utils/useQuery'

import GithubAuth from '../common/GithubAuth'
import GithubDocument from '../common/GithubDocument'
import { useDataApiContext } from '../context'
import CreateCluster from '../Editor/CreateCluster'
import {
  DATA_APP_NAME_RULES,
  clearCreateFormStorageDatas,
  useFormatClusterList,
  useGithubAuthRequest
} from '../helpers'
import { CreateAppFormValues, DataApp } from '../types'

export const CreateItems = () => {
  const { setValue, getValues, trigger } = useFormContext()
  const { list: clusterList } = useFormatClusterList()
  const query = useQuery()
  const createType = query.get('type')
  const { AISetting, createDataAppFromLogs } = useDataApiContext()
  const [createTypeFromUrl, setCreateTypeFromUrl] = useState<string | null>('')

  useEffect(() => {
    const name = localStorage.getItem('dataapp_create_app_name')
    setValue('app_name', name || 'New App')
    setValue('description', localStorage.getItem('dataapp_create_description'))

    const ids = localStorage.getItem('dataapp_create_app_cluster_ids')
    if (ids) {
      setValue('cluster_ids', JSON.parse(ids))
    }

    setCreateTypeFromUrl(createType)
    const appType = createType === 'chat2data' ? 'chat2query' : 'dataapi'
    setValue('dataAppType', appType)
    history.replace('/project/data-service')
  }, [])

  useEffect(() => {
    if (createDataAppFromLogs) {
      setCreateTypeFromUrl('dataapi')
      setValue('dataAppType', 'dataapi')
    }
  }, [createDataAppFromLogs])

  useEffect(() => {
    const availableClusters = clusterList.filter((v) => !v.disabled)
    if (availableClusters?.length === 1 && !getValues('cluster_ids')) {
      setValue('cluster_ids', [availableClusters[0]?.value])
    }
  }, [clusterList])

  return (
    <Box>
      <Flex align="top" gap={24} mb={24}>
        <FormTextInput
          sx={{
            flex: 2
          }}
          autoComplete="off"
          name="app_name"
          label={<Typography variant="title-md">Data App Name</Typography>}
          maxLength={31}
          placeholder="Data App name"
          rules={DATA_APP_NAME_RULES}
          onChange={(e) => {
            localStorage.setItem('dataapp_create_app_name', e.target.value)
            trigger('app_name')
          }}
        />

        <FormMultiSelect
          data-test-name="cluster-ids"
          styles={() => ({
            root: {
              flex: 3,
              zIndex: 9999,
              width: 0
            },
            label: {
              marginBottom: 8
            },
            pillsList: {
              overflow: 'hidden',
              flexWrap: 'nowrap'
            },
            pill: {
              maxWidth: '30%'
            },
            values: {
              height: 'auto'
            }
          })}
          comboboxProps={{ zIndex: 9999 }}
          label={<Typography variant="title-md">Link Data Sources</Typography>}
          name="cluster_ids"
          data={clusterList.map((v) => ({ ...v }))}
          placeholder="Select one or more clusters as your data source"
          nothingFoundMessage={<CreateCluster />}
          onChange={(val) => {
            localStorage.setItem('dataapp_create_app_cluster_ids', JSON.stringify(val))
          }}
        />
      </Flex>
      <Flex align="top" gap={24} mb={24}>
        {createTypeFromUrl !== 'chat2data' && (
          <Box
            sx={{
              flex: 2
            }}
          >
            <Flex mb={8}>
              <Typography variant="title-md">Data App Type</Typography>
              <HoverCard width={420} position="top" withArrow shadow="md" zIndex={9999}>
                <HoverCard.Target>
                  <ActionIcon aria-label="Info" size={20} ml={4}>
                    <IconInfoCircle size={16} />
                  </ActionIcon>
                </HoverCard.Target>
                <HoverCard.Dropdown>
                  <Typography variant="body-md">
                    <b>Standard Data App:</b> Standard Data App is an ideal choice for creating Data Apps primarily
                    centered around traditional HTTP(S) endpoints, making it a well-rounded option for the most common
                    web services and API use cases.
                  </Typography>
                  <Typography variant="body-md" mt={4}>
                    <b>Chat2Query Data App:</b> Chat2Query Data App enables AI-driven SQL statement generation and
                    execution through user instructions.
                  </Typography>
                </HoverCard.Dropdown>
              </HoverCard>
            </Flex>
            <FormSelect
              name="dataAppType"
              disabled={!!createTypeFromUrl}
              data={[
                {
                  label: 'Standard Data App',
                  value: 'dataapi'
                },
                {
                  label: 'Chat2Query Data App',
                  value: 'chat2query'
                }
              ]}
              comboboxProps={{ zIndex: 9999 }}
            ></FormSelect>
          </Box>
        )}
        <FormTextInput
          sx={{
            flex: 3
          }}
          name="description"
          label={
            <Flex>
              <Typography variant="title-md">Description</Typography>
              <Typography variant="body-lg" c="carbon.7" ml={4}>
                (Optional)
              </Typography>
            </Flex>
          }
          autoComplete="off"
          placeholder="Provide a Data App description (up to 1000 characters)"
          maxLength={1000}
          onChange={(e) => {
            localStorage.setItem('dataapp_create_description', e.target.value)
          }}
        />
      </Flex>

      {getValues('dataAppType') !== 'dataapi' && !AISetting.is_privacy_allowed && (
        <Box>
          <FormCheckbox
            mt={24}
            name="is_privacy_allowed"
            label={
              <Typography variant="label-lg" fw={600}>
                We use AI to improve your experience. By continuing, you consent to PingCAP's use of AI to process your
                code snippets via our AI-powered functions to improve our Services.
              </Typography>
            }
            styles={() => ({
              label: {
                cursor: 'pointer'
              },
              inner: {
                marginTop: 0
              },
              input: {
                cursor: 'pointer'
              }
            })}
          />
          <Typography variant="label-lg" ml={32} mt={4}>
            Learn more in our
            <Anchor
              ml={4}
              c="peacock.7"
              fw={500}
              href="https://www.pingcap.com/legal/ai-powered-functions-privacy-statement/"
              target="_blank"
              rel="noreferrer"
            >
              AI-Powered Functions Privacy Statement
            </Anchor>
            .
          </Typography>
        </Box>
      )}
    </Box>
  )
}

const CreateForm = ({ onCancel = () => {} }: { onCancel?: () => void }) => {
  const {
    orgId,
    projectId,
    getAppList,
    setEditEndpoint,
    editEndpointRef,
    setEditApp,
    isReposConflict,
    directoryErrInfo,
    appList,
    setIsReposConflict,
    setDirectoryErrInfo,
    setAISetting,
    AISetting,
    setNewAppListExpandKey,
    setDataappOpenedTab,
    createDataAppFromLogs
  } = useDataApiContext()

  const { setEditAppInHelpCenter, openDialog, setCurrentPath } = useHelpCenterContext()
  const createMutation = useCreateDataApp()
  const updateAISettingMutation = useUpdateAIUserSetting()
  const [requestId] = useGithubAuthRequest()
  const formProps = useForm<CreateAppFormValues>({})
  const { watch, setValue } = formProps
  const [githubOpened, setGithubOpened] = useState(false)
  const name = watch('app_name')
  const clusterIds = watch('cluster_ids')
  const directory = watch('directory')
  const dataAppType = watch('dataAppType')
  const isChat2DataPriAllowed = watch('is_privacy_allowed')

  const createApp = async (values: CreateAppFormValues) => {
    try {
      const data: EntityCreateDataAppParam = {
        app_name: values.app_name,
        cluster_ids: values.cluster_ids,
        description: values.description,
        app_type: values.dataAppType ?? 'chat2query'
      }

      if (values.repository_id && values.branch && values.directory) {
        const repo = values.repository_id.split('-')
        data.deployment_config = {
          branch: values.branch,
          directory: values.directory,
          preflight_request_id: requestId,
          repository_id: +repo[0],
          installation_id: +repo[1]
        }
      }

      const res = await createMutation.mutateAsync({
        orgId,
        projectId,
        data
      })

      if (res.code !== 200) {
        notifier.error(res.message)
        return
      }

      clearCreateFormStorageDatas()

      // chat2query allow ai
      if (values.dataAppType !== 'dataapi' && values.is_privacy_allowed) {
        const changeItems = {
          chat2query_init: true,
          is_privacy_allowed: values.is_privacy_allowed,
          privacy_box_count: 1
        }

        const res = await updateAISettingMutation.mutateAsync({
          orgId,
          projectId,
          data: changeItems
        })
        if (res.code !== 200) {
          notifier.error(res.message)
        } else {
          setAISetting(changeItems as UserSetting)
        }
      }

      if (createDataAppFromLogs) {
        getAppList()

        onCancel()
        return
      }

      setDataappOpenedTab(values.dataAppType === 'dataapi' ? 'Overview' : 'Settings')

      const app = res.data?.app_info
      if (app) {
        setEditEndpoint(null)
        editEndpointRef.current = null
        setEditApp(app as any as DataApp)

        if (values.dataAppType !== 'dataapi') {
          setNewAppListExpandKey(`${app.id}`)
        }

        getAppList()

        onCancel()
      }

      if (appList.length === 0) {
        setEditAppInHelpCenter(res.data?.app_info as any as DataApp)

        setTimeout(() => {
          setCurrentPath(DATA_SERVICE_BASE_PATH)
          openDialog()
        }, 2000)
      }
    } catch (_e) {
      notifier.error('Create Data App failed')
    }
  }

  useEffect(() => {
    if (requestId) {
      setValue('is_github_linked', true)
      setGithubOpened(true)
    }
  }, [requestId])

  const isSubmitDisabled = useMemo(() => {
    if (isReposConflict || directoryErrInfo) {
      return true
    }

    if (!name || !clusterIds?.length) {
      return true
    }

    if (dataAppType !== 'dataapi' && !AISetting.is_privacy_allowed && !isChat2DataPriAllowed) {
      return true
    }

    if (!githubOpened) {
      return false
    }

    if (directory) {
      return false
    }

    return true
  }, [githubOpened, name, clusterIds, directory, isReposConflict, dataAppType, isChat2DataPriAllowed])

  useEffect(() => {
    if (!githubOpened) {
      setValue('directory', '')
      setValue('branch', '')
      setValue('repository_id', '')
      setDirectoryErrInfo('')
      setIsReposConflict(false)
    }
  }, [githubOpened])

  useEffect(() => {
    if (dataAppType !== 'dataapi') {
      setGithubOpened(false)
    }
  }, [dataAppType])

  return (
    <Form
      withActions={false}
      form={formProps}
      layout="none"
      formMode="onChange"
      onCancel={onCancel}
      onSubmit={createApp}
    >
      <CreateItems />

      {dataAppType === 'dataapi' && (
        <Flex align="center" gap={32} mt={24}>
          <Box sx={{ flex: 1 }}>
            <Flex align="center" mb={4}>
              <Typography variant="title-md">Connect to GitHub</Typography>
              <Typography variant="body-lg" c="carbon.7" ml={2}>
                (Optional)
              </Typography>
            </Flex>
            <Typography variant="body-md">Connect your Data App to GitHub for Automatic Deployments.</Typography>
          </Box>
          <FormSwitch
            name="is_github_linked"
            size="lg"
            offLabel="Off"
            onLabel="On"
            onChange={(preChecked) => setGithubOpened(!preChecked)}
          />
        </Flex>
      )}

      {githubOpened && dataAppType === 'dataapi' && (
        <GithubAuth isCreate={true}>
          <Alert mt={24} mb={24}>
            "Connect to GitHub" will automatically deploy changes from the specified branch. You can modify this setting
            later in the application's settings. If you are importing an existing data application from a GitHub
            repository, please follow the instructions provided
            <GithubDocument
              ml={4}
              text="here"
              link="https://docs.pingcap.com/tidbcloud/data-service-manage-github-connection#import-configurations-of-an-existing-data-app"
            />
            .
          </Alert>
        </GithubAuth>
      )}

      <Group justify="flex-end" mt={24}>
        <Button variant="default" mr={12} onClick={onCancel} data-mp-event="mp-cancel-1691461014994">
          Cancel
        </Button>
        <Button
          data-testid="create-data-app"
          loading={createMutation.isLoading || updateAISettingMutation.isLoading}
          disabled={isSubmitDisabled}
          type="submit"
          data-mp-event="DataService create data app button clicked"
          data-mp-source="empty"
        >
          Create
        </Button>
      </Group>
    </Form>
  )
}

export default CreateForm
