import {
  Button,
  Group,
  Modal,
  Stack,
  TextInput,
  Typography,
  notifier
} from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { IconSearchLg } from '@tidbcloud/uikit/icons'
import { useCallback, useMemo, useState } from 'react'

import {
  cloudConfigControllerCreateMetaProfile,
  cloudConfigControllerListMetaProfiles
} from 'apiClient/services/devops'
import {
  CloudconfigClusterType,
  CloudconfigMetaProfile,
  CloudconfigCreateMetaProfileReq
} from 'apiClient/services/devops/interface'
import useTable from 'components/Table/useTable'
import ReadOnlyMetaProfile from 'pages/ConfigCenter/Template/components/MetaProfileView'

import CreateMetaProfile, {
  CloudconfigCreateMetaProfileForm,
  CloudconfigCreateMetaProfileFormErrors,
  getInitialMetaProfileForm
} from './Form/CreateMetaProfile'

type TablePaginationState = {
  pageIndex: number
  pageSize: number
}

const getErrorContent = (error: any) =>
  error?.response?.data?.message ||
  error?.response?.data?.errmsg ||
  error?.response?.data?.error ||
  error?.message ||
  JSON.stringify(error)

const hasValue = (value?: string | number) =>
  value !== undefined && value !== null && String(value).trim() !== ''

export default function MetaProfile({
  org_id,
  cluster_type
}: {
  org_id?: string
  cluster_type: CloudconfigClusterType
}) {
  const [metaProfileForm, setMetaProfileForm] = useState(false)
  const [viewMetaProfile, setMetaProfile] = useState(false)
  const [profileIDToView, setProfileIDToView] = useState<string>('')
  const [profileName, setProfileName] = useState('')
  const [profileNameInput, setProfileNameInput] = useState('')
  const [createSubmitting, setCreateSubmitting] = useState(false)
  const [createdOperationId, setCreatedOperationId] = useState<string>()
  const [createFormErrors, setCreateFormErrors] =
    useState<CloudconfigCreateMetaProfileFormErrors>({})
  const [createFormValue, setCreateFormValue] =
    useState<CloudconfigCreateMetaProfileForm>(() =>
      getInitialMetaProfileForm({
        clusterType: cluster_type,
        tenantId: org_id || ''
      })
    )

  const resetCreateForm = useCallback(() => {
    setCreateFormErrors({})
    setCreateFormValue(
      getInitialMetaProfileForm({
        clusterType: cluster_type,
        tenantId: org_id || ''
      })
    )
  }, [cluster_type, org_id])

  const handleOpenCreateMetaProfile = useCallback(() => {
    resetCreateForm()
    setMetaProfileForm(true)
  }, [resetCreateForm])

  const handleCancelCreateMetaProfile = useCallback(() => {
    setMetaProfileForm(false)
    resetCreateForm()
  }, [resetCreateForm])

  const fetchData = (params?: Partial<PageInfo>) =>
    cloudConfigControllerListMetaProfiles({
      cluster_type: cluster_type,
      page: params?.page,
      per_page: params?.pageSize,
      profile_name: profileName || undefined,
      tenant_id: org_id
    })

  const validateCreateForm = useCallback(
    (values: CloudconfigCreateMetaProfileForm) => {
      const errors: CloudconfigCreateMetaProfileFormErrors = {}

      if (!values.profile_name.trim()) {
        errors.profile_name = 'Profile name is required'
      }

      const selectedComponents = new Set<string>()
      ;(values.component_settings || []).forEach((item, index) => {
        if (!item.key) {
          errors[`component_settings.${index}.key`] =
            'Component name is required'
          return
        }
        if (selectedComponents.has(item.key)) {
          errors[`component_settings.${index}.key`] =
            'Component name must be unique'
          return
        }
        selectedComponents.add(item.key)

        if (!item.version) {
          errors[`component_settings.${index}.version`] = 'Version is required'
        }
      })

      const selectedConfigTypes = new Set<string>()
      ;(values.config_custom_templates || []).forEach((item, index) => {
        if (!item.key) {
          errors[`config_custom_templates.${index}.key`] =
            'Config type is required'
          return
        }
        if (selectedConfigTypes.has(item.key)) {
          errors[`config_custom_templates.${index}.key`] =
            'Config type must be unique'
          return
        }
        selectedConfigTypes.add(item.key)

        if (!hasValue(item.value)) {
          errors[`config_custom_templates.${index}.value`] =
            'Template is required'
        }
      })

      setCreateFormErrors(errors)
      return Object.keys(errors).length === 0
    },
    []
  )

  const handleFinish = async () => {
    if (!validateCreateForm(createFormValue)) {
      notifier.error('Please fix the highlighted fields before continuing.')
      return
    }

    const component_image_tags: Record<string, string> = {}
    const component_versions: Record<string, string> = {}
    ;(createFormValue.component_settings || []).forEach((item) => {
      if (!item.key) {
        return
      }

      if (item.image_tag) {
        component_image_tags[item.key] = item.image_tag
      }
      if (item.version) {
        component_versions[item.key] = item.version
      }
    })

    const config_custom_templates: Record<string, number> = {}
    ;(createFormValue.config_custom_templates || []).forEach((item) => {
      if (item?.key && hasValue(item.value)) {
        config_custom_templates[item.key] = Number(item.value)
      }
    })

    const req: CloudconfigCreateMetaProfileReq = {
      cluster_type: cluster_type,
      component_image_tags,
      description: createFormValue.description,
      profile_name: createFormValue.profile_name,
      tenant_id: org_id!
    }

    if (Object.keys(config_custom_templates).length > 0) {
      req.config_custom_templates = config_custom_templates
    }
    if (Object.keys(component_versions).length > 0) {
      req.component_versions = component_versions
    }

    setCreateSubmitting(true)
    try {
      const resp = (await cloudConfigControllerCreateMetaProfile(req)).data
        .instance_id
      setCreatedOperationId(resp?.toString())
      setMetaProfileForm(false)
      resetCreateForm()
    } catch (error) {
      notifier.error(getErrorContent(error), {
        title: 'Failed to create meta profile'
      })
    } finally {
      setCreateSubmitting(false)
    }
  }

  const {
    dataSource: templateData,
    loading: templateLoading,
    paginationProps: templatePaginationProps,
    onTableChange: templateOnTableChange,
    resetPageIndex: templateResetPageIndex
  } = useTable<ListData<CloudconfigMetaProfile>>(fetchData, [], {
    deps: [cluster_type, org_id, profileName],
    pagination: true
  })

  const tablePagination = useMemo<TablePaginationState>(
    () => ({
      pageIndex: Math.max((templatePaginationProps.current || 1) - 1, 0),
      pageSize: templatePaginationProps.pageSize || 10
    }),
    [templatePaginationProps.current, templatePaginationProps.pageSize]
  )

  const columns = useMemo<MRT_ColumnDef<CloudconfigMetaProfile>[]>(
    () => [
      {
        accessorFn: (record) => record.profile_id || '-',
        header: 'ID',
        id: 'profile_id',
        size: 120
      },
      {
        accessorFn: (record) => record.profile_name || '-',
        header: 'Name',
        id: 'profile_name',
        size: 240
      },
      {
        accessorFn: (record) => record.description || '-',
        header: 'Description',
        id: 'description',
        size: 320
      },
      {
        Cell: ({ row }) => (
          <Button
            onClick={() => {
              setProfileIDToView(row.original.profile_id!.toString())
              setMetaProfile(true)
            }}
            size="xs"
            variant="subtle"
          >
            Detail
          </Button>
        ),
        header: 'Action',
        id: 'action',
        size: 100
      }
    ],
    []
  )

  const handleSearch = () => {
    templateResetPageIndex()
    setProfileName(profileNameInput.trim())
  }

  return (
    <>
      <Stack gap="md">
        <Group gap="sm" align="center">
          <Button onClick={handleOpenCreateMetaProfile}>
            Create Meta Profile
          </Button>
          <TextInput
            leftSection={<IconSearchLg size={16} />}
            onChange={(event) => setProfileNameInput(event.currentTarget.value)}
            onKeyDown={(event) => {
              if (event.key === 'Enter') {
                handleSearch()
              }
            }}
            placeholder="Search by profile name"
            style={{ width: 280 }}
            value={profileNameInput}
          />
          <Button onClick={handleSearch} variant="default">
            Search
          </Button>
        </Group>

        <ProTable<CloudconfigMetaProfile>
          columns={columns}
          data={templateData || []}
          enableColumnActions={false}
          enableColumnFilters={false}
          enableDensityToggle={false}
          enableFullScreenToggle={false}
          enableHiding={false}
          enablePagination
          enableSorting={false}
          enableTopToolbar={false}
          getRowId={(row, rowIndex) =>
            row.profile_id?.toString() || rowIndex.toString()
          }
          loading={templateLoading}
          manualPagination
          onPaginationChange={(updaterOrValue) => {
            const nextPagination =
              typeof updaterOrValue === 'function'
                ? updaterOrValue(tablePagination)
                : updaterOrValue

            templateOnTableChange(
              {
                current: nextPagination.pageIndex + 1,
                pageSize: nextPagination.pageSize,
                total: templatePaginationProps.total
              },
              {}
            )
          }}
          pagination={{ showRowsPerPage: false }}
          rowCount={templatePaginationProps.total || 0}
          state={{ pagination: tablePagination }}
        />
      </Stack>

      <Modal
        centered
        closeOnClickOutside={false}
        opened={metaProfileForm}
        onClose={handleCancelCreateMetaProfile}
        size={1000}
        title="Create Meta Profile"
        trapFocus={false}
      >
        <Stack gap="lg">
          <CreateMetaProfile
            clusterType={cluster_type}
            errors={createFormErrors}
            onChange={(nextValue) => {
              setCreateFormValue(nextValue)
              setCreateFormErrors({})
            }}
            tenantId={org_id!}
            value={createFormValue}
          />
          <Group justify="flex-end" gap="sm">
            <Button onClick={handleCancelCreateMetaProfile} variant="default">
              Cancel
            </Button>
            <Button loading={createSubmitting} onClick={handleFinish}>
              Next
            </Button>
          </Group>
        </Stack>
      </Modal>

      <Modal
        centered
        opened={viewMetaProfile}
        onClose={() => {
          setMetaProfile(false)
        }}
        size={800}
        title="View Meta Profile"
        trapFocus={false}
      >
        <ReadOnlyMetaProfile
          profile_id={profileIDToView}
          cluster_type={cluster_type}
        />
      </Modal>

      <Modal
        centered
        opened={!!createdOperationId}
        onClose={() => setCreatedOperationId(undefined)}
        size={520}
        title="Info"
        trapFocus={false}
      >
        <Stack gap="lg">
          <Typography>
            This config change has been created. Please go to the Detail page to
            check the approval information and apply it.
          </Typography>
          <Group justify="flex-end" gap="sm">
            <Button
              onClick={() => setCreatedOperationId(undefined)}
              variant="default"
            >
              Cancel
            </Button>
            <Button
              onClick={() => {
                window.open(`/operations/${createdOperationId}`, '_blank')
                setCreatedOperationId(undefined)
              }}
            >
              OK
            </Button>
          </Group>
        </Stack>
      </Modal>
    </>
  )
}
