import React, { useState, useMemo } from 'react'

import { Group, Paper } from '@mantine/core'
import { Select, DatePicker, Typography, Table, Space, Input } from 'antd'
import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'
import dayjs from 'dayjs'
import moment from 'moment-timezone'
import useSWR from 'swr'

import { CloudClusterInfo } from '@clinic/client'
import { getActiveQPS } from '~/api'
import { AppLayout } from '~/components/Layout'
import { useQueryParams } from '~/hooks/use-query-params'
import { activeQPSTelemetry } from '~/telemetry/active-qps'
import { clusterDeployTypeFilters } from '~/utils/cluster-status'

const { Option } = Select
const { RangePicker } = DatePicker

const QPS_BAR = [1, 100, 10000]

const REGIONS = [
  // aws
  'us-west-2',
  'us-east-1',
  'ap-northeast-1',
  'ap-southeast-1',
  'eu-central-1',

  // gcp
  'us-west1',
  'us-west2',
  'us-central1',
  'asia-east1',
  'asia-southeast1',
  'asia-northeast1'
]
const regionFilters = REGIONS.map((r) => ({ text: r, value: r }))

const now = moment()
const yesterday = now.subtract(1, 'day')

const defQueryParams = {
  page: 1,
  pageSize: 20,

  threshold: 100,
  region: [],
  deployType: [],
  beginDate: yesterday.format('YYYY-MM-DD'),
  endDate: yesterday.format('YYYY-MM-DD'),

  sort: 'max_qps',
  order: 'descend',

  query: ''
}

const disabledDate: (date: moment.Moment) => boolean = (current) => {
  const biggerThanNow = current && current > yesterday.endOf('days')
  return biggerThanNow
}

const gotoClinicCluster = (orgId: string, clusterId: string) => {
  window.open(
    `${window.location.protocol}//${window.location.host}${window.location.pathname}#/orgs/${orgId}/clusters/${clusterId}`,
    '_blank'
  )
}

const AcitveQPSPage: React.FC = () => {
  const { queryParams, setQueryParams } = useQueryParams(defQueryParams)

  const [defDateRange] = useState<[moment.Moment, moment.Moment] | null>(() => {
    const { beginDate, endDate } = queryParams
    if (beginDate !== '' && endDate !== '') {
      return [moment(beginDate), moment(endDate)]
    }
    return null
  })

  const {
    data: resp,
    isValidating,
    error
  } = useSWR(
    [
      '/api/v1/dashboard/activeqps',
      queryParams.threshold,
      queryParams.region,
      queryParams.deployType,
      queryParams.query,
      queryParams.beginDate,
      queryParams.endDate
    ],
    () => {
      let beginTs = 0
      if (queryParams.beginDate !== '') {
        // use UTC+0
        beginTs = moment(`${queryParams.beginDate}T00:00:00Z`).unix()
      }
      let endTs = 0
      if (queryParams.endDate !== '') {
        // use UTC+0
        endTs = moment(`${queryParams.endDate}T23:59:59Z`).unix()
      }
      return getActiveQPS(
        queryParams.threshold,
        beginTs,
        endTs,
        queryParams.region,
        queryParams.deployType,
        queryParams.query
      )
    }
  )
  const loading = !resp && !error

  function handleDateChange(values: any) {
    if (values === null) {
      setQueryParams({
        beginDate: defQueryParams.beginDate,
        endDate: defQueryParams.endDate,
        page: 1
      })
      activeQPSTelemetry.changeDate({ beginDate: null, endDate: null })
    } else {
      const beginDate = values[0].format('YYYY-MM-DD')
      const endDate = values[1].format('YYYY-MM-DD')
      setQueryParams({
        beginDate,
        endDate,
        page: 1
      })
      activeQPSTelemetry.changeDate({ beginDate, endDate })
    }
  }

  function handleTableChange(
    newPagination: TablePaginationConfig,
    filters: any,
    sorter: any
  ) {
    // filters: {deploy_type: null, region: ['us-west-2']}
    // sorter: {}, or {order:'ascend'|'descend', field:'clusterDeletedAt'}
    setQueryParams({
      deployType: filters.deploy_type || [],
      region: filters.region || [],

      page: newPagination.current ?? defQueryParams.page,
      pageSize: newPagination.pageSize ?? defQueryParams.pageSize,

      sort: sorter.field ?? '',
      order: sorter.order ?? ''
    })
    // telemetry

    if (
      (filters.deploy_type ?? []).join(',') !==
      (queryParams.deployType ?? []).join(',')
    ) {
      activeQPSTelemetry.changeFilters({
        filterType: 'deployType',
        filterValue: filters.deploy_type
      })
    } else if (
      (filters.region ?? []).join('') !== (queryParams.region ?? []).join('')
    ) {
      activeQPSTelemetry.changeFilters({
        filterType: 'region',
        filterValue: filters.region
      })
    } else if (
      sorter.field !== queryParams.sort ||
      sorter.order !== queryParams.order
    ) {
      activeQPSTelemetry.changeSort({ sort: sorter.field, order: sorter.order })
    } else {
      activeQPSTelemetry.changePagination({
        page: newPagination.current!,
        pageSize: newPagination.pageSize!
      })
    }
  }

  const columns = useMemo<ColumnsType<CloudClusterInfo>>(
    () => [
      {
        title: 'Tenant',
        width: 210,
        fixed: 'left',
        dataIndex: 'tenant_id',
        render: (_, record) => (
          <div className='flex flex-col'>
            {record.tenant_name ? (
              <Typography.Text ellipsis={{ tooltip: record.tenant_name }}>
                {record.tenant_name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type='secondary'>
              {record.tenant_id}
            </Typography.Text>
          </div>
        )
      },
      {
        title: 'Cluster',
        width: 210,
        fixed: 'left',
        dataIndex: 'cluster_id',
        render: (_, record) => (
          <div className='flex flex-col'>
            <Typography.Text ellipsis={{ tooltip: record.cluster_name }}>
              {record.cluster_name}
            </Typography.Text>
            <Typography.Text type='secondary'>
              {record.cluster_id}
            </Typography.Text>
          </div>
        )
      },
      {
        title: 'Deploy Type',
        dataIndex: 'deploy_type',
        width: 150,
        filters: clusterDeployTypeFilters,
        defaultFilteredValue: queryParams.deployType
      },
      {
        title: 'Region',
        dataIndex: 'region',
        width: 150,
        filters: regionFilters,
        defaultFilteredValue: queryParams.region
      },
      {
        title: 'Date (UTC+0)',
        dataIndex: 'timestamp',
        render: (v) => (
          <span>
            {/* toISOString() show UTC+0 time format */}
            {dayjs.unix(v).toISOString().slice(0, 'YYYY-MM-DD'.length)}
          </span>
        ),
        width: 150,
        sorter: (a, b) => a.timestamp! - b.timestamp!,
        defaultSortOrder:
          queryParams.sort === 'timestamp' ? queryParams.order : null
      },
      {
        title: 'Duration (mins)',
        dataIndex: 'duration',
        render: (v) => <span>{(Number(v) / 60).toFixed(0)}</span>,
        width: 150,
        sorter: (a, b) => a.duration! - b.duration!,
        defaultSortOrder:
          queryParams.sort === 'duration' ? queryParams.order : null
      },
      {
        title: 'Max QPS',
        dataIndex: 'max_qps',
        render: (v) => <span>{Number(v).toFixed(2)}</span>,
        sorter: (a, b) => a.max_qps! - b.max_qps!,
        defaultSortOrder:
          queryParams.sort === 'max_qps' ? queryParams.order : null
      },
      {
        title: 'Action',
        key: 'operation',
        width: 80,
        fixed: 'right',
        render: (val: null, record) => {
          return (
            <Space>
              <Typography.Link
                onClick={() => {
                  gotoClinicCluster(record.org_id!, record.cluster_id!)
                  activeQPSTelemetry.viewClusterDetail()
                }}
              >
                Clinic
              </Typography.Link>
            </Space>
          )
        }
      }
    ],
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []
  )

  return (
    <AppLayout>
      <Paper shadow='md' radius='sm'>
        <Group
          mx='md'
          py='md'
          className='border-0 border-b border-solid border-gray-200'
        >
          <Input.Search
            placeholder='Search by tenant/cluster name or id'
            onSearch={(s) => {
              setQueryParams({ query: s })
              activeQPSTelemetry.search({ text: s })
            }}
            loading={loading || isValidating}
            style={{ width: 340 }}
            size='large'
            defaultValue={queryParams.query}
          />

          <div>
            <Select
              size='large'
              style={{ width: 150 }}
              defaultValue={queryParams.threshold}
              onChange={(v) => {
                setQueryParams({ threshold: v, page: 1 })
                activeQPSTelemetry.changeThreshold({ threshold: v })
              }}
            >
              {QPS_BAR.map((q) => (
                <Option value={q} key={q}>
                  QPS &gt; {q}
                </Option>
              ))}
            </Select>
          </div>

          <RangePicker
            picker='date'
            className='rounded-lg self-stretch'
            disabledDate={disabledDate}
            onChange={handleDateChange}
            defaultValue={defDateRange}
          />
        </Group>

        <Group px='md'>
          <Table
            size='small'
            loading={loading}
            columns={columns}
            dataSource={resp?.data.items || []}
            scroll={{ x: 1248 }}
            pagination={{
              current: queryParams.page,
              pageSize: queryParams.pageSize,
              showTotal: (total) => `Total ${total} items`
            }}
            onChange={handleTableChange}
          />
        </Group>
      </Paper>
    </AppLayout>
  )
}

export default AcitveQPSPage
