import { Box, Button, ComboboxData, Flex, Typography, Divider } from '@tidbcloud/uikit'
import { FormSelect, MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { IconBuilding05, IconPlus } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import type { ReactNode } from 'react'
import { useFormContext, useFieldArray } from 'react-hook-form'

import { RBACRoles, RBACRoleUINames } from 'dbaas/contexts/access-control'
import { getBFFTiDB } from 'dbaas/features/ClusterManagement/tidb'
import { useTiDBServiceListTidbs } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta2'
import { TiDBServiceListTidbsServicePlansItem } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'
import creditCardIcon from 'media/icon/credit_card.png'
import crown3dIcon from 'media/icon/crown_3d.png'
import eye3dIcon from 'media/icon/eye_3d.png'
import memo3dIcon from 'media/icon/memo_3d.png'
import pencil3dIcon from 'media/icon/pencil_3d.png'

import { RoleScopeTypes } from './RolesView'
import { ScopeRoleSelect } from './ScopeRoleSelect'
export { renderRoleOption } from './ScopeRoleSelect'

export interface RoleValue {
  role: string
  scope: string
}

const roleIcon = (src: string): ReactNode => (
  <Box component="img" src={src} alt="" w={24} h={24} sx={{ display: 'block' }} />
)

export const orgRoleOptions = [
  {
    value: RBACRoles.OrgOwner,
    label: RBACRoleUINames[RBACRoles.OrgOwner],
    icon: roleIcon(crown3dIcon),
    description: 'Full control of all users, billing, audits, clusters, instances, and projects.'
  },
  {
    value: RBACRoles.OrgMember,
    label: RBACRoleUINames[RBACRoles.OrgMember],
    icon: roleIcon(eye3dIcon),
    description: 'Default access to view organization meta information.'
  },
  {
    value: RBACRoles.OrgBillAdmin,
    label: RBACRoleUINames[RBACRoles.OrgBillAdmin],
    icon: roleIcon(creditCardIcon),
    description: 'Manage all billing information for the organization.'
  },
  {
    value: RBACRoles.OrgBillViewer,
    label: RBACRoleUINames[RBACRoles.OrgBillViewer],
    icon: roleIcon(creditCardIcon),
    description: 'View billing information for the organization.'
  },
  {
    value: RBACRoles.OrgAuditAdmin,
    label: RBACRoleUINames[RBACRoles.OrgAuditAdmin],
    icon: roleIcon(memo3dIcon),
    description: 'Manage console audit logging settings.'
  }
]

export const projectRoleOptions = [
  {
    value: RBACRoles.ProjectOwner,
    label: RBACRoleUINames[RBACRoles.ProjectOwner],
    icon: roleIcon(crown3dIcon),
    description: 'Manage all project-level settings and resources.'
  },
  {
    value: RBACRoles.ProjectViewer,
    label: RBACRoleUINames[RBACRoles.ProjectViewer],
    icon: roleIcon(eye3dIcon),
    description: 'Read-only project-level role for visibility and monitoring.'
  },
  {
    value: RBACRoles.ProjectDev,
    label: RBACRoleUINames[RBACRoles.ProjectDev],
    icon: roleIcon(pencil3dIcon),
    description: 'Project-level role for users who need full data operation capabilities.'
  },
  {
    value: RBACRoles.ProjectReadOnly,
    label: RBACRoleUINames[RBACRoles.ProjectReadOnly],
    icon: roleIcon(memo3dIcon),
    description: 'Project-level role for users who need read-only access to the database.'
  }
]

export const instanceRoleOptions: { value: string; label: string; icon?: ReactNode; description?: string }[] = [
  {
    value: RBACRoles.InstanceAdmin,
    label: RBACRoleUINames[RBACRoles.InstanceAdmin],
    icon: roleIcon(crown3dIcon),
    description: 'Full control of instance, configurations, and data access.'
  },
  {
    value: RBACRoles.InstanceViewer,
    label: RBACRoleUINames[RBACRoles.InstanceViewer],
    icon: roleIcon(eye3dIcon),
    description: 'View instance information without data access.'
  }
] as const

export const RolesSelectOptions = [
  {
    group: 'Organization level',
    items: orgRoleOptions
  },
  {
    group: 'Project level',
    items: projectRoleOptions
  },
  {
    group: 'Instance level',
    items: instanceRoleOptions
  }
]

export const RolesSelect = ({ name = 'roles', options = orgRoleOptions }: { name: string; options?: ComboboxData }) => {
  const { control, watch } = useFormContext()

  const { append } = useFieldArray({
    control,
    name
  })

  const data = watch(name)

  const columns: MRT_ColumnDef<RoleValue>[] = [
    {
      header: 'Role',
      accessorKey: 'role',
      size: 150,
      mantineTableHeadCellProps: {
        style: { paddingLeft: 16 }
      },
      mantineTableBodyCellProps: {
        style: { padding: '12px 16px' }
      },
      Cell: ({ row }) => {
        return <FormSelect name={`${name}.${row.index}.role`} data={options} />
      }
    },
    {
      header: 'Scope',
      accessorKey: 'scope',
      size: 150,
      mantineTableHeadCellProps: {
        style: { paddingLeft: 16 }
      },
      mantineTableBodyCellProps: {
        style: { padding: '12px 16px' }
      },
      Cell: ({ row }) => {
        return (
          <FormSelect
            name={`${name}.${row.index}.scope`}
            disabled
            leftSection={<IconBuilding05 />}
            data={[{ label: 'Organization', value: 'org' }]}
          />
        )
      }
    }
  ]

  return (
    <ProTable
      columns={columns}
      data={data}
      emptyMessage="No Data"
      // TODO: remove this after multiple roles are supported
      enableBottomToolbar={false}
      mantineTableBodyProps={{
        hidden: data?.length === 0
      }}
      renderBottomToolbar={
        <Flex
          py={10}
          justify="space-between"
          align="center"
          w="100%"
          px="md"
          sx={(theme) =>
            data?.length === 0
              ? {}
              : {
                  borderTop: `1px solid ${theme.colors.carbon[4]}`
                }
          }
        >
          <Button
            variant="default"
            size="sm"
            onClick={() => append({ role: RBACRoles.OrgOwner, scope: 'org' })}
            leftSection={<IconPlus size={14} />}
          >
            Add Role
          </Button>
          <Typography variant="body-lg" c="carbon.7">
            Total roles: {data?.length}
          </Typography>
        </Flex>
      }
    />
  )
}

export const AdvancedRolesSelect = observer(() => {
  const {
    store: {
      userProfile: { projects },
      tenantData
    }
  } = useStores()

  const projectOptions = projects.map((p) => ({
    value: p.id,
    label: p.name,
    projectType: p.type
  }))

  const { data: tidbs } = useTiDBServiceListTidbs(
    {
      orgId: tenantData.id,
      pageSize: 200,
      skip: 0,
      servicePlans: [
        TiDBServiceListTidbsServicePlansItem.Starter,
        TiDBServiceListTidbsServicePlansItem.Essential,
        TiDBServiceListTidbsServicePlansItem.Essential_V2,
        TiDBServiceListTidbsServicePlansItem.Premium,
        TiDBServiceListTidbsServicePlansItem.BYOC
      ]
    },
    {
      query: {
        refetchOnWindowFocus: false
      }
    }
  )

  const instanceOptions =
    tidbs?.tidbs?.map((t) => {
      const instance = getBFFTiDB(t)
      return {
        value: instance.tidbId || '',
        label: instance.displayName || '',
        servicePlan: instance.servicePlan
      }
    }) || []

  return (
    <div>
      <Flex direction="column" gap={16}>
        <Box>
          <Typography variant="label-lg" mb="sm" c="carbon.8" fw={700}>
            Project Access
          </Typography>
          <ScopeRoleSelect
            name="project_roles"
            roleSelectProps={{ data: projectRoleOptions }}
            scopeSelectProps={{ data: projectOptions, searchable: true }}
            defaultRole={RBACRoles.ProjectViewer}
            scopeType={RoleScopeTypes.PROJECT}
            disabledTips="No available projects."
          />
        </Box>
        <Divider />
        <Box>
          <Typography variant="label-lg" mb="sm" c="carbon.8" fw={700}>
            Instance Access
          </Typography>
          <ScopeRoleSelect
            name="cluster_roles"
            roleSelectProps={{ data: instanceRoleOptions }}
            scopeSelectProps={{ data: instanceOptions || [], searchable: true }}
            defaultRole={RBACRoles.InstanceViewer}
            scopeType={RoleScopeTypes.TIDB}
            disabledTips="No available instances."
          />
        </Box>
      </Flex>
    </div>
  )
})
