import { PlusOutlined, ReloadOutlined } from '@ant-design/icons'
import {
  Button as UIKitButton,
  Group,
  Modal as UIKitModal
} from '@tidbcloud/uikit'
import { IconFileSearch02 } from '@tidbcloud/uikit/icons'
import {
  Table,
  Space,
  Typography,
  Button,
  Form,
  Input,
  notification
} from 'antd'
import { Tabs, Select } from 'antd'
import TextArea from 'antd/lib/input/TextArea'
import { ColumnsType } from 'antd/lib/table'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'

import { getOrgProjects } from 'apiClient/services/account'
import {
  listClusters,
  o11yControllerCreateCluster,
  useO11yControllerListClusters
} from 'apiClient/services/devops'
import {
  ClusterCluster,
  CloudConfigControllerSearchClusterComponentsClusterType,
  O11yCluster,
  O11yCreateClusterRequest,
  OperationOperationTarget
} from 'apiClient/services/devops/interface'
import ModalForm from 'components/ModalForm'
import { useTable } from 'components/Table'
import { ClusterComponentVersions } from 'pages/ConfigCenter/Component/ClusterComponentVersions'
import { getErrorMessage } from 'utils/error'
import { capitalize } from 'utils/string'

import CreateOperation from '../../Devops/Operations/CreateOperation'
import { BYOCOpsAuditLog } from '../TenantDetail/BYOCAuditLog'

export const ClusterInfo: React.FC<React.PropsWithChildren<unknown>> = () => {
  return (
    <>
      <Tabs defaultActiveKey="dedicated">
        <Tabs.TabPane tab="Dedicated" key="dedicated">
          <DedicatedClusters />
        </Tabs.TabPane>

        <Tabs.TabPane tab="Starter & Essential" key="serverless">
          <ServerlessClusters />
        </Tabs.TabPane>

        <Tabs.TabPane tab="Premium & BYOC" key="nextgen">
          <NextGenClusters />
        </Tabs.TabPane>

        <Tabs.TabPane tab="Resource Pools" key="resource_pools">
          <ResourcePools />
        </Tabs.TabPane>

        <Tabs.TabPane tab="BYOC M1" key="byoc">
          <ByocCluster />
        </Tabs.TabPane>
        <Tabs.TabPane tab="BYOC OPS Audit Log" key="byoc_ops_audit_log">
          <BYOCOpsAuditLog />
        </Tabs.TabPane>
      </Tabs>
    </>
  )
}

const TenantComponentVersionsAction = ({
  clusterType,
  title
}: {
  clusterType: CloudConfigControllerSearchClusterComponentsClusterType
  title: string
}) => {
  const { org_id } = useParams<{ org_id: string }>()
  const [opened, setOpened] = useState(false)

  return (
    <>
      <UIKitButton
        variant="default"
        leftSection={<IconFileSearch02 size={16} />}
        onClick={() => setOpened(true)}
      >
        Component Versions
      </UIKitButton>
      <UIKitModal
        opened={opened}
        onClose={() => setOpened(false)}
        title={title}
        size="95vw"
        padding="lg"
      >
        <ClusterComponentVersions
          fixedClusterType={clusterType}
          scope="tenant"
          tenantId={org_id}
        />
      </UIKitModal>
    </>
  )
}

const DedicatedClusters: React.FC<React.PropsWithChildren<unknown>> = () => {
  const { org_id } = useParams<{ org_id: string }>()
  const getData = (params?: Partial<PageInfo>) =>
    listClusters({
      deploy_type: 'DEPLOY_TYPE_DEDICATED',
      page: params?.page,
      per_page: params?.pageSize,
      tenant_id: [org_id]
    })

  const { dataSource, loading, paginationProps, onTableChange } = useTable<
    ListData<ClusterCluster>
  >(getData, [], {
    pagination: true
  })

  // const [cluster, setCluster] = useState<FormsTenantCluster | null>(null)

  const columns = useMemo(() => {
    const cols: ColumnsType<ClusterCluster> = [
      {
        title: 'Cluster',
        width: 180,
        fixed: 'left',
        dataIndex: 'id',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 180 }}
                ellipsis={{ tooltip: record.name }}
              >
                {record.name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type="secondary">{record.id}</Typography.Text>
          </Space>
        )
      },
      {
        title: 'Project',
        width: 180,
        fixed: 'left',
        dataIndex: 'project_id',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 180 }}
                ellipsis={{ tooltip: record.project_name }}
              >
                {record.project_name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type="secondary">
              {record.project_id}
            </Typography.Text>
          </Space>
        )
      },
      {
        title: 'Status',
        dataIndex: 'status',
        render: (_: any, { status }: ClusterCluster) =>
          status ? status.replace('USER_CLUSTER_STATUS_', '') : '-',
        width: 90
      },
      ...['provider', 'region'].map((_) => ({
        title: capitalize(_),
        dataIndex: _,
        width: 90
      })),
      {
        title: 'Version',
        dataIndex: 'version',
        width: 90
      },
      {
        title: 'Action',
        key: 'action',
        fixed: 'right',
        render: (_: any, record: ClusterCluster) => (
          <Space>
            <Link to={`/orgs/${org_id}/clusters/${record.id}`}>Detail</Link>
          </Space>
        ),
        width: 100
      }
    ]
    return cols
  }, [])

  // // use tenant_name in session storage for no query params case
  // const [nameInStorage] = useSessionStorageState('tenant_name')

  return (
    <>
      <Table<ClusterCluster>
        columns={columns}
        rowKey="id"
        dataSource={dataSource}
        loading={loading}
        pagination={paginationProps}
        onChange={onTableChange}
        size="small"
        scroll={{ x: 1200 }}
      />
    </>
  )
}

const NextGenClusters: React.FC<React.PropsWithChildren<unknown>> = () => {
  const { org_id } = useParams<{ org_id: string }>()
  const getData = (params?: Partial<PageInfo>) =>
    listClusters({
      deploy_type: 'DEPLOY_TYPE_NEXTGEN',
      page: params?.page,
      per_page: params?.pageSize,
      tenant_id: [org_id]
    })

  const { dataSource, loading, paginationProps, onTableChange } = useTable<
    ListData<ClusterCluster>
  >(getData, [], {
    pagination: true
  })

  // const [cluster, setCluster] = useState<FormsTenantCluster | null>(null)

  const columns = useMemo(() => {
    const cols: ColumnsType<ClusterCluster> = [
      {
        title: 'Cluster',
        width: 180,
        fixed: 'left',
        dataIndex: 'id',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 180 }}
                ellipsis={{ tooltip: record.name }}
              >
                {record.name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type="secondary">{record.id}</Typography.Text>
          </Space>
        )
      },
      {
        title: 'Status',
        dataIndex: 'status',
        render: (_: any, { status }: ClusterCluster) =>
          status ? status.replace('USER_CLUSTER_STATUS_', '') : '-',
        width: 90
      },
      {
        title: 'Service Plan',
        dataIndex: 'service_plan',
        render: (_: any, { service_plan }: ClusterCluster) =>
          service_plan ? service_plan : '-',
        width: 90
      },
      ...['provider', 'region'].map((_) => ({
        title: capitalize(_),
        dataIndex: _,
        width: 90
      })),
      {
        title: 'TiDB Tag',
        dataIndex: 'nextgen_details',
        render: (details: any) => details?.tidb_tag || '-',
        width: 120
      },
      {
        title: 'Action',
        key: 'action',
        fixed: 'right',
        render: (_: any, record: ClusterCluster) => (
          <Space>
            <Link to={`/orgs/${org_id}/clusters/${record.id}`}>Detail</Link>
          </Space>
        ),
        width: 100
      }
    ]
    return cols
  }, [])

  // // use tenant_name in session storage for no query params case
  // const [nameInStorage] = useSessionStorageState('tenant_name')

  return (
    <>
      <Group justify="flex-start" mb={16}>
        <TenantComponentVersionsAction
          clusterType={
            CloudConfigControllerSearchClusterComponentsClusterType.LOGICAL_CLUSTER
          }
          title="Cluster Component Versions"
        />
      </Group>
      <Table<ClusterCluster>
        columns={columns}
        rowKey="id"
        dataSource={dataSource}
        loading={loading}
        pagination={paginationProps}
        onChange={onTableChange}
        size="small"
        scroll={{ x: 1200 }}
      />
    </>
  )
}

const ServerlessClusters: React.FC<React.PropsWithChildren<unknown>> = () => {
  const { org_id } = useParams<{ org_id: string }>()
  const getData = (params?: Partial<PageInfo>) =>
    listClusters({
      deploy_type: 'DEPLOY_TYPE_SERVERLESS',
      page: params?.page,
      per_page: params?.pageSize,
      tenant_id: [org_id]
    })

  const { dataSource, loading, paginationProps, onTableChange } = useTable<
    ListData<ClusterCluster>
  >(getData, [], {
    pagination: true
  })

  // const [cluster, setCluster] = useState<FormsTenantCluster | null>(null)

  const columns = useMemo(() => {
    const cols: ColumnsType<ClusterCluster> = [
      {
        title: 'Cluster',
        width: 180,
        fixed: 'left',
        dataIndex: 'id',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 180 }}
                ellipsis={{ tooltip: record.name }}
              >
                {record.name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type="secondary">{record.id}</Typography.Text>
          </Space>
        )
      },
      {
        title: 'Project',
        width: 180,
        fixed: 'left',
        dataIndex: 'project_id',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 180 }}
                ellipsis={{ tooltip: record.project_name }}
              >
                {record.project_name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type="secondary">
              {record.project_id}
            </Typography.Text>
          </Space>
        )
      },
      {
        title: 'Status',
        dataIndex: 'status',
        render: (_: any, { status }: ClusterCluster) =>
          status ? status.replace('USER_CLUSTER_STATUS_', '') : '-',
        width: 90
      },
      {
        title: 'Service Plan',
        dataIndex: 'service_plan',
        render: (_: any, { service_plan }: ClusterCluster) =>
          service_plan ? service_plan : '-',
        width: 90
      },
      ...['provider', 'region'].map((_) => ({
        title: capitalize(_),
        dataIndex: _,
        width: 90
      })),
      {
        title: 'Version',
        dataIndex: 'version',
        width: 90
      },
      {
        title: 'Action',
        key: 'action',
        fixed: 'right',
        render: (_: any, record: ClusterCluster) => (
          <Space>
            <Link to={`/orgs/${org_id}/clusters/${record.id}`}>Detail</Link>
          </Space>
        ),
        width: 100
      }
    ]
    return cols
  }, [])

  // // use tenant_name in session storage for no query params case
  // const [nameInStorage] = useSessionStorageState('tenant_name')

  return (
    <>
      <Table<ClusterCluster>
        columns={columns}
        rowKey="id"
        dataSource={dataSource}
        loading={loading}
        pagination={paginationProps}
        onChange={onTableChange}
        size="small"
        scroll={{ x: 1200 }}
      />
    </>
  )
}

const ResourcePools: React.FC<React.PropsWithChildren<unknown>> = () => {
  const { org_id } = useParams<{ org_id: string }>()
  const getData = (params?: Partial<PageInfo>) =>
    listClusters({
      is_resource_pool: true,
      tenant_id: [org_id]
    })

  const { dataSource, loading, paginationProps, onTableChange, reload } =
    useTable<ListData<ClusterCluster>>(getData, [], {
      pagination: false
    })

  // const [cluster, setCluster] = useState<FormsTenantCluster | null>(null)

  const columns = useMemo(() => {
    const cols: ColumnsType<ClusterCluster> = [
      {
        title: 'Cluster',
        width: 130,
        fixed: 'left',
        dataIndex: 'id',
        render: (_, record) => (
          <Space direction="vertical">
            {record.name ? (
              <Typography.Text
                style={{ width: 180 }}
                ellipsis={{ tooltip: record.name }}
              >
                {record.name}
              </Typography.Text>
            ) : (
              <span style={{ color: '#aaa' }}>-</span>
            )}
            <Typography.Text type="secondary">{record.id}</Typography.Text>
          </Space>
        )
      },
      {
        title: 'Service Plan',
        dataIndex: 'service_plan',
        render: (_: any, { service_plan }: ClusterCluster) =>
          service_plan ? service_plan : '-',
        width: 75
      },
      {
        title: 'Provider',
        dataIndex: 'provider',
        width: 60
      },
      {
        title: 'Region',
        dataIndex: 'region',
        width: 90
      },
      /*
      ...['provider', 'region'].map((_) => ({
        title: capitalize(_),
        dataIndex: _,
        width: 90
      })),*/
      {
        title: 'Default In Region',
        dataIndex: 'resource_pool_details',
        render: (details: any) => (details?.is_default ? 'Yes' : 'No'),
        width: 60
      },
      {
        title: 'Logical Region',
        dataIndex: 'logical_region',
        render: (_: any, { logical_region }: ClusterCluster) =>
          logical_region ? logical_region : '-',
        width: 90
      },
      {
        title: 'TiKV Tag',
        dataIndex: 'resource_pool_details',
        render: (details: any) => details?.tikv_tag || '-',
        width: 120
      },
      {
        title: 'Instance Limit',
        dataIndex: 'resource_pool_details?.instance_limit',
        render: (_: any, { resource_pool_details }: ClusterCluster) =>
          resource_pool_details?.instance_limit
            ? resource_pool_details.instance_limit
            : '-',
        width: 50
      },
      {
        title: 'Action',
        key: 'action',
        fixed: 'right',
        render: (_: any, record: ClusterCluster) => (
          <Space>
            <Link to={`/orgs/${org_id}/clusters/${record.id}`}>Detail</Link>
          </Space>
        ),
        width: 50
      }
    ]
    return cols
  }, [])

  return (
    <>
      <Group justify="space-between" mb={16}>
        <TenantComponentVersionsAction
          clusterType={
            CloudConfigControllerSearchClusterComponentsClusterType.SHARED_POOL
          }
          title="Cluster Component Versions"
        />
        <Button type="default">
          <CreateOperation
            target_type={OperationOperationTarget.tenant}
            target_id={org_id}
            op="CreateResourcePool"
            init_categories={['resource-pool']}
            bottom_name="Create"
          />
        </Button>
      </Group>
      <Table<ClusterCluster>
        columns={columns}
        rowKey="id"
        dataSource={dataSource}
        loading={loading}
        pagination={paginationProps}
        onChange={onTableChange}
        size="small"
        scroll={{ x: 1200 }}
      />
    </>
  )
}

const ByocAvailableVendors = ['aws']
const ByocAvailableRegions = ['us-west-2']

const ByocCluster: React.FC<React.PropsWithChildren<unknown>> = () => {
  const { org_id } = useParams<{ org_id: string }>()

  const [curVendor, setCurVector] = useState<string>('aws')
  const [curRegion, setCurRegion] = useState<string>('us-west-2')
  const [createModalOpen, setCreateModalOpen] = useState<boolean>(false)

  const { data, isLoading, refetch } = useO11yControllerListClusters(
    {
      orgID: org_id,
      vendor: curVendor,
      region: curRegion
    },
    {
      query: {
        refetchOnMount: false,
        refetchInterval: false,
        onError: (err) => {
          notification.error({ message: getErrorMessage(err) })
        }
      }
    }
  )

  const columns: ColumnsType<O11yCluster> = [
    {
      title: 'ID',
      render: (_: any, record) => {
        return record.id
      }
    },
    {
      title: 'Project ID',
      render: (_: any, record) => {
        return record.projectID
      }
    },
    {
      title: 'Application ID',
      render: (_: any, record) => record.applicationID
    },
    {
      title: 'Vector',
      render: (_: any, record) => {
        return record.vendor
      }
    },
    {
      title: 'Region',
      render: (_: any, record) => {
        return record.region
      }
    },
    {
      title: 'Action',
      render: (_: any, record) => (
        <div>
          <Button type="link">
            <Link
              to={`/orgs/${org_id}/byoc-clusters/${record.id}?vendor=${record.vendor}&region=${record.region}`}
            >
              Detail
            </Link>
          </Button>
        </div>
      )
    }
  ]

  const handleCreate = useCallback(
    async (payload: O11yCreateClusterRequest) => {
      return o11yControllerCreateCluster(payload)
        .then(() => {
          setCreateModalOpen(false)
          refetch()
        })
        .catch((e) => {
          // HACK: overide the default error of axios to enable showing error message in ModalForm
          if (e.response.data.errmsg && e.response.status)
            throw {
              response: {
                data: {
                  message: e.response.status + ': ' + e.response.data.errmsg
                }
              }
            }
          else throw e
        })
    },
    [refetch]
  )

  return (
    <>
      <div
        style={{
          display: 'flex',
          gap: '10px',
          justifyContent: 'space-between'
        }}
      >
        <div style={{ display: 'flex', gap: '10px' }}>
          <Select
            options={ByocAvailableVendors.map((v) => ({ label: v, value: v }))}
            value={curVendor}
            style={{ width: 'auto', alignSelf: 'flex-start' }}
            onChange={(e: string) => {
              setCurVector(e)
              refetch()
            }}
            defaultValue={curVendor}
          ></Select>
          <Select
            options={ByocAvailableRegions.map((v) => ({ label: v, value: v }))}
            value={curRegion}
            style={{ width: 'auto', alignSelf: 'flex-start' }}
            onChange={(e: string) => {
              setCurRegion(e)
              refetch()
            }}
            defaultValue={curRegion}
          ></Select>
        </div>

        <div>
          <Button
            type="primary"
            icon={<PlusOutlined />}
            onClick={() => {
              setCreateModalOpen(true)
            }}
          >
            Create Cluster
          </Button>
          &nbsp;
          <Button
            icon={<ReloadOutlined />}
            onClick={() => {
              refetch()
            }}
          ></Button>
        </div>
      </div>

      <br></br>

      <Table<O11yCluster>
        columns={columns}
        rowKey="id"
        dataSource={data?.data.data?.clusters}
        loading={isLoading}
        pagination={{ pageSize: 10 }}
        size="small"
      />

      <ModalForm<O11yCreateClusterRequest>
        visible={!!createModalOpen}
        name="create byoc cluster"
        title="Create Byoc Cluster"
        getFields={() => <CreateByocClusterFormField org_id={org_id} />}
        onSubmit={handleCreate}
        okText="Create"
        onCancel={() => {
          setCreateModalOpen(false)
        }}
      />
    </>
  )
}

const CreateByocClusterFormField = ({ org_id }: { org_id: string }) => {
  const inputStyle = { width: 300 }
  const [projects, setProjects] = useState<string[]>([])

  async function fetchProjects() {
    const data = (
      await getOrgProjects(org_id, {
        page: 1,
        page_size: 100
      })
    ).data
    setProjects(
      data.items
        ?.map((p) => p.id)
        .filter((id): id is string => id !== undefined) || []
    )
  }

  useEffect(() => {
    fetchProjects()
  }, [])

  return (
    <div style={{ width: '600px' }}>
      <Form.Item name="orgID" initialValue={org_id} label="Tenant ID">
        <Input style={inputStyle} disabled={true} />
      </Form.Item>

      <Form.Item
        name="projectID"
        label="Project ID"
        rules={[
          {
            required: true,
            message: 'Please input project id'
          }
        ]}
      >
        <Select
          style={inputStyle}
          options={projects.map((v) => ({ label: v, value: v }))}
        />
      </Form.Item>

      <Form.Item
        name="applicationID"
        label="Application ID"
        rules={[
          {
            required: true,
            message: 'Please input application id'
          }
        ]}
      >
        <Input style={inputStyle} />
      </Form.Item>

      <Form.Item
        name="vendor"
        label="Vendor"
        rules={[
          {
            required: true,
            message: 'Please input vendor'
          }
        ]}
      >
        <Select
          style={inputStyle}
          options={ByocAvailableVendors.map((v) => ({ label: v, value: v }))}
        />
      </Form.Item>

      <Form.Item
        name="region"
        label="Region"
        rules={[
          {
            required: true,
            message: 'Please input region'
          }
        ]}
      >
        <Select
          style={inputStyle}
          options={ByocAvailableRegions.map((v) => ({ label: v, value: v }))}
        />
      </Form.Item>

      <Form.Item
        name="agentAccessARN"
        label="Agent Access ARN"
        rules={[
          {
            required: true,
            message: 'Please input agent access arn'
          }
        ]}
      >
        <Input style={inputStyle} />
      </Form.Item>

      <Form.Item
        name="agentManagerARN"
        label="Agent Manager ARN"
        rules={[
          {
            required: true,
            message: 'Please input agent access arn'
          }
        ]}
      >
        <Input style={inputStyle} />
      </Form.Item>

      <Form.Item name="ruleTemplateID" label="Rule Template ID">
        <Input style={inputStyle} />
      </Form.Item>

      <Form.Item name="tags" label="Tags">
        <Select mode="tags" style={inputStyle} />
      </Form.Item>

      <Form.Item name="note" label="Note">
        <TextArea style={inputStyle}></TextArea>
      </Form.Item>
    </div>
  )
}
