import { EditableApprovalWorkflow, EditableWorkflowStep } from "@/interfaces/approval.workflow";
import Option from "@/interfaces/option";
import { CorporateUser, DeveloperUser, MasterCorporateUser, TeacherUser } from "@/interfaces/user";
import { AnimatePresence, Reorder, motion } from "framer-motion";
import { FaRegCheckCircle, FaSpinner } from "react-icons/fa";
import { IoIosAddCircleOutline } from "react-icons/io";
import Button from "../Low/Button";
import Tip from "./Tip";
import WorkflowEditableStepComponent from "./WorkflowEditableStepComponent";

interface Props {
    workflow: EditableApprovalWorkflow;
    onWorkflowChange: (workflow: EditableApprovalWorkflow) => void;
    entityApprovers: (TeacherUser | CorporateUser | MasterCorporateUser | DeveloperUser)[];
    entityAvailableFormIntakers?: (TeacherUser | CorporateUser | MasterCorporateUser | DeveloperUser)[];
    isLoading: boolean;
    isRedirecting?: boolean;
}

export default function WorkflowForm({ workflow, onWorkflowChange, entityApprovers, entityAvailableFormIntakers, isLoading, isRedirecting }: Props) {
    const lastStep = workflow.steps[workflow.steps.length - 1];

    const renumberSteps = (steps: EditableWorkflowStep[]): EditableWorkflowStep[] => {
        return steps.map((step, index) => ({
            ...step,
            stepNumber: index + 1,
        }));
    };

    const addStep = () => {
        const newStep: EditableWorkflowStep = {
            key: Date.now(),
            stepType: "approval-by",
            stepNumber: workflow.steps.length,
            completed: false,
            assignees: [null],
            firstStep: false,
            finalStep: false,
        };

        const updatedSteps = [
            ...workflow.steps.slice(0, -1),
            newStep,
            lastStep
        ];
        onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) });
    };

    const handleDelete = (key: number | undefined) => {
        if (!key) return;

        const updatedSteps = workflow.steps.filter((step) => step.key !== key);
        onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) });
    };

    const handleSelectChange = (key: number | undefined, numberOfSelects: number, index: number, selectedOption: Option | null) => {
        if (!key) return;

        const updatedSteps = workflow.steps.map((step) => {
            if (step.key !== key) return step;

            const assignees = step.assignees ?? [];
            let newAssignees = [...assignees];

            if (numberOfSelects === assignees.length) { // means no new select was added and instead one was changed
                newAssignees[index] = selectedOption?.value;
            } else if (numberOfSelects === assignees.length + 1) { // means a new select was added
                newAssignees.push(selectedOption?.value || null);
            }

            return { ...step, assignees: newAssignees };
        });
        onWorkflowChange({ ...workflow, steps: updatedSteps });
    };

    const handleReorder = (newOrder: EditableWorkflowStep[]) => {
        let draggableIndex = 0;
        const updatedSteps = workflow.steps.map((step) => {
            if (!step.firstStep && !step.finalStep && !step.completed) {
                return newOrder[draggableIndex++];
            }
            // Keep static steps as-is
            return step;
        });
        onWorkflowChange({ ...workflow, steps: renumberSteps(updatedSteps) });
    };


    return (
        <>
            {workflow.entityId && workflow.name &&
                <div>
                    <div
                        className="flex flex-col gap-6"
                    >
                        <Tip text="Introduce here all the steps associated with this instance." />
                        <Button
                            color="purple"
                            variant="solid"
                            onClick={addStep}
                            type="button"
                            className="max-w-fit text-lg font-medium flex items-center gap-2 text-left mb-7"
                        >
                            <IoIosAddCircleOutline className="size-6" />
                            Add Step
                        </Button>
                    </div>

                    <Reorder.Group
                        axis="y"
                        values={workflow.steps}
                        onReorder={handleReorder}
                        className="flex flex-col gap-0"
                    >
                        <AnimatePresence>
                            {workflow.steps.map((step, index) =>
                                step.completed || step.firstStep || step.finalStep ? (
                                    <motion.div
                                        key={step.key}
                                        layout
                                        initial={{ opacity: 0, y: -30 }}
                                        animate={{ opacity: 1, y: 0 }}
                                        exit={{ opacity: 0, x: 30 }}
                                        transition={{ duration: 0.20 }}
                                    >
                                        <WorkflowEditableStepComponent
                                            stepNumber={index + 1}
                                            assignees={step.assignees}
                                            finalStep={step.finalStep}
                                            onDelete={() => handleDelete(step.key)}
                                            onSelectChange={(numberOfSelects, idx, option) =>
                                                handleSelectChange(step.key, numberOfSelects, idx, option)
                                            }
                                            entityApprovers={
                                                step.stepNumber === 1 && entityAvailableFormIntakers
                                                    ? entityAvailableFormIntakers
                                                    : entityApprovers
                                            }
                                            isCompleted={step.completed}
                                        />
                                    </motion.div>
                                ) : (
                                    // Render non-completed steps as draggable items
                                    <Reorder.Item
                                        key={step.key}
                                        value={step}
                                        initial={{ opacity: 0, y: -30 }}
                                        animate={{ opacity: 1, y: 0 }}
                                        exit={{ opacity: 0, x: 30 }}
                                        transition={{ duration: 0.20 }}
                                        layout
                                        drag={!step.firstStep && !step.finalStep}
                                        dragListener={!step.firstStep && !step.finalStep}
                                    >
                                        <WorkflowEditableStepComponent
                                            stepNumber={index + 1}
                                            assignees={step.assignees}
                                            finalStep={step.finalStep}
                                            onDelete={() => handleDelete(step.key)}
                                            onSelectChange={(numberOfSelects, idx, option) =>
                                                handleSelectChange(step.key, numberOfSelects, idx, option)
                                            }
                                            entityApprovers={
                                                step.stepNumber === 1 && entityAvailableFormIntakers
                                                    ? entityAvailableFormIntakers
                                                    : entityApprovers
                                            }
                                            isCompleted={step.completed}
                                        />
                                    </Reorder.Item>
                                )
                            )}
                            <Button
                                type="submit"
                                color="purple"
                                variant="solid"
                                disabled={isLoading}
                                className="max-w-fit text-lg font-medium flex items-center gap-2 text-left -mt-4"
                            >
                                {isRedirecting ? (
                                    <>
                                        <FaSpinner className="animate-spin size-5" />
                                        Redirecting...
                                    </>
                                ) : isLoading ? (
                                    <>
                                        <FaSpinner className="animate-spin size-5" />
                                        Loading...
                                    </>
                                ) : (
                                    <>
                                        <FaRegCheckCircle className="size-5" />
                                        Confirm Exam Workflow Pipeline
                                    </>
                                )}
                            </Button>
                        </AnimatePresence>
                    </Reorder.Group>
                </div>
            }
        </>
    );
};