import { Button, Space, Modal, Table, Typography } from 'antd'
import { ColumnsType } from 'antd/lib/table'
import { useCallback, useMemo, useState } from 'react'

import {
  iAMServiceCreatePolicy,
  iAMServiceListPolicies
} from 'apiClient/services/core-server'
import {
  V1CreatePolicyRequest,
  V1Permission,
  V1Policy
} from 'apiClient/services/core-server/interface'
import CollapseCell from 'components/CollapseCell'
import ModalForm from 'components/ModalForm'
import SearchBar from 'components/SearchBar'
import { useTable, ListToolBar } from 'components/Table'
import {
  getPolicyTypeLabel,
  showErrorModal,
  toListDataResponse
} from 'pages/IAM/utils'

import PolicyModalForm from './Policy/Forms/PolicyForm'

function NestedTable({ privileges }: { privileges: V1Permission[] }) {
  const renderItem = useCallback(({ resource, operations }: V1Permission) => {
    return (
      <Space>
        <Typography>{resource}</Typography>
        <Typography>:</Typography>
        <Typography>{operations?.join('|')}</Typography>
      </Space>
    )
  }, [])

  const memoList = useMemo(() => privileges, [privileges])

  return <CollapseCell<V1Permission> list={memoList} renderItem={renderItem} />
}

export default function Policies() {
  const [searchParams, setSearchParams] = useState<{ nameLike?: string }>({
    nameLike: undefined
  })
  const [createPolicy, setCreatePolicy] = useState(false)

  const getData = (params?: Partial<PageInfo>) =>
    iAMServiceListPolicies({
      page: params?.page,
      perPage: params?.pageSize,
      nameLike: searchParams.nameLike
    }).then((response) => toListDataResponse(response, (data) => data.policies))

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

  const renderPermissionCell = useCallback((record: V1Policy) => {
    const permissions = record.permissions || []
    return <NestedTable privileges={permissions} />
  }, [])

  const columns: ColumnsType<V1Policy> = [
    {
      title: 'Name',
      render: (_: any, record) => {
        return <a href={'/iam/role/policies/' + record.name}>{record.name}</a>
      }
    },
    {
      title: 'Description',
      render: (_: any, record) => {
        return record.description
      }
    },
    {
      title: 'Type',
      render: (_: any, record) => {
        return getPolicyTypeLabel(record.type)
      }
    },
    {
      title: 'Permissions',
      render: renderPermissionCell
    }
  ]

  const onSearch = (query: { nameLike?: string }) => {
    let newQuery: { [key: string]: any } = { ...query }
    newQuery.page = 1
    setSearchParams(newQuery)
    return reload()
  }

  const actions = useMemo(
    () => [
      <SearchBar
        defaultValue={searchParams}
        options={['nameLike']}
        labels={['Name']}
        fetcher={onSearch}
      />,
      <Button
        type="primary"
        onClick={() => {
          setCreatePolicy(true)
        }}
      >
        Create
      </Button>
    ],
    [searchParams]
  )

  const renderCreateFormFields = useCallback(() => {
    return <PolicyModalForm isEdit={false} />
  }, [createPolicy])

  const handleCreate = useCallback(
    async (payload: V1CreatePolicyRequest) => {
      const req = {
        ...payload
      }
      try {
        await iAMServiceCreatePolicy(req)
        Modal.success({
          title: 'Info',
          content: (
            <div>
              <p>Policy has been created</p>
            </div>
          ),
          onOk() {}
        })
        setCreatePolicy(false)
        reload()
      } catch (error) {
        showErrorModal(error)
      }
    },
    [reload]
  )

  const handleCancelCreate = useCallback(() => {
    setCreatePolicy(false)
  }, [])

  return (
    <div>
      <ListToolBar reload={reload} actions={actions} />

      <Table<V1Policy>
        rowKey="id"
        columns={columns}
        dataSource={dataSource}
        loading={loading}
        pagination={paginationProps}
        size="small"
        onChange={onTableChange}
      ></Table>

      <ModalForm<V1CreatePolicyRequest>
        visible={!!createPolicy}
        name="createPolicy"
        title={'Create a Policy'}
        getFields={renderCreateFormFields}
        onSubmit={handleCreate}
        onCancel={handleCancelCreate}
        width={800}
      />
    </div>
  )
}
