import { FC, useCallback, useEffect, useState } from 'react'
import { FormContainer, FormContent, FormHeader } from '@maks-it.com/webui-components'
import { Offcanvas } from '@maks-it.com/webui-components'
import { CreateApiKey } from './CreateApiKey'
import { useAppSelector } from '../../redux/hooks'
import { deleteData, postData } from '../../axiosConfig'
import { ApiRoutes, GetApiRoute } from '../../AppMap'
import { PagedResponse } from '@maks-it.com/webui-contracts'
import { SearchApiKeyRequest } from '../../models/apiKey/search/SearchApiKeyRequest'
import { SearchApiKeyResponse } from '../../models/apiKey/search/SearchApiKeyResponse'
import { ApiKeyResponse } from '../../models/apiKey/ApiKeyResponse'
import {
  createColumn,
  createColumns,
  DataTable,
  DataTableFilter,
  DataTableLabel,
} from '@maks-it.com/webui-components'
import { EditApiKey } from './EditApiKey'
import { hasFlag } from '@maks-it.com/webui-core'
import { ScopeEntityType } from '../../models/ScopeEntityType'
import { ScopePermission } from '@maks-it.com/webui-core'


const SearchApiKey: FC = () => {

  const { identity } = useAppSelector(state => state.identity)

  const [pagedRequest, setPagedRequest] = useState<SearchApiKeyRequest>({})
  const [rawd, setRawd] = useState<PagedResponse<SearchApiKeyResponse> | undefined>(undefined)

  const [apiKeyId, setApiKeyId] = useState<string | undefined>(undefined)
  const [creating, setCreating] = useState<boolean>(false)

  const columns = createColumns([
    createColumn<SearchApiKeyResponse, 'id'>({
      id: 'id',
      accessorKey: 'id',
      header: 'Id',
      filter: (props, onFilterChange) => (
        <DataTableFilter
          type={'normal'}
          columnId={props.columnId}
          accessorKey={'id'}
          onFilterChange={onFilterChange}
          disabled={true}
        />
      ),
      cell: (props) => {
        const { value } = props
        return <DataTableLabel type={'normal'} value={value} />
      }
    }),
    createColumn<SearchApiKeyResponse, 'description'>({
      id: 'description',
      accessorKey: 'description',
      header: 'Description',
      filter: (props, onFilterChange) => (
        <DataTableFilter
          type={'normal'}
          columnId={props.columnId}
          accessorKey={'description'}
          onFilterChange={onFilterChange}
        />
      ),
      cell: (props) => (
        <DataTableLabel type={'normal'} value={props.value ?? ''} />
      ),
    }),
    createColumn<SearchApiKeyResponse, 'createdAt'>({
      id: 'createdAt',
      accessorKey: 'createdAt',
      header: 'Created At',
      filter: (props, onFilterChange) => (
        <DataTableFilter
          type={'normal'}
          columnId={props.columnId}
          accessorKey={'createdAt'}
          onFilterChange={onFilterChange}
        />
      ),
      cell: (props) => (
        <DataTableLabel type={'normal'} value={props.value} dataType={'date'} />
      ),
    }),
    createColumn<SearchApiKeyResponse, 'expiresAt'>({
      id: 'expiresAt',
      accessorKey: 'expiresAt',
      header: 'Expires At',
      filter: (props, onFilterChange) => (
        <DataTableFilter
          type={'normal'}
          columnId={props.columnId}
          accessorKey={'expiresAt'}
          onFilterChange={onFilterChange}
        />
      ),
      cell: (props) => (
        <DataTableLabel type={'normal'} value={props.value ?? ''} />
      ),
    }),
    createColumn<SearchApiKeyResponse, 'isGlobalAdmin'>({
      id: 'isGlobalAdmin',
      accessorKey: 'isGlobalAdmin',
      header: 'Global Admin',
      filter: (props, onFilterChange) => (
        <DataTableFilter
          type={'normal'}
          columnId={props.columnId}
          accessorKey={'isGlobalAdmin'}
          onFilterChange={onFilterChange}
          disabled={true}
        />
      ),
      cell: (props) => {
        const { value } = props
        return <DataTableLabel type={'normal'} value={value ? 'Yes' : 'No'} />
      },
    }),
  ])

  const loadData = useCallback(() => {
    postData<SearchApiKeyRequest, PagedResponse<SearchApiKeyResponse>>(GetApiRoute(ApiRoutes.apikeySearch).route, pagedRequest).then((response) => {
      setRawd(response.payload ?? undefined)
    }).finally(() => {})
  }, [pagedRequest])

  useEffect(() => loadData(), [loadData])


  const handleAddRow = () => {
    setCreating(true)
  }

  const handleEditRow = (ids: {[key: string]: string}) => {
    setApiKeyId(ids.id)
  }

  const handleDeleteRow = (ids: {[key: string]: string}) => {
    deleteData(GetApiRoute(ApiRoutes.apikeyDelete).route
      .replace('{apiKeyId}', ids.id)
    ).then((response) => {
      if (!response.ok) return
      loadData()
    })
  }

  const handleEditCancel = () => {
    setApiKeyId(undefined)
  }

  const handleFilterChange = (filters: { [filterId: string]: string }) => {
    setPagedRequest({
      ...pagedRequest,
      ...filters
    })
  }

  const handlePageChange = (pageNumber: number) => {
    setPagedRequest({
      ...pagedRequest,
      pageNumber
    })
  }

  const handleOnSubmitted = (_item?: ApiKeyResponse) => {
    setApiKeyId(undefined)

    setCreating(false)

    loadData()
  }

  if (!identity) return <></>

  const handleAllowAddRow = () => {
    if (identity.isGlobalAdmin)
      return true
    const hasCreateApiKey = identity.acls?.some(acl =>
      acl.entityType === ScopeEntityType.ApiKey && hasFlag(acl.scope, ScopePermission.Create))
    return !!hasCreateApiKey
  }

  const handleAllowEditRow = (ids: Record<string, string>) => {
    if (identity.isGlobalAdmin)
      return true

    const organizationId = ids.organizationId
    if (!organizationId) {
      return identity.acls?.some(acl =>
        acl.entityType === ScopeEntityType.ApiKey && hasFlag(acl.scope, ScopePermission.Write)) ?? false
    }

    const canEditApiKey = identity.acls
      ?.find(acl => acl.entityId == organizationId
        && acl.entityType === ScopeEntityType.ApiKey
        && hasFlag(acl.scope, ScopePermission.Write))

    return !!canEditApiKey
  }

  const handleAllowDeleteRow = (ids: Record<string, string>) => {
    if (identity.isGlobalAdmin)
      return true

    const organizationId = ids.organizationId
    if (!organizationId) {
      return identity.acls?.some(acl =>
        acl.entityType === ScopeEntityType.ApiKey && hasFlag(acl.scope, ScopePermission.Delete)) ?? false
    }

    const canDeleteApiKey = identity.acls
      ?.find(acl => acl.entityId == organizationId
        && acl.entityType === ScopeEntityType.ApiKey
        && hasFlag(acl.scope, ScopePermission.Delete))

    return !!canDeleteApiKey
  }

  return <>
    <FormContainer>
      <FormHeader>API Keys</FormHeader>
      <FormContent>
        <div className={'grid grid-cols-12 gap-4 w-full h-full'}>
          <DataTable
            colspan={12}
            rawd={rawd}
            columns={columns}
            storageKey={'SearchApiKey'}
            idFields={['id']}

            allowAddRow={handleAllowAddRow}
            onAddRow={handleAddRow}
            allowEditRow={handleAllowEditRow}
            onEditRow={handleEditRow}
            allowDeleteRow={handleAllowDeleteRow}
            onDeleteRow={handleDeleteRow}

            onFilterChange={handleFilterChange}
            onPreviousPage={handlePageChange}
            onNextPage={handlePageChange}
          />
        </div>

      </FormContent>
    </FormContainer>

    <Offcanvas isOpen={apiKeyId !== undefined}>
      {apiKeyId && <EditApiKey
        key={apiKeyId}
        apiKeyId={apiKeyId}
        cancelEnabled={true}
        onSubmitted={handleOnSubmitted}
        onCancel={handleEditCancel}
      />}
    </Offcanvas>

    {creating && (
      <CreateApiKey
        isOpen={true}
        onSubmitted={handleOnSubmitted}
        cancelEnabled={true}
        onCancel={() => setCreating(false)}
      />
    )}
  </>
}

export {
  SearchApiKey
}
