import { Controller, useFormContext } from 'react-hook-form';
import { useQuery } from 'react-query';

import Checkbox, { CheckboxProps } from '@material-hu/mui/Checkbox';
import FormControlLabel from '@material-hu/mui/FormControlLabel';
import Grid from '@material-hu/mui/Grid';
import Tooltip from '@material-hu/mui/Tooltip';
import Typography from '@material-hu/mui/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';

import { useTranslation as usePermissionTranslation } from 'src/constants/permissionI18n';
import useAuth from 'src/contexts/JWTContext';
import useCommunityFeature from 'src/hooks/useCommunityFeature';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import { appsKeys } from 'src/pages/dashboard/Apps/queries';
import * as instancesService from 'src/services/instancesService';
import { CommunityFeature } from 'src/types/communityFeatures';
import { FeatureFlags } from 'src/types/featureFlags';
import { useLokaliseTranslation } from 'src/utils/i18n';
import {
  FakePermissions,
  fakeToRealPermissions,
  getPermissionsGroup,
  Permission,
  realToFakeMappings,
  realToFakePermissions,
} from 'src/utils/permissions';
import { instanceHasRoles } from 'src/utils/userUtils';

import CircularProgress from 'src/components/CircularProgress';

import { FieldValues } from '../../form';

import PermissionsByRole from './permissionsByRole';

const PermissionsTab = () => {
  const { t } = useLokaliseTranslation('users');
  const { t: pt } = usePermissionTranslation();
  const { instance } = useAuth();
  const { watch, setValue } = useFormContext<FieldValues>();
  const permissions = watch('permissions');
  const fakePermissions = realToFakePermissions(permissions);

  const canLiveStreaming = useCommunityFeature(
    CommunityFeature.VIEW_LIVESTREAM,
  );

  const handleChange: CheckboxProps['onChange'] = event =>
    setValue(
      'permissions',
      fakeToRealPermissions({
        ...fakePermissions,
        [event.target.name]: event.target.checked,
      }),
      { shouldDirty: true },
    );

  const { data: instancePermissions, isLoading } = useQuery(
    appsKeys.instanceCapabilities(instance?.id ?? ''),
    () => instancesService.getInstanceCapabilities({ id: instance?.id ?? 0 }),
    { select: r => r.data, enabled: !!instance?.id },
  );

  const allAreSelected = (permissionList: Permission[]) =>
    permissionList.every(p => fakePermissions[p]);

  const handleSelectAll = (permissionList: Permission[]) => {
    const newSelectedValue = !allAreSelected(permissionList);
    permissionList.forEach(permission => {
      fakePermissions[permission] = newSelectedValue;
    });
    setValue(
      'permissions',
      fakeToRealPermissions({
        ...fakePermissions,
      }),
      { shouldDirty: true },
    );
  };

  const canInteractWithExternalBot = useCommunityFeature(
    CommunityFeature.CAN_INTERACT_WITH_EXTERNAL_BOT,
  );
  const canViewExternalApps = useCommunityFeature(
    CommunityFeature.VIEW_EXTERNAL_APPS,
  );
  // TODO-SQGZ: Remove when available to all users.
  const employeeLifecycleEnabled = useFeatureFlag(
    FeatureFlags.VIEW_EMPLOYEE_LIFECYCLE,
  );
  const chatV1Enabled = useFeatureFlag(FeatureFlags.CHATS_V1_AVAILABLE);

  const atsEnabled = useCommunityFeature(CommunityFeature.ATS_ENABLED);

  function SelectAll({ permissionList }: { permissionList: Permission[] }) {
    return (
      <Button
        size="small"
        onClick={() => handleSelectAll(permissionList)}
      >
        {t(allAreSelected(permissionList) ? 'DESELECT_ALL' : 'SELECT_ALL')}
      </Button>
    );
  }

  if (instanceHasRoles(instance?.id ?? 0)) return <PermissionsByRole />;

  const renderPermissionItem = (permission: Permission) => {
    const truePermissions = Object.fromEntries(
      Object.entries(instancePermissions ?? {}).filter(
        ([key, value]) => key && !!value,
      ),
    );

    const isBlockedByInstance =
      permission in realToFakeMappings
        ? realToFakeMappings[permission as FakePermissions].some(p =>
            Object.keys(truePermissions).includes(p),
          )
        : Object.keys(truePermissions).includes(permission);

    return (
      <Tooltip
        title={isBlockedByInstance ? t('DISABLED') : ''}
        key={permission}
      >
        <FormControlLabel
          control={
            <Checkbox
              name={permission}
              checked={!!fakePermissions[permission] || isBlockedByInstance}
              onChange={handleChange}
              disabled={isBlockedByInstance}
            />
          }
          label={pt('PERMISSION', { context: permission })}
          sx={{ display: 'block' }}
        />
      </Tooltip>
    );
  };

  const workflowsEnabled = useFeatureFlag(FeatureFlags.WORKFLOWS_ENABLED);
  const competenciesEnabled = useFeatureFlag(FeatureFlags.COMPETENCIES_ENABLED);

  const permissionsGroup = getPermissionsGroup({
    canLiveStreaming,
    canInteractWithExternalBot,
    canViewExternalApps,
    chatV1Enabled,
    employeeLifecycleEnabled,
    atsEnabled,
    workflowsEnabled,
    competenciesEnabled,
  });

  return isLoading ? (
    <CircularProgress centered />
  ) : (
    <Controller
      name="permissions"
      render={() => (
        <Grid
          container
          columns={2}
        >
          {permissionsGroup.map(permissionGroup => (
            <Grid
              item
              xs
              key={permissionGroup.title}
              sx={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
              }}
            >
              <div>
                <Typography
                  variant="h5"
                  gutterBottom
                >
                  {t('TITLE', { context: permissionGroup.title })}
                </Typography>
                <SelectAll
                  permissionList={permissionGroup.list.filter(p => p !== null)}
                />
                {permissionGroup.list
                  .sort((a, b) =>
                    pt('PERMISSION', { context: a }).localeCompare(
                      pt('PERMISSION', { context: b }),
                    ),
                  )
                  .filter(p => p !== null)
                  .map(renderPermissionItem)}
              </div>
            </Grid>
          ))}
        </Grid>
      )}
    />
  );
};

export default PermissionsTab;
