import React, { createContext, useContext, useState } from 'react'

import useUrlState from '@ahooksjs/use-url-state'
import { LeftCircleOutlined } from '@ant-design/icons'
import { Button, message, Skeleton, DatePicker, Select } from 'antd'
import moment from 'moment-timezone'
import { RangeValue } from 'rc-picker/lib/interface'
import { useNavigate, useParams } from 'react-router-dom'
import useSWR, { useSWRConfig } from 'swr'

import { getClusterInfo, createReport } from '~/api'
import { useCurOrg } from '~/hooks/state'
import { reportsTelemetry } from '~/telemetry/reports'

import { ReportType } from '../shared/types'
import { ReportTable, getListKey } from './ReportTable'
import {
  ReportTypeContext,
  useReportTypeAPIPrefix,
  useReportTypeName
} from './useReportType'

interface AbsoluteValue {
  type: 'absolute'
  value: [startTime: number, endTime: number]
}
interface RelativeValue {
  type: 'relative'
  value: number
}

type TouchReportFormValue = AbsoluteValue | RelativeValue

function isAbsoluteValue(v: TouchReportFormValue): v is AbsoluteValue {
  return v.type === 'absolute'
}

const DEFAULT_FORM_VALUE: TouchReportFormValue = {
  type: 'relative',
  value: 2 * 60 * 60
}

type TouchReportForm = TouchReportFormValue
const FormContext = createContext<
  [TouchReportForm, React.Dispatch<React.SetStateAction<TouchReportForm>>]
>(null as any)
const useFormInstance = () => useContext(FormContext)

interface EntryProps {
  reportType: ReportType
}

const PageWrapper: React.FC<EntryProps> = (props) => {
  const { reportType } = props
  return (
    <ReportTypeContext.Provider value={reportType}>
      <Page {...props} />
    </ReportTypeContext.Provider>
  )
}

const Page: React.FC<EntryProps> = () => {
  const { orgId, cid } = useParams<'orgId' | 'cid'>()
  const navigate = useNavigate()

  const [queryParams] = useUrlState({
    from: 'now-2h',
    to: 'now'
  })

  const f = useState<TouchReportForm>(() => {
    if (queryParams.to === 'now') {
      return DEFAULT_FORM_VALUE
    }
    return {
      type: 'absolute',
      value: [Number(queryParams.from), Number(queryParams.to)]
    }
  })
  const { data: clusterInfoRes } = useSWR(
    `/orgs/${orgId}/clusters/${cid}`,
    () => getClusterInfo(orgId!, cid!)
  )
  const title = useReportTypeName()

  return (
    <div className='flex flex-col h-full'>
      <div className='py-4'>
        <Button
          icon={<LeftCircleOutlined />}
          type='text'
          onClick={() => navigate(-1)}
        ></Button>
        <span className='text-xl ml-2'>{title}</span>
      </div>

      <div className='rounded-lg bg-white p-6 mb-4'>
        <p className='text-xl'>
          Cluster Name:{' '}
          {clusterInfoRes?.data?.name ? (
            clusterInfoRes?.data?.name
          ) : (
            <Skeleton.Input style={{ width: '150px' }} active />
          )}
        </p>

        <div className='relative'>
          <FormContext.Provider value={f}>
            <TimerangeSelect />
            <CreateReportButton />
          </FormContext.Provider>
        </div>
      </div>

      <div className='rounded-lg bg-white px-6 pt-6'>
        <p className='text-lg'>All Reports</p>
        <ReportTable />
      </div>
    </div>
  )
}

const CreateReportButton = React.memo(() => {
  const { orgId, cid } = useParams<'orgId' | 'cid'>()

  const { curOrg } = useCurOrg()
  const { orgType } = curOrg!

  const apiPrefix = useReportTypeAPIPrefix()
  const [f] = useFormInstance()
  const { mutate } = useSWRConfig()
  const [loading, setLoading] = useState(false)
  const title = useReportTypeName()

  return (
    <Button
      style={{ position: 'absolute !important' as any }}
      className='absolute top-0 right-0'
      type='primary'
      disabled={loading}
      onClick={async () => {
        const isAbs = isAbsoluteValue(f)
        const now = parseInt(`${Date.now() / 1000}`)
        const endTime = isAbs ? f.value[1] : now
        const startTime = isAbs ? f.value[0] : now - f.value
        const isValidForm =
          startTime && endTime && startTime < endTime && endTime <= now
        if (!isValidForm) {
          message.error(
            'Please select valid time range and less than the current date time'
          )
          return
        }

        try {
          setLoading(true)
          const params = {
            begin_ts: startTime,
            end_ts: endTime,
            org_type: orgType
          }
          await createReport(orgId!, cid!, apiPrefix, params)
          reportsTelemetry.createReport(title, orgId!, cid!, params)
          mutate(getListKey(orgId!, cid!, apiPrefix, 1))
          message.loading(
            'Diagnosis Engine is generating report, it may take about few minutes.'
          )
        } finally {
          setLoading(false)
        }
      }}
    >
      Create Report
    </Button>
  )
})

const TIME_RANGE_OPTIONS = [
  {
    value: 30 * 60,
    label: 'Recent 30 mins'
  },
  {
    value: 2 * 60 * 60,
    label: 'Recent 2 hours'
  },
  {
    value: 8 * 60 * 60,
    label: 'Recent 8 hours'
  },
  {
    value: 24 * 60 * 60,
    label: 'Recent 24 hours'
  },
  {
    value: 'absolute',
    label: 'Absolute'
  }
]

const TimerangeSelect = () => {
  const [f, setF] = useFormInstance()
  // const [hackValue, setHackValue] = useState<RangeValue<moment.Moment>>(() => {
  //   if (f.type === 'absolute') {
  //     return [moment.unix(f.value[0]), moment.unix(f.value[1])]
  //   }
  //   return null
  // })
  const [dates, setDates] = useState<RangeValue<moment.Moment>>(null)
  const [value, setValue] = useState<RangeValue<moment.Moment>>(() => {
    if (f.type === 'absolute') {
      return [moment.unix(f.value[0]), moment.unix(f.value[1])]
    }
    return null
  })

  const disabledDate: (date: moment.Moment) => boolean = (current) => {
    if (!dates) {
      return false
    }
    const tooLate = dates[0] && current.diff(dates[0], 'hours') > 48
    const tooEarly = dates[1] && dates[1].diff(current, 'hours') > 48
    const biggerThanNow = current && current > moment().endOf('days')
    const lessThan7Days =
      current && current < moment().subtract(7, 'days').startOf('days')
    return !!tooEarly || !!tooLate || biggerThanNow || lessThan7Days
  }

  const onOpenChange = (open: boolean) => {
    if (open) {
      // setHackValue([null, null])
      setDates([null, null])
    } else {
      // setHackValue(null)
      setDates(null)
    }
  }

  return (
    <>
      <div className='mb-2'>
        <span className='mr-2'>Time Range:</span>
        <Select
          className='mr-2'
          defaultValue={f.type === 'relative' ? f.value : f.type}
          style={{ width: 150 }}
          onChange={(v) => {
            const isAbs = typeof v === 'string' && v === 'absolute'
            const formValue = {
              type: isAbs ? 'absolute' : 'relative',
              value: isAbs ? [0, 0] : v
            } as TouchReportFormValue
            setF(formValue)
          }}
          options={TIME_RANGE_OPTIONS}
        />
        {f.type === 'absolute' && (
          <DatePicker.RangePicker
            className='rounded-lg'
            showTime
            value={dates || value}
            // defaultValue={hackValue}
            disabledDate={disabledDate}
            onOpenChange={onOpenChange}
            onCalendarChange={(val) => {
              setDates(val)
            }}
            onChange={(v) => {
              const [start, end] = v!.map((t) => t!.unix())
              setValue(v)
              setF({
                type: 'absolute',
                value: [start, end]
              })
            }}
          />
        )}
      </div>
    </>
  )
}

export default PageWrapper
