import { FormProvider, useForm, useFormContext } from 'react-hook-form';

import { yupResolver } from '@hookform/resolvers/yup';
import { useDrawer } from '@material-hu/hooks/useDrawer';
import { Stack } from '@material-hu/mui';

import HuTitle from '@material-hu/components/design-system/Title';

import { type FlowNode, NodeType } from 'src/types/workflows';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { validateBranches } from 'src/components/Condition/components/validations';

import {
  type ApprovalRole,
  addApprovalNode,
  addConditionalNode,
  addTaskNode,
  type InvalidNodeInfo,
  newNodeToEnd,
} from '../utils';

import Branches from './Add/Branches';
import ChangeField from './Add/ChangeField';
import RequestApproval from './Add/RequestApproval';
import Task from './Add/Task';
import NodeCard from './NodeCard';

type SidesheetContentProps = {
  resetNodes: () => void;
  onClose: () => void;
  node: FlowNode;
  onInvalidNode?: (invalidNode: InvalidNodeInfo) => void;
  onValidNode?: (nodeId: string) => void;
};

const SidesheetContent = ({
  resetNodes,
  onClose: closeSidesheet,
  node,
  onInvalidNode,
  onValidNode,
}: SidesheetContentProps) => {
  const { t } = useLokaliseTranslation(['workflows', 'general']);

  const {
    showDrawer: showChangeFieldDrawer,
    drawer: changeFieldDrawer,
    closeDrawer: closeChangeFieldDrawer,
  } = useDrawer(
    ChangeField,
    {
      title: t('change_field'),
      onClose: () => {
        closeChangeFieldDrawer();
      },
      slotProps: {
        layout: {
          sx: { pb: 1 },
        },
      },
    },
    {
      resetNodes: resetNodes,
      onClose: () => {
        closeChangeFieldDrawer();
        closeSidesheet();
      },
      node: node,
      ...(onInvalidNode && { onInvalidNode }),
      ...(onValidNode && { onValidNode }),
    },
  );

  const workflowForm = useFormContext();

  const connectsToEnd = newNodeToEnd(workflowForm.getValues('body'));

  const branchesForm = useForm({
    mode: 'onChange',
    resolver: yupResolver(validateBranches()),
  });

  const { node: branchesNode } = branchesForm.watch();

  const {
    showDrawer: showBranchesDrawer,
    drawer: branchesDrawer,
    closeDrawer: closeBranchesDrawer,
  } = useDrawer(Branches, {
    title: t('branches_title'),
    primaryButtonProps: {
      children: t('general:add'),
      onClick: () => {
        addConditionalNode(
          workflowForm,
          branchesNode?.branches,
          branchesNode?.defaultBranch,
          t,
          resetNodes,
          onInvalidNode,
          onValidNode,
        );
        closeBranchesDrawer();
        closeSidesheet();
      },
      fullWidth: true,
    },
    secondaryButtonProps: {
      children: t('general:cancel'),
      onClick: () => {
        closeBranchesDrawer();
      },
      fullWidth: true,
    },
    onClose: () => {
      closeBranchesDrawer();
    },
    slotProps: {
      layout: {
        sx: { pb: 1 },
      },
    },
  });

  const requestApprovalForm = useForm({
    mode: 'onChange',
  });

  const {
    showDrawer: showRequestApprovalDrawer,
    drawer: requestApprovalDrawer,
    closeDrawer: closeRequestApprovalDrawer,
  } = useDrawer(
    RequestApproval,
    {
      title: t('request_approval'),
      primaryButtonProps: {
        children: t('general:add'),
        onClick: () => {
          const formData = requestApprovalForm.getValues();

          const approverIds = formData.node.approverIds?.map(
            (user: { id: number }) => user.id,
          );
          const approverRoles = formData.node.approverRoles?.map(
            (role: { value: ApprovalRole }) => role.value,
          );
          const approvalPolicy = formData.node.approvalPolicyOption?.value;

          addApprovalNode(
            workflowForm,
            formData.node.name,
            t,
            approverIds,
            approverRoles,
            approvalPolicy,
            resetNodes,
            onInvalidNode,
            onValidNode,
          );
          closeRequestApprovalDrawer();
          closeSidesheet();
        },
        fullWidth: true,
      },
      secondaryButtonProps: {
        children: t('general:cancel'),
        onClick: () => {
          closeRequestApprovalDrawer();
        },
        fullWidth: true,
      },
      onClose: () => {
        closeRequestApprovalDrawer();
      },
      slotProps: {
        layout: {
          sx: { pb: 1 },
        },
      },
    },
    {
      isNewNode: true,
    },
  );

  const taskForm = useForm({
    mode: 'onChange',
  });

  const {
    showDrawer: showTaskDrawer,
    drawer: taskDrawer,
    closeDrawer: closeTaskDrawer,
  } = useDrawer(
    Task,
    {
      title: t('task'),
      primaryButtonProps: {
        children: t('general:add'),
        onClick: () => {
          const formData = taskForm.getValues();

          const agentGroupId = formData.node.agentGroupId?.id;
          const assignedAgentId = formData.node.assigneeId?.id;

          addTaskNode(
            workflowForm,
            formData.node.name,
            formData.node.description,
            agentGroupId,
            assignedAgentId,
            formData.node.blockingTask,
            t,
            resetNodes,
            onInvalidNode,
            onValidNode,
          );
          taskForm.reset();
          closeTaskDrawer();
          closeSidesheet();
        },
        fullWidth: true,
      },
      secondaryButtonProps: {
        children: t('general:cancel'),
        onClick: () => {
          closeTaskDrawer();
        },
        fullWidth: true,
      },
      onClose: () => {
        closeTaskDrawer();
        taskForm.reset();
      },
      slotProps: {
        layout: {
          sx: { pb: 1 },
        },
      },
    },
    {
      isNewNode: true,
    },
  );

  return (
    <Stack
      sx={{
        gap: 2,
        pb: 10,
      }}
    >
      {changeFieldDrawer}
      <FormProvider {...requestApprovalForm}>
        {requestApprovalDrawer}
      </FormProvider>
      <FormProvider {...taskForm}>{taskDrawer}</FormProvider>
      <FormProvider {...branchesForm}>{branchesDrawer}</FormProvider>
      <Stack sx={{ gap: 2 }}>
        <HuTitle
          variant="S"
          title={t('logic')}
        />
        <NodeCard
          type={NodeType.CONDITIONAL}
          title={t('branches')}
          description={t('branches_sub')}
          onClick={showBranchesDrawer}
          disabled={!connectsToEnd}
        />
      </Stack>
      <Stack sx={{ gap: 2 }}>
        <HuTitle
          variant="S"
          title={t('actions')}
        />
        <NodeCard
          type={NodeType.TASK}
          title={t('new_task')}
          description={t('new_task_sub')}
          onClick={showTaskDrawer}
        />
        <NodeCard
          type={NodeType.APPROVAL}
          title={t('request_approval')}
          description={t('request_sub')}
          onClick={showRequestApprovalDrawer}
          disabled={!connectsToEnd}
        />
        <NodeCard
          type={NodeType.CHANGE_ASSIGNEE}
          title={t('change_field')}
          description={t('change_field_sub')}
          onClick={showChangeFieldDrawer}
        />
      </Stack>
    </Stack>
  );
};

export default SidesheetContent;
