import TimeRangePicker from '@tidb-cloud-uikit/components/TimeRangePicker'
import { ActionIcon, Box, Flex, Loader, Typography } from '@tidbcloud/uikit'
import { TimeRange, TimeRangeValue, toTimeRangeValue } from '@tidbcloud/uikit/biz'
import { Form, FormTextInput, FormSelect } from '@tidbcloud/uikit/biz'
import { IconChevronLeft, IconChevronRight, IconRefreshCcw01, IconXClose } from '@tidbcloud/uikit/icons'
import dayjs from 'dayjs'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'

import { useGetAppRequestLog, useListAppCluster } from 'dbaas/services/dataservice'
import { DtoDataAppLogEntry } from 'dbaas/services/dataservice/interface'

import { useDataApiContext } from '../../context'
import { OVERVIEW_QUICK_RANGES } from '../../utils'

import LogListTable from './ListTable'
import LogActions from './LogActions'
import LogDetail from './LogDetail'
import RequestBodySetting from './RequestBodySetting'

export const DEFAULT_TIME_RANGE: TimeRange = {
  type: 'relative',
  value: 30 * 60
}

interface AppLogFilterProps {
  status: string
  type: string
  cluster_id: string
  endpoint_id?: number
  request_id?: string
}

const AppLogs = () => {
  const [timeRange, setTimeRange] = useState<TimeRange>(DEFAULT_TIME_RANGE)
  const [timeRangeValue, setTimeRangeValue] = useState<TimeRangeValue>(toTimeRangeValue(DEFAULT_TIME_RANGE))
  const [detailOpened, setDetailOpened] = useState(false)
  const [detailItem, setDetailItem] = useState<DtoDataAppLogEntry | null>(null)

  const { orgId, projectId, editApp, dataappOpenedTab, logsDefaultValue, setLogsDefaultValue } = useDataApiContext()
  const formProps = useForm<AppLogFilterProps>({
    defaultValues: {
      status: 'All',
      type: 'all',
      cluster_id: '',
      endpoint_id: undefined,
      request_id: ''
    }
  })
  const { watch, setValue, getValues } = formProps
  const status = watch('status')
  const type = watch('type')
  const cluster_id = watch('cluster_id')
  const request_id = watch('request_id')
  const endpoint_id = watch('endpoint_id')
  const [requestLogs, setRequestLogs] = useState<{
    logs: DtoDataAppLogEntry[]
    has_more: boolean
  } | null>(null)
  const [curPageNo, setCurPageNo] = useState(1)
  const [passback, setPassback] = useState('')

  const resetRequest = () => {
    formProps.setValue('status', 'All')
    formProps.setValue('type', 'all')
    setValue('cluster_id', linkedClusters?.data?.length ? (linkedClusters?.data[0].cluster_id ?? '') : '')
    setTimeRange(DEFAULT_TIME_RANGE)
    setTimeRangeValue(toTimeRangeValue(DEFAULT_TIME_RANGE))
    setValue('endpoint_id', undefined)
    setValue('request_id', '')
  }

  useEffect(() => {
    if (dataappOpenedTab === 'Logs' && logsDefaultValue?.endpointId) {
      setValue('endpoint_id', (logsDefaultValue.endpointId as any as number) ?? undefined)
      if (logsDefaultValue?.timeRange) {
        const val = {
          type: 'absolute',
          value: [logsDefaultValue.timeRange?.from, logsDefaultValue?.timeRange?.to]
        } as TimeRange
        setTimeRange(val)
        setTimeRangeValue(toTimeRangeValue(val))
      }
      setValue('status', logsDefaultValue?.status ?? 'All')
      setLogsDefaultValue(null)
    }
  }, [dataappOpenedTab])

  const {
    isLoading: isLoadigLogs,
    isRefetching: isRefetchingLogs,
    isFetching: isFetchingLogs,
    refetch: refetchRequestLogs
  } = useGetAppRequestLog(
    orgId,
    projectId,
    `${editApp?.id}`,
    {
      start: timeRangeValue[0],
      end: timeRangeValue[1],
      status,
      type,
      endpoint_id,
      request_id,
      cluster_id,
      page: curPageNo,
      passback
    },
    {
      query: {
        enabled: false,
        cacheTime: 0,
        refetchInterval: false,
        refetchOnWindowFocus: false,
        onSuccess: (res) => {
          setPassback(res.passback ?? '')
          setRequestLogs({
            logs: res.logs ?? [],
            has_more: res.has_more ?? false
          })
        }
      }
    }
  )

  const { data: linkedClusters } = useListAppCluster(orgId, projectId, `${editApp?.id}`, {
    query: {
      enabled: !!(orgId && projectId && editApp?.id),
      refetchOnWindowFocus: false,
      onSuccess: (data) => {
        if (data?.data?.length) {
          const defaultEndpId = getValues('endpoint_id')
          const endp = (editApp?.endpoints || []).filter((item) => `${item.id}` === `${defaultEndpId}`)
          if (defaultEndpId && endp.length) {
            setValue('cluster_id', endp[0].cluster_id ?? '')
          } else {
            setValue('cluster_id', data.data[0].cluster_id ?? '')
          }
        }
      }
    }
  })

  const resetPageNo = () => {
    setCurPageNo(1)
  }

  useEffect(() => {
    resetPageNo()
  }, [editApp?.id])

  useEffect(() => {
    if (!cluster_id) {
      return
    }

    refetchRequestLogs()
  }, [curPageNo, refetchRequestLogs])

  useEffect(() => {
    resetPageNo()
    setPassback('')

    if (!cluster_id) {
      return
    }

    setTimeout(() => {
      refetchRequestLogs()
    }, 200)
  }, [cluster_id, timeRangeValue, status, type])

  const LogFilterInput = (name: keyof AppLogFilterProps, placeholder: string) => {
    return (
      <FormTextInput
        autoComplete="off"
        placeholder={placeholder}
        name={name}
        w={110}
        rightSection={
          !!request_id && (
            <IconXClose
              style={{ cursor: 'pointer' }}
              size={14}
              onClick={() => {
                setValue(name, '')
                setPassback('')
                setTimeout(() => {
                  refetchRequestLogs()
                })
              }}
            />
          )
        }
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            setPassback('')
            setTimeout(() => {
              refetchRequestLogs()
            })
          }
        }}
      />
    )
  }

  return (
    <Box
      sx={{
        height: '100%',
        overflowX: 'hidden',
        overflowY: 'auto',
        marginLeft: -16,
        marginRight: -16
      }}
    >
      <Flex px={16} align="center" my={16} justify="space-between" wrap="wrap">
        <Form layout="none" formMode="onChange" onSubmit={(_values) => {}} form={formProps} withActions={false}>
          <Flex align="center" gap={4}>
            <TimeRangePicker
              value={timeRange}
              quickRanges={OVERVIEW_QUICK_RANGES}
              loading={isLoadigLogs}
              minDateTime={() => dayjs().subtract(30, 'day').toDate()}
              maxDateTime={() => dayjs().toDate()}
              onChange={(v) => {
                setTimeRange(v)
                setTimeRangeValue(toTimeRangeValue(v))
              }}
            />

            <FormSelect
              w={115}
              name="type"
              data={[
                {
                  label: 'All Type',
                  value: 'all'
                },
                {
                  label: 'Endpoint',
                  value: 'endpoints'
                }
              ]}
              placeholder="Type"
              onChange={(type) => setValue('type', type!)}
            />

            <FormSelect
              w={115}
              name="status"
              data={[
                {
                  label: 'All Status',
                  value: 'All'
                },
                {
                  label: 'Success',
                  value: 'OK'
                },
                {
                  label: 'Error',
                  value: 'Error'
                }
              ]}
              placeholder="Status"
              onChange={(status) => setValue('status', status!)}
            />

            <FormSelect
              placeholder="Cluster Id"
              name="cluster_id"
              w={115}
              onChange={(id) => setValue('cluster_id', id!)}
              data={(linkedClusters?.data ?? []).map((item) => ({
                label: item.cluster_name ?? '',
                value: item.cluster_id ?? ''
              }))}
            />

            {LogFilterInput('request_id', 'Request Id')}
            {LogFilterInput('endpoint_id', 'Operation Id')}

            {!isFetchingLogs ? (
              <Typography variant="label-lg" sx={{ cursor: 'pointer' }} onClick={resetRequest}>
                Clear Filters
              </Typography>
            ) : (
              <Typography variant="label-lg" color="carbon.6">
                Clear Filters
              </Typography>
            )}
          </Flex>
        </Form>

        <Flex gap={4}>
          <ActionIcon
            aria-label="Refresh"
            variant="subtle"
            onClick={() => {
              setTimeRangeValue(toTimeRangeValue(timeRange))
              refetchRequestLogs()
            }}
          >
            {isFetchingLogs ? <Loader size={16} /> : <IconRefreshCcw01 size={16} strokeWidth={2} color="carbon.8" />}
          </ActionIcon>

          <LogActions
            orgId={orgId}
            projectId={projectId}
            appId={editApp?.id ?? ''}
            start={timeRangeValue[0]}
            end={timeRangeValue[1]}
            status={getValues('status')}
            type={getValues('type')}
            request_id={getValues('request_id') ?? ''}
            endpoint_id={getValues('endpoint_id') ?? ''}
            cluster_id={getValues('cluster_id') ?? ''}
          />

          <RequestBodySetting
            orgId={orgId}
            projectId={projectId}
            appId={editApp?.id ?? ''}
            logBodyStatus={!!editApp?.settings?.log_exec_result}
          />
        </Flex>
      </Flex>

      <LogListTable loading={isLoadigLogs || isRefetchingLogs} requestLogs={requestLogs?.logs ?? []} />

      {(curPageNo > 1 || requestLogs?.has_more) && (
        <Flex justify="end" align="center" mt={16} mr={16}>
          {curPageNo > 1 && (
            <ActionIcon aria-label="Previous Page" variant="subtle" onClick={() => setCurPageNo(curPageNo - 1)}>
              <IconChevronLeft />
            </ActionIcon>
          )}

          <Box
            fw={600}
            mx={8}
            sx={(t) => ({
              backgroundColor: t.colors.carbon[3],
              borderRadius: t.defaultRadius,
              width: 32,
              lineHeight: '32px',
              textAlign: 'center'
            })}
          >
            {curPageNo}
          </Box>

          {requestLogs?.has_more && (
            <ActionIcon aria-label="Next Page" variant="subtle" onClick={() => setCurPageNo(curPageNo + 1)}>
              <IconChevronRight />
            </ActionIcon>
          )}
        </Flex>
      )}

      <LogDetail
        opened={detailOpened}
        close={() => {
          setDetailOpened(false)
          setDetailItem(null)
        }}
        data={detailItem}
      />
    </Box>
  )
}
export default AppLogs
