import { PlusOutlined } from '@ant-design/icons'
import { Button, Modal, Select } from 'antd'
import { FormInstance } from 'antd/es/form/Form'
import Table, { ColumnsType } from 'antd/lib/table'
import { useCallback, useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'

import { patchSku } from 'apiClient/services/devops'
import {
  spuServiceCreateSku,
  spuServiceCreateSpu,
  spuServiceListSkus,
  spuServiceListSpus,
  spuServiceUpdateSku
} from 'apiClient/services/sku'
import {
  ConditionKey,
  ConditionOperator,
  Dedicatedv1ComponentType,
  InstanceMuCpuArch,
  SkuCondition,
  SkuDiskType,
  SpuServiceListSkusCloudProvider,
  SpuServiceListSkusComponentTypesItem,
  SpuServiceListSkusParams,
  SpuServiceListSpusComponentType,
  SpuServiceUpdateSkuBody,
  StorageMuVolumeType,
  TidbMgmtServicev1Sku,
  TidbMgmtServicev1Spu,
  V1SkuStorage
} from 'apiClient/services/sku/interface'
import ModalForm from 'components/ModalForm'
import { ListToolBar, useTable } from 'components/Table'

import SKUPage, { SKUFormType, StorageType } from './Forms/SKUForm'

export const getAvailableDisplaynames = (
  dataSource: TidbMgmtServicev1Sku[]
) => {
  let all = dataSource.map((v) => {
    return v.spuDisplayName!
  })
  return all
    .filter((item, index) => all.indexOf(item) === index)
    .map((v) => ({ label: v, value: v }))
}

export const getAvailableSPUKeys = (
  dataSource: TidbMgmtServicev1Sku[],
  provider?: SpuServiceListSkusCloudProvider,
  componentType?: Dedicatedv1ComponentType,
  displayName?: string
) => {
  let all = dataSource
    .filter(
      (v) =>
        v.cloudProvider === provider &&
        v.componentType === componentType &&
        v.spuDisplayName === displayName
    )
    .map((v) => v.spuKey!)
  return all
    .filter((item, index) => all.indexOf(item) === index)
    .map((v) => ({ label: v, value: v }))
}

export const getAvailableVolumeTypes = (
  dataSource: TidbMgmtServicev1Sku[],
  provider?: SpuServiceListSkusCloudProvider
) => {
  let all = dataSource
    .filter((v) => v.cloudProvider === provider)
    .map((v) => v.dataStorage?.volumeType!)
  return all
    .filter((item, index) => all.indexOf(item) === index)
    .map((v) => ({ label: v, value: v }))
}

export const SKUManagement = () => {
  const params = new URLSearchParams(window.location.search)
  const spuKey = params.get('spu_key') || ''
  const [listParam, setListParam] = useState<SpuServiceListSkusParams>({
    cloudProvider: SpuServiceListSkusCloudProvider.AWS
  })
  const [filterVolumeType, setFilterVolumeType] =
    useState<StorageMuVolumeType>()
  const [filterArc, setFilterArc] = useState<InstanceMuCpuArch>()
  const [filterDisplayName, setFilterDisplayName] = useState()
  const [modifyRecord, setModifyRecord] = useState<TidbMgmtServicev1Sku>()
  const getData = (params?: Partial<PageInfo>) =>
    spuServiceListSkus(listParam).then((response) => ({
      ...response,
      data: {
        items: response.data.skus
      }
    }))
  const { dataSource, loading, reload, paginationProps, onTableChange } =
    useTable<ListData<TidbMgmtServicev1Sku>>(getData, [], {
      pagination: true
    })
  const columns: ColumnsType<TidbMgmtServicev1Sku> = [
    {
      title: 'ID',
      render: (_: any, record) => {
        return record.id
      }
    },
    {
      title: 'SKU KEY',
      render: (_: any, record) => {
        return record.key
      }
    },
    {
      title: 'SPU KEY',
      render: (_: any, record) => {
        return record.spuKey
      }
    },
    {
      title: 'DISPLAY NAME',
      render: (_: any, record) => {
        return record.spuDisplayName
      }
    },
    {
      title: 'COMPONENT',
      render: (_: any, record) => {
        return record.componentType
      }
    },
    {
      title: 'INSTANCE TYPE',
      render: (_: any, record) => {
        return record.instanceType || ''
      }
    },
    {
      title: 'PROVIDER',
      render: (_: any, record) => {
        return record.cloudProvider
      }
    },
    {
      title: 'INSTANCE CPU ARCH',
      render: (_: any, record) => {
        return record.cpuArch || ''
      }
    },
    {
      title: 'VOLUME TYPE',
      render: (_: any, record) => {
        return record.dataStorage?.volumeType || ''
      }
    },
    {
      title: 'DEFAULT STORAGE SIZE',
      render: (_: any, record) => {
        return record.dataStorage?.sizeGiDefault || ''
      }
    },
    {
      title: 'MIN STORAGE SIZE',
      render: (_: any, record) => {
        return record.dataStorage?.sizeGiMin || ''
      }
    },
    {
      title: 'MAX STORAGE SIZE',
      render: (_: any, record) => {
        return record.dataStorage?.sizeGiMax || ''
      }
    },
    {
      title: 'DEFAULT IOPS',
      render: (_: any, record) => {
        return record.dataStorage?.iopsFixed?.iops || ''
      }
    },
    {
      title: 'DEFAULT THROUGHPUT',
      render: (_: any, record) => {
        return record.dataStorage?.throughputFixed?.throughputMibps || ''
      }
    },
    {
      title: 'DEFAULT NODE NUMBERS',
      render: (_: any, record) => {
        return record.defaultNodeCount
      }
    },
    {
      title: 'TIKV SKU KEY',
      render: (_: any, record) => {
        return record.conditions
          ?.filter((v) => v.key === ConditionKey.ATTACH_TIERUNIT)
          .map((v) => v.values.join(', '))
          .join(', ')
      }
    },
    {
      title: 'Actions',
      width: 300, // 定义足够列宽
      render: (_: any, record) => (
        <div
          style={{
            display: 'flex',
            gap: 8, // 现代浏览器间距方案
            flexWrap: 'nowrap' // 禁止换行
          }}
        >
          <Button
            type="link"
            size="small"
            style={{ padding: '0 4px' }}
            onClick={() => {
              setModifyRecord(record)
              setModifyForm(true)
            }}
          >
            Modify
          </Button>
          <Button type="link" size="small" style={{ padding: '0 4px' }}>
            <Link
              target="_blank"
              to={`/sku_service/whitelist?sku_key=${record.key}&component_type=${record.componentType}`}
            >
              Whitelist Strategy
            </Link>
          </Button>
        </div>
      )
    }
  ]

  const [createForm, setCreateForm] = useState(false)
  const [modifyForm, setModifyForm] = useState(false)
  const handleCancel = useCallback(() => {
    setCreateForm(false)
  }, [])
  const handleCancelModify = useCallback(() => {
    setModifyForm(false)
  }, [])

  const createSKU = () => {
    setCreateForm(true)
  }

  const renderCreateFormFields = useCallback(
    (form: FormInstance) => {
      if (!form.getFieldValue('componentType')) {
        form.setFieldsValue({
          componentType: SpuServiceListSkusComponentTypesItem.TIDB
        })
      }
      return <SKUPage form={form} type="create" />
    },
    [createForm]
  )

  const fillStorageValue = (s?: V1SkuStorage) => {
    if (s !== undefined) {
      let formData = {
        storageMuSelector: s.storageMuId,
        volumeType: s.volumeType!,
        storageMuId: s.storageMuId,
        defaultStorageSize: s.sizeGiDefault,
        minStorageSize: s.sizeGiMin,
        maxStorageSize: s.sizeGiMax,
        minIops: s.iopsMin,
        maxIops: s.iopsMax,
        minThroughput: s.throughputMibpsMin,
        maxThroughput: s.throughputMibpsMax,
        iopsStrategy: s.iopsDynamic === undefined ? 'Fixed' : 'Dynamic',
        iopsValue:
          s.iopsDynamic === undefined
            ? s.iopsFixed?.iops
            : s.iopsDynamic.iopsPerSizeGi,
        throughputStrategy:
          s.throughputDynamic === undefined ? 'Fixed' : 'Dynamic',
        throughputValue: s.throughputFixed?.throughputMibps,
        throughputMibpsPerIops: s.throughputDynamic?.throughputMibpsPerIops,
        throughputMibpsPerSizeGi: s.throughputDynamic?.throughputMibpsPerSizeGi
      }
      return formData
    } else {
      return undefined
    }
  }

  const renderModifyFormFields = useCallback(
    (form: FormInstance) => {
      form.setFieldsValue({
        displayName: modifyRecord?.spuDisplayName,
        componentType: modifyRecord?.componentType,
        provider: modifyRecord?.cloudProvider,
        instanceType: modifyRecord?.instanceType,
        instanceMuId: modifyRecord?.instanceMuId,
        cpuArch: modifyRecord?.cpuArch,
        spuId: modifyRecord?.spuId,
        vCPUNumber: modifyRecord?.cpuCore,
        memorySize: modifyRecord?.memoryGi,
        defaultNodeNumber: modifyRecord?.defaultNodeCount,
        spuKey: modifyRecord?.spuKey,
        skuKey: modifyRecord?.key,
        tikvSkuKey:
          modifyRecord?.conditions &&
          modifyRecord?.conditions
            .filter((v) => v.key === ConditionKey.ATTACH_TIERUNIT)
            .map((v) => v.values)
            .flatMap((item) => item)
      })
      form.setFieldsValue(fillStorageValue(modifyRecord?.dataStorage))
      if (modifyRecord?.raftlogStorage !== undefined) {
        form.setFieldsValue({
          raft: fillStorageValue(modifyRecord?.raftlogStorage),
          raftEnable: true
        })
      } else {
        form.setFieldsValue({
          raftEnable: false
        })
      }
      return <SKUPage form={form} type="modify" />
    },
    [modifyForm, modifyRecord]
  )

  const reverseStorageValue = (s: StorageType, diskType: SkuDiskType) => {
    let storageData: V1SkuStorage = {
      diskType: diskType,
      storageMuId: s.storageMuId,
      volumeType: s.volumeType,
      sizeGiDefault: s.defaultStorageSize,
      sizeGiMax: s.maxStorageSize,
      sizeGiMin: s.minStorageSize,
      iopsMax: s.maxIops,
      iopsMin: s.minIops,
      throughputMibpsMax: s.maxThroughput,
      throughputMibpsMin: s.minThroughput,
      iopsFixed:
        s.iopsStrategy === 'Fixed' ? { iops: s.iopsValue! } : undefined,
      iopsDynamic:
        s.iopsStrategy === 'Dynamic'
          ? { iopsPerSizeGi: s.iopsValue! }
          : undefined,
      throughputFixed:
        s.throughputStrategy === 'Fixed'
          ? { throughputMibps: s.throughputValue! }
          : undefined,
      throughputDynamic:
        s.throughputStrategy === 'Dynamic'
          ? {
              throughputMibpsPerIops: s.throughputMibpsPerIops!,
              throughputMibpsPerSizeGi: s.throughputMibpsPerSizeGi!
            }
          : undefined
    }
    return storageData
  }

  const reverseFormToReq = (s: SKUFormType) => {
    let reverseData: TidbMgmtServicev1Sku = {
      spuId: s.spuId,
      spuKey: s.spuKey,
      spuDisplayName: s.displayName,
      key: s.skuKey,
      cloudProvider: s.provider,
      componentType: s.componentType,
      instanceMuId: s.instanceMuId,
      cpuArch: s.cpuArch,
      instanceType: s.instanceType,
      cpuCore: s.vCPUNumber,
      memoryGi: s.memorySize,
      defaultNodeCount: s.defaultNodeNumber
    }
    if (s.tikvSkuKey !== undefined) {
      reverseData.conditions = []
      reverseData.conditions.push({
        key: ConditionKey.ATTACH_TIERUNIT,
        operator: ConditionOperator.IN,
        values: s.tikvSkuKey
      })
    }
    if (s.componentType !== SpuServiceListSkusComponentTypesItem.TIDB) {
      reverseData.dataStorage = reverseStorageValue(s, SkuDiskType.DATA)
    }
    if (s.raft !== undefined) {
      reverseData.raftlogStorage = reverseStorageValue(
        s.raft,
        SkuDiskType.RAFT_LOG
      )
    }
    return reverseData
  }

  const handleCreate = useCallback(
    async (payload: SKUFormType) => {
      let condition: SkuCondition | undefined = undefined
      if (payload.tikvSkuKey !== undefined) {
      }
      condition = {
        key: ConditionKey.ATTACH_TIERUNIT,
        operator: ConditionOperator.IN,
        values: payload.tikvSkuKey || []
      }
      let req: TidbMgmtServicev1Sku = reverseFormToReq(payload)
      try {
        await spuServiceCreateSku(req)
        Modal.success({
          title: 'Info',
          content: (
            <div>
              <p>SKU has been created</p>
            </div>
          ),
          onOk() {}
        })
        setCreateForm(false)
        reload()
      } catch (error) {
        Modal.error({
          title: error.response.data.code,
          content: error.response.data.message
        })
      }
    },
    [reload]
  )
  const handleModify = useCallback(
    async (payload: SKUFormType) => {
      let req: SpuServiceUpdateSkuBody = {
        defaultNodeCount: payload.defaultNodeNumber,
        dataStorage:
          payload.componentType === SpuServiceListSkusComponentTypesItem.TIDB
            ? undefined
            : reverseStorageValue(payload, SkuDiskType.DATA)
      }
      if (payload.raft !== undefined) {
        req.raftlogStorage = reverseStorageValue(
          payload.raft,
          SkuDiskType.RAFT_LOG
        )
      }
      if (payload.componentType === SpuServiceListSkusComponentTypesItem.PD) {
        req.conditions = [
          {
            key: ConditionKey.ATTACH_TIERUNIT,
            operator: ConditionOperator.IN,
            values: payload.tikvSkuKey || []
          }
        ]
      }

      try {
        const instance = (await patchSku(modifyRecord!.id!, req)).data
          .instance_id
        Modal.success({
          title: 'info',
          content: (
            <div>
              <p>
                Successfully submit the request to update the Sku.
                <br></br>
                <br></br>
                To check the progress of this operation, please refer to the{' '}
                <a href={`/operations/${instance}`}>Detail</a> page.
              </p>
            </div>
          ),
          onOk() {
            window.open(`/operations/${instance}`, '_blank')
          }
        })
        setModifyForm(false)
        reload()
      } catch (error) {
        Modal.error({
          title: error.response.data.code,
          content: error.response.data.message
        })
      }
    },
    [reload]
  )

  const actions = useMemo(
    () => [
      <Select
        options={getAvailableDisplaynames(dataSource)}
        value={filterDisplayName}
        onChange={(event) => {
          setFilterDisplayName(event)
          reload()
        }}
        style={{ width: 150 }}
        showSearch
        allowClear
        placeholder="Display Name"
      ></Select>,
      <Select
        options={Object.entries(SpuServiceListSkusCloudProvider).map(
          ([key, value]) => ({
            label: key,
            value: value
          })
        )}
        value={listParam.cloudProvider}
        onChange={(event) => {
          setListParam((pre) => ({ ...pre, cloudProvider: event }))
          reload()
        }}
        style={{ width: 150 }}
      ></Select>,
      <Select
        placeholder="Component"
        options={Object.entries(SpuServiceListSkusComponentTypesItem).map(
          ([key, value]) => ({
            label: key,
            value: value
          })
        )}
        value={listParam.componentTypes}
        mode="multiple"
        onChange={(event) => {
          setListParam((pre) => ({ ...pre, componentTypes: event }))
          reload()
        }}
        style={{ width: 150 }}
      ></Select>,
      <Select
        placeholder="Instance Type"
        options={Object.entries(StorageMuVolumeType).map(([key, value]) => ({
          label: key,
          value: value
        }))}
        value={filterVolumeType}
        onChange={(event) => {
          setFilterVolumeType(event)
        }}
        style={{ width: 150 }}
        allowClear={true}
      ></Select>,
      <Select
        placeholder="CPU Arch"
        options={Object.entries(InstanceMuCpuArch).map(([key, value]) => ({
          label: key,
          value: value
        }))}
        value={filterArc}
        onChange={(event) => {
          setFilterArc(event)
        }}
        style={{ width: 150 }}
        allowClear={true}
      ></Select>,
      <div style={{ display: 'flex', gap: '10px' }}>
        <Button type="primary" onClick={createSKU} icon={<PlusOutlined />}>
          Create SKU
        </Button>
      </div>
    ],
    [listParam, filterArc, filterVolumeType, dataSource]
  )

  return (
    <div>
      <ListToolBar
        actions={actions}
        reload={() => {
          setListParam({ cloudProvider: SpuServiceListSkusCloudProvider.AWS })
          setFilterArc(undefined)
          setFilterVolumeType(undefined)

          const url = new URL(window.location.href)
          url.search = ''
          window.history.replaceState({}, '', url)
          return reload()
        }}
      ></ListToolBar>
      <Table<TidbMgmtServicev1Sku>
        columns={columns}
        rowKey="id"
        dataSource={dataSource
          .filter(
            (v) =>
              (!filterVolumeType ||
                v.dataStorage?.volumeType === filterVolumeType) &&
              (!filterArc || v.cpuArch === filterArc) &&
              (!filterDisplayName || v.spuDisplayName === filterDisplayName) &&
              (!spuKey || v.spuKey === spuKey)
          )
          .sort((v1, v2) => {
            return parseInt(v2.id!) - parseInt(v1.id!)
          })}
        loading={loading}
        pagination={paginationProps}
        size="small"
        onChange={onTableChange}
      ></Table>
      <ModalForm<SKUFormType>
        visible={!!createForm}
        name="createSKU"
        title={'Create SKU'}
        formLayout="vertical"
        width={1200}
        getFields={renderCreateFormFields}
        onSubmit={handleCreate}
        onCancel={handleCancel}
        maskClosable={false}
        destoryOnClose={true}
      />
      <ModalForm<SKUFormType>
        visible={!!modifyForm}
        name="modifySPU"
        formLayout="vertical"
        title={'Modify SPU'}
        width={1200}
        getFields={renderModifyFormFields}
        onSubmit={handleModify}
        onCancel={handleCancelModify}
        maskClosable={false}
        destoryOnClose={true}
      />
    </div>
  )
}
