import React, { useEffect, useState, useRef } from 'react';
import { Button, Form, Label } from '@theorchard/suite-components';
import { AbacusContractType } from 'src/apollo/definitions/globalTypes';
import { ContractTermConditionForm } from 'src/components/contract-terms-refactored/contract-terms-condition-form';
import { CopyTermConditionsFormPopup } from 'src/components/contract-terms-refactored/contract-terms-distro-copy-terms-popup';
import DragAndDrop from 'src/components/shared/drag-and-drop';
import type { AbacusContractTermConditionInput } from 'src/apollo/definitions/globalTypes';
import type { AbacusDistroContractTermCondition } from 'src/types/abacus-contract-term';
import type { AbacusContractTermsInputErrors } from 'src/types/abacus-contract-terms-distro-input-errors';

interface ContractTermsDistroConditionsListProps {
    termId: string | undefined;
    contractTermConditions: AbacusDistroContractTermCondition[];
    onConditionsChange: (
        // eslint-disable-next-line no-unused-vars
        conditions: AbacusContractTermConditionInput[]
    ) => void;
    isLoading: boolean;
    setIsSaveDisabled: React.Dispatch<React.SetStateAction<boolean>>;
    setErrors: React.Dispatch<
        React.SetStateAction<AbacusContractTermsInputErrors>
    >;
}

export const ContractTermsDistroConditionsList: React.FC<
    ContractTermsDistroConditionsListProps
> = ({
    termId,
    contractTermConditions,
    onConditionsChange,
    isLoading,
    setIsSaveDisabled,
    setErrors,
}) => {
    const updateSource = useRef<'external' | 'modal' | 'internal' | null>(null);
    const [isCopyConditionsModalOpen, setIsCopyConditionsModalOpen] =
        useState(false);

    const getEmptyCondition = (
        priority: number
    ): AbacusDistroContractTermCondition => ({
        contractTermId: termId || '',
        contractTermConditionId: '',
        priority,
        termRate: '',
        conditions: {
            countries: [],
            stores: [],
            transactionTypes: [],
        },
        contractTermConditionName: null,
    });

    const [displayConditions, setDisplayConditions] = useState<
        AbacusDistroContractTermCondition[]
    >(() => {
        if (termId && contractTermConditions.length > 0) {
            return contractTermConditions.map((cond, index) => ({
                contractTermId: termId,
                contractTermConditionId: cond.contractTermConditionId || '',
                priority: cond.priority ?? index + 1,
                termRate: cond.termRate ?? '',
                conditions: cond.conditions
                    ? {
                          countries: Array.isArray(cond.conditions)
                              ? []
                              : (cond.conditions?.countries ?? []),
                          stores: Array.isArray(cond.conditions)
                              ? []
                              : (cond.conditions?.stores ?? []),
                          transactionTypes: Array.isArray(cond.conditions)
                              ? []
                              : (cond.conditions?.transactionTypes ?? []),
                      }
                    : { countries: [], stores: [], transactionTypes: [] },
                contractTermConditionName:
                    cond.contractTermConditionName ?? null,
            }));
        }

        return [getEmptyCondition(1)];
    });

    useEffect(() => {
        if (isLoading || !termId) return;

        if (updateSource.current !== 'internal') {
            const normalized = contractTermConditions.map((cond, index) => ({
                contractTermId: termId,
                contractTermConditionId: cond.contractTermConditionId || '',
                priority: cond.priority ?? index + 1,
                termRate: cond.termRate ?? '',
                conditions: cond.conditions
                    ? Array.isArray(cond.conditions)
                        ? {
                              countries: [] as string[],
                              stores: [] as string[],
                              transactionTypes: [] as string[],
                          }
                        : {
                              countries: (cond.conditions.countries ??
                                  []) as string[],
                              stores: (cond.conditions.stores ??
                                  []) as string[],
                              transactionTypes: (cond.conditions
                                  .transactionTypes ?? []) as string[],
                          }
                    : {
                          countries: [] as string[],
                          stores: [] as string[],
                          transactionTypes: [] as string[],
                      },
                contractTermConditionName:
                    cond.contractTermConditionName ?? null,
            }));
            updateSource.current = null;

            setDisplayConditions(
                normalized.length > 0 ? normalized : [getEmptyCondition(1)]
            );
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [contractTermConditions, termId, isLoading]);

    const mapToInputType = (
        conditions: AbacusDistroContractTermCondition[]
    ): AbacusContractTermConditionInput[] => {
        return conditions.map(c => ({
            contractTermConditionId: c.contractTermConditionId,
            contractTermId: c.contractTermId,
            priority: c.priority,
            termRate:
                c.termRate && !isNaN(Number(c.termRate))
                    ? Number(c.termRate)
                    : undefined,
            conditions: {
                countries: Array.isArray(c.conditions)
                    ? []
                    : (c.conditions?.countries ?? []),
                stores: Array.isArray(c.conditions)
                    ? []
                    : (c.conditions?.stores ?? []),
                transactionTypes: Array.isArray(c.conditions)
                    ? []
                    : (c.conditions?.transactionTypes ?? []),
            },
        }));
    };
    const handleAddCondition = () => {
        updateSource.current = 'internal';
        const newPriority = displayConditions.length + 1;
        const updatedConditions = [
            ...displayConditions,
            getEmptyCondition(newPriority),
        ];
        setDisplayConditions(updatedConditions);
        onConditionsChange(mapToInputType(updatedConditions));
    };

    const handleReorderCondition = (dragIndex: number, dropIndex: number) => {
        const reordered = [...displayConditions];
        const [moved] = reordered.splice(dragIndex, 1);
        reordered.splice(dropIndex, 0, moved);
        const reindexed = reordered.map((cond, i) => ({
            ...cond,
            priority: i + 1,
        }));
        setDisplayConditions(reindexed);
        onConditionsChange(mapToInputType(reindexed));
    };

    const handleChangeCondition = (
        index: number,
        name: string,
        value: string | number | string[] | undefined
    ) => {
        setDisplayConditions(prev => {
            if (index < 0 || index >= prev.length) {
                return prev;
            }

            const currentCondition = prev[index];
            const currentConditionsObject = Array.isArray(
                currentCondition.conditions
            )
                ? {
                      countries: [] as string[],
                      stores: [] as string[],
                      transactionTypes: [] as string[],
                  }
                : currentCondition.conditions;

            let updatedCondition: AbacusDistroContractTermCondition;

            if (name === 'termRate') {
                updatedCondition = {
                    ...currentCondition,
                    termRate: typeof value === 'string' ? value : '',
                };
            } else {
                updatedCondition = {
                    ...currentCondition,
                    conditions: {
                        ...currentConditionsObject,
                        [name]: value,
                    },
                };
            }

            const newConditions = [...prev];
            newConditions[index] = updatedCondition;
            onConditionsChange(mapToInputType(newConditions));
            return newConditions;
        });
    };

    const handleDeleteCondition = (
        condition: AbacusDistroContractTermCondition,
        index: number
    ) => {
        const updated = displayConditions.filter((_, i) => i !== index);
        const reindexed = updated.map((cond, i) => ({
            ...cond,
            priority: i + 1,
        }));
        const finalConditions =
            reindexed.length > 0 ? reindexed : [getEmptyCondition(1)];
        setDisplayConditions(finalConditions);
        onConditionsChange(mapToInputType(finalConditions));
    };

    return (
        <Form className="ContractTermsDistroFormFields-ContractTermsConditionsForm">
            <DragAndDrop
                items={displayConditions.map(c => ({ id: c.priority }))}
                onDragEnd={handleReorderCondition}
            >
                <Form.Row className="ContractTermsDistroFormFields-ContractTermsConditionsForm-header">
                    <Label text=" " />
                    <Label text="Transaction type" />
                    <Label text="Service" />
                    <Label text="Country" />
                    <Label text="Label's share" />
                </Form.Row>

                {displayConditions.map((condition, index) => (
                    <Form.Group
                        key={`contract-term-condition-${condition.contractTermConditionId || condition.priority || index}`}
                    >
                        <ContractTermConditionForm
                            condition={condition}
                            index={index}
                            isDraggable={displayConditions.length > 1}
                            dragAndDropCondition={handleReorderCondition}
                            conditions={displayConditions}
                            onChange={handleChangeCondition}
                            onDelete={() =>
                                handleDeleteCondition(condition, index)
                            }
                            setIsSaveDisabled={setIsSaveDisabled}
                            setErrors={setErrors}
                        />
                    </Form.Group>
                ))}

                <Form.Row className="ContractTermsDistroFormFields-ContractTermsConditionsForm-actions">
                    <div className="ContractTermsDistroFormFields-ContractTermsConditionsForm-actionsLeft">
                        <Button onClick={handleAddCondition} variant="link">
                            + New Condition
                        </Button>
                    </div>
                    <div className="ContractTermsDistroFormFields-ContractTermsConditionsForm-actionsRight">
                        <Button
                            onClick={() => setIsCopyConditionsModalOpen(true)}
                            variant="link"
                        >
                            Copy Conditions From...
                        </Button>
                    </div>
                </Form.Row>
            </DragAndDrop>

            <CopyTermConditionsFormPopup
                contractType={AbacusContractType.DISTRIBUTION}
                isCopyConditionsModalOpen={isCopyConditionsModalOpen}
                setIsCopyConditionsModalOpen={setIsCopyConditionsModalOpen}
                conditions={displayConditions}
                setConditions={newConditions => {
                    updateSource.current = 'modal';
                    setDisplayConditions(newConditions);
                    onConditionsChange(mapToInputType(newConditions));
                }}
            />
        </Form>
    );
};
