import { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Link,
  useNavigate,
  useParams,
  useSearchParams,
} from 'react-router-dom';

import { useModal } from '@material-hu/hooks/useModal';
import { IconX } from '@material-hu/icons/tabler';
import Container from '@material-hu/mui/Container';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import * as animations from '@material-hu/utils/animations';

import HuDialog from '@material-hu/components/design-system/Dialog';
import HuPills from '@material-hu/components/design-system/Pills';
import HuSpinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import HuSkeleton from '@material-hu/components/design-system/Skeleton';
import HuStepper from '@material-hu/components/design-system/Stepper';
import HuTabs from '@material-hu/components/design-system/Tabs';
import HuTitle from '@material-hu/components/design-system/Title';

import { useLokaliseTranslation } from 'src/utils/i18n';

import { roleStatusConfig } from '../../../constants';
import useRoleBasicInfo from '../../../hooks/useRoleBasicInfo';
import useRolesPermissions from '../../../hooks/useRolesPermissions';
import { rolesAndPermissionsRoutes } from '../../../routes';
import {
  type CreateRoleResponseType,
  RoleState,
  RoleType,
} from '../../../types';
import { roleSteps } from '../../constants';
import AssignmentStep from '../RoleSteps/AssignmentStep';
import BasicInformation from '../RoleSteps/BasicInformation';
import PermissionStep from '../RoleSteps/PermissionStep';
import ReviewStep from '../RoleSteps/ReviewStep';

import { type RoleStepperProps, type RoleStepperSteps } from './types';

const RoleStepper = ({ isNew }: RoleStepperProps) => {
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const { t } = useLokaliseTranslation('rolesAndPermissions');
  const { canManageRoles, canDefineRoles, canUpdateRolesAssignment } =
    useRolesPermissions();
  const { id: roleId } = useParams();
  const roleType = (searchParams.get('type') as RoleType) || RoleType.CUSTOM;

  const [createdRole, setCreatedRole] =
    useState<Partial<CreateRoleResponseType> | null>(null);

  const stepId = isNew ? null : (searchParams.get('step') as RoleStepperSteps);

  const { data: basicInformation, isLoading: basicInformationLoading } =
    useRoleBasicInfo(roleId!, !isNew);

  const currentRole = basicInformation || createdRole;
  const isActive = currentRole?.state === RoleState.ACTIVE;

  const [currentStep, setCurrentStep] = useState<RoleStepperSteps>(
    stepId || 'basicInformation',
  );

  const steps = useMemo(
    () =>
      roleSteps(t, isActive, {
        canManageRoles,
        canDefineRoles,
        canUpdateRolesAssignment,
      }),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [isActive, canManageRoles, canDefineRoles, canUpdateRolesAssignment],
  );

  useEffect(() => {
    if (!isNew && basicInformationLoading) return;
    if (steps.length === 0) return;
    const stepIsVisible = steps.some(s => s.id === currentStep);
    if (!stepIsVisible) {
      setCurrentStep(steps[0].id);
    }
  }, [isNew, basicInformationLoading, currentStep, steps]);

  const defaultTitle = t('create_role');

  const isPredefined = roleType !== RoleType.CUSTOM;
  const isAllUsersRolePredefined = roleType === RoleType.ALL_USERS;
  const isAdminRolePredefined = roleType === RoleType.ADMIN;

  const getAdjacentStepId = useCallback(
    (
      id: RoleStepperSteps,
      direction: 'next' | 'prev',
    ): RoleStepperSteps | undefined => {
      const idx = steps.findIndex(s => s.id === id);
      if (idx === -1) return undefined;
      const offset = direction === 'next' ? 1 : -1;
      return steps[idx + offset]?.id;
    },
    [steps],
  );

  const handleBasicInformationStepSubmit = useCallback(
    (role: CreateRoleResponseType) => {
      const nextStep =
        getAdjacentStepId('basicInformation', 'next') ?? 'review';
      setCurrentStep(nextStep);
      if (isNew) {
        setCreatedRole(role);

        if (role.id) {
          const newRoleURL = `${rolesAndPermissionsRoutes.edit(role.id)}?step=${nextStep}&type=${roleType}`;
          navigate(newRoleURL, { replace: true });
        }
      }
    },
    [navigate, isNew, roleType, getAdjacentStepId],
  );

  useEffect(() => {
    if (currentStep) {
      setSearchParams(
        { step: currentStep, type: roleType as RoleType },
        { replace: true },
      );
    }
  }, [currentStep, setSearchParams]);
  const [allowChangeStep, setAllowChangeStep] = useState(true);
  const [warnChangeStep, setWarnChangeStep] = useState(false);

  const changeTabModal = useModal(
    ({ changeStep }: { changeStep: () => void }) => (
      <HuDialog
        onClose={changeTabModal.closeModal}
        title={`¿Deseas salir de ${steps.find(step => step.id === currentStep)?.title}?`}
        textBody={
          'Tienes cambios sin guardar. Si sales ahora, perderás esos cambios. '
        }
        primaryButtonProps={{
          children: t('general:cancel'),
          onClick: changeTabModal.closeModal,
        }}
        secondaryButtonProps={{
          children: t('general:unsaved_changes.confirm'),
          onClick: () => {
            changeTabModal.closeModal();
            changeStep();
          },
        }}
      />
    ),
  );

  const readyToRender = currentRole || isNew;

  return (
    <Stack sx={{ minHeight: '100%' }}>
      {changeTabModal.modal}
      <Stack
        sx={{
          backgroundColor: theme =>
            theme.palette.hugoBackground?.neutralBgTerciary,
          flexDirection: 'row',
          justifyContent: 'space-between',
          alignItems: 'center',
          position: 'sticky',
          top: 0,
          px: 3,
          py: 2,
          zIndex: 2,
        }}
      >
        <Stack sx={{ gap: 2, flexDirection: 'row', alignItems: 'center' }}>
          {basicInformationLoading && (
            <>
              <HuSkeleton
                variant="rounded"
                width={200}
                height={22}
              />
              <HuSkeleton
                variant="rounded"
                width={100}
                height={22}
              />
            </>
          )}
          {!basicInformationLoading && (
            <>
              <HuTitle
                key={currentRole?.name || defaultTitle}
                sx={{
                  animation: `${animations.fadeIn} 250ms ease-in-out backwards`,
                }}
                title={currentRole?.name || defaultTitle}
                variant="L"
              />
              {currentRole?.state && (
                <HuPills
                  type={roleStatusConfig[currentRole.state].color!}
                  hasIcon={false}
                  label={t(`general:states.${currentRole.state}`)}
                />
              )}
            </>
          )}
        </Stack>
        <IconButton
          to={rolesAndPermissionsRoutes.base()}
          component={Link}
          aria-label={t('GENERAL:CLOSE')}
          title={t('GENERAL:CLOSE')}
        >
          <IconX />
        </IconButton>
      </Stack>

      <Stack
        sx={{
          backgroundColor: theme => theme.palette.hugoBackground?.neutralBg,
          flex: 0,
          pt: 3,
        }}
      >
        {readyToRender && (
          <Container
            maxWidth="md"
            sx={{
              display: 'flex',
              flexDirection: 'column',
            }}
          >
            {isActive && (
              <HuTabs
                tabs={steps.map(step => ({
                  label: step.title,
                  value: step.id,
                }))}
                onTabChange={value => {
                  const changeStep = () =>
                    allowChangeStep &&
                    setCurrentStep(value as RoleStepperSteps);
                  if (warnChangeStep) {
                    changeTabModal.showModal({ changeStep });
                  } else {
                    changeStep();
                  }
                }}
                value={currentStep}
              />
            )}
            {!isActive && (
              <HuStepper
                steps={steps}
                currentStep={steps.findIndex(item => item.id === currentStep)}
              />
            )}
          </Container>
        )}
      </Stack>

      {!readyToRender && (
        <Stack
          sx={{
            flex: 1,
            alignItems: 'center',
            justifyContent: 'center',
            py: 8,
          }}
        >
          <HuSpinner centered />
        </Stack>
      )}
      {readyToRender && (
        <>
          {currentStep === 'basicInformation' && (
            <BasicInformation
              defaultValues={{
                name: currentRole?.name || '',
                description: currentRole?.description || '',
              }}
              setAllowChangeStep={setAllowChangeStep}
              setWarnChangeStep={setWarnChangeStep}
              onSubmitted={
                !isActive ? handleBasicInformationStepSubmit : undefined
              }
              isNew={isNew!}
              isPredefined={isPredefined}
              isActive={isActive}
            />
          )}

          {currentStep === 'assignment' && (
            <AssignmentStep
              onPreviousStep={() => {
                const prev = getAdjacentStepId('assignment', 'prev');
                if (prev) setCurrentStep(prev);
              }}
              onNextStep={() => {
                const next = getAdjacentStepId('assignment', 'next');
                if (next) setCurrentStep(next);
              }}
              roleId={currentRole?.id!}
              isEdit={!isNew}
              isActive={isActive}
              isAllUsersRolePredefined={isAllUsersRolePredefined}
              isAdminRolePredefined={isAdminRolePredefined}
              setWarnChangeStep={setWarnChangeStep}
            />
          )}

          {currentStep === 'permissions' && (
            <PermissionStep
              roleId={currentRole?.id!}
              onPreviousStep={() =>
                setCurrentStep(
                  getAdjacentStepId('permissions', 'prev') ??
                    'basicInformation',
                )
              }
              onNextStep={() => {
                const next = getAdjacentStepId('permissions', 'next');
                if (next) setCurrentStep(next);
              }}
              isEdit={!isNew}
              isActive={isActive}
              isAllUsersRolePredefined={isAllUsersRolePredefined}
              setWarnChangeStep={setWarnChangeStep}
            />
          )}

          {currentStep === 'review' && (
            <ReviewStep
              onPreviousStep={() => setCurrentStep('permissions')}
              isEdit={!isNew}
              isActive={isActive}
              roleId={currentRole?.id!}
              onJumpToStep={setCurrentStep}
            />
          )}
        </>
      )}
    </Stack>
  );
};

export default RoleStepper;
