import React from 'react';
import { Checkbox, Col, Row, Tooltip } from '@theorchard/suite-components';
import dayjs from 'dayjs';
import { isNumber, isString } from 'lodash-es';
import {
    AbacusContractLifecycleSchedulePeriodType,
    AbacusContractLifecycleScheduleRenewalType,
} from 'src/apollo/definitions/globalTypes';
import {
    CONTRACT_RENEWAL_TYPES_SELECT,
    MAX_CONTRACT_LIFECYCLE_DETAIL_INTERVAL,
    TOOLTIP_SAME_RENEWAL_RULES,
} from 'src/apollo/type-constants/contract';
import { CollectionPeriod } from 'src/components/contract-lifecycle-shared/collection-period';
import { CurrentPeriodEndDate } from 'src/components/contract-lifecycle-shared/current-period-end-date';
import { CurrentPeriodStartDate } from 'src/components/contract-lifecycle-shared/current-period-start-date';
import { RenewPeriodically } from 'src/components/contract-lifecycle-shared/renew-periodically';
import { RenewalTypeSelect } from 'src/components/contract-lifecycle-shared/renewal-type-select';
import { TerminationNotice } from 'src/components/contract-lifecycle-shared/termination-notice';
import { CONTRACT_TYPES } from 'src/constants';
import type {
    ContractLifecycle,
    ContractLifecycleSchedule,
} from 'src/types/abacus-contract-lifecycle';

export interface CurrentPeriodFormFieldsPropTypes {
    /* eslint-disable no-unused-vars */
    contractLifecycle: ContractLifecycle;
    contractType?: string;
    currentSchedule?: ContractLifecycleSchedule;
    defaultFormValues: ContractLifecycleSchedule;
    errors: Partial<ContractLifecycle> & Partial<ContractLifecycleSchedule>;
    isCollectionPeriodVisible?: boolean;
    isDisabled?: boolean;
    isEditForm?: boolean;
    isSameRenewalRulesChecked?: boolean;
    setContractLifecycle: (params: ContractLifecycle) => void;
    setContractLifecycleSchedules: (
        params: ContractLifecycleSchedule[]
    ) => void;
    setErrors: React.Dispatch<
        React.SetStateAction<
            Partial<ContractLifecycle> & Partial<ContractLifecycleSchedule>
        >
    >;
    setIsCollectionPeriodVisible?: (params: boolean) => void;
    setIsSameRenewalRulesChecked?: (params: boolean) => void;
    subsequentSchedule?: ContractLifecycleSchedule;
    /* eslint-enable no-unused-vars */
}

export const CurrentPeriodFormFields: React.FC<
    CurrentPeriodFormFieldsPropTypes
> = ({
    contractLifecycle,
    contractType = CONTRACT_TYPES.DISTRIBUTION,
    currentSchedule,
    defaultFormValues,
    errors,
    isCollectionPeriodVisible = false,
    isDisabled = false,
    isEditForm = false,
    isSameRenewalRulesChecked,
    setContractLifecycle,
    setContractLifecycleSchedules,
    setErrors,
    setIsCollectionPeriodVisible,
    setIsSameRenewalRulesChecked,
    subsequentSchedule,
}) => {
    const handleFormChange = (
        formField: string,
        inputValue: number | string | null | undefined
    ) => {
        setErrors({});

        if (
            [
                'collectionPeriodDetailInterval',
                'renewalOffsetDetailInterval',
                'terminationNoticeDetailInterval',
            ].includes(formField)
        ) {
            if (
                isNumber(inputValue) &&
                inputValue > MAX_CONTRACT_LIFECYCLE_DETAIL_INTERVAL
            )
                return;
        }

        if (formField === 'lifecycleTermStart') {
            if (isString(inputValue) && dayjs(inputValue).isValid())
                setContractLifecycle({ [formField]: inputValue });
            else setContractLifecycle({ [formField]: null });

            if (
                currentSchedule &&
                dayjs(inputValue).isValid() &&
                dayjs(currentSchedule.scheduleEnd).isValid() &&
                dayjs(currentSchedule.scheduleEnd).isBefore(
                    dayjs(inputValue),
                    'day'
                )
            )
                updateContractLifecycleSchedules({
                    ...currentSchedule,
                    scheduleEnd: null,
                });

            return null;
        }

        if (
            setIsSameRenewalRulesChecked &&
            formField === 'renewalType' &&
            (!inputValue ||
                inputValue !==
                    AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY)
        )
            setIsSameRenewalRulesChecked(true);

        if (!currentSchedule) return null;

        let updatedSchedule = { ...currentSchedule, [formField]: inputValue };
        if (formField === 'renewalType')
            updatedSchedule = {
                ...currentSchedule,
                ...defaultFormValues,
                terminationNoticeDetailInterval: !inputValue
                    ? null
                    : currentSchedule?.terminationNoticeDetailInterval,
                terminationNoticeDetailType: !inputValue
                    ? AbacusContractLifecycleSchedulePeriodType.DAY
                    : currentSchedule?.terminationNoticeDetailType,
                [formField]: !inputValue ? null : `${inputValue}`,
            };

        updateContractLifecycleSchedules(updatedSchedule, formField);
    };

    const updateContractLifecycleSchedules = (
        updatedSchedule: ContractLifecycleSchedule,
        formField: string | null = null
    ) => {
        if (
            !isEditForm &&
            formField === 'renewalType' &&
            updatedSchedule.renewalType !==
                AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE
        ) {
            setContractLifecycleSchedules([updatedSchedule, defaultFormValues]);
        } else if (
            subsequentSchedule &&
            updatedSchedule.renewalType !==
                AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE
        )
            setContractLifecycleSchedules([
                updatedSchedule,
                subsequentSchedule,
            ]);
        else setContractLifecycleSchedules([updatedSchedule]);
    };

    const renderRenewalTypeFormFields = () => {
        switch (currentSchedule?.renewalType) {
            case AbacusContractLifecycleScheduleRenewalType.CONTINUOUSLY_ACTIVE:
                return (
                    <TerminationNotice
                        contractLifecycleSchedule={currentSchedule}
                        errors={errors}
                        handleFormChange={handleFormChange}
                        isDisabled={isDisabled}
                        isEditForm={isEditForm}
                    />
                );
            case AbacusContractLifecycleScheduleRenewalType.RENEW_AFTER_CERTAIN_DATE:
                return (
                    <>
                        <CurrentPeriodEndDate
                            contractLifecycleSchedule={currentSchedule}
                            errors={errors}
                            handleFormChange={handleFormChange}
                            isDisabled={isDisabled}
                            isEditForm={isEditForm}
                            lifecycleTermStart={
                                contractLifecycle.lifecycleTermStart || null
                            }
                        />
                        <TerminationNotice
                            contractLifecycleSchedule={currentSchedule}
                            errors={errors}
                            handleFormChange={handleFormChange}
                            isDisabled={isDisabled}
                            isEditForm={isEditForm}
                        />
                    </>
                );
            case AbacusContractLifecycleScheduleRenewalType.RENEW_PERIODICALLY:
                return (
                    <>
                        <RenewPeriodically
                            contractLifecycleSchedule={currentSchedule}
                            errors={errors}
                            handleFormChange={handleFormChange}
                            isDisabled={isDisabled}
                            isEditForm={isEditForm}
                        />
                        <TerminationNotice
                            contractLifecycleSchedule={currentSchedule}
                            errors={errors}
                            handleFormChange={handleFormChange}
                            isDisabled={isDisabled}
                            isEditForm={isEditForm}
                        />
                        {!isEditForm && (
                            <Row>
                                <Col>
                                    <Tooltip
                                        id="same-renewal-rules-tooltip"
                                        message={TOOLTIP_SAME_RENEWAL_RULES}
                                        placement="left"
                                        testId="same-renewal-rules-tooltip"
                                    >
                                        <Checkbox
                                            checked={isSameRenewalRulesChecked}
                                            label="Use the same renewal rules for subsequent periods"
                                            onChange={() => {
                                                setIsSameRenewalRulesChecked &&
                                                    setIsSameRenewalRulesChecked(
                                                        !isSameRenewalRulesChecked
                                                    );
                                                setContractLifecycleSchedules([
                                                    currentSchedule,
                                                    defaultFormValues,
                                                ]);
                                            }}
                                            testId="same-renewal-rules-checkbox"
                                        />
                                    </Tooltip>
                                </Col>
                            </Row>
                        )}
                    </>
                );
            default:
                return null;
        }
    };

    if (!currentSchedule) return null;

    return (
        <>
            <CurrentPeriodStartDate
                errors={errors}
                handleFormChange={handleFormChange}
                lifecycleTermStart={
                    contractLifecycle.lifecycleTermStart || null
                }
                isReadOnly={!isEditForm}
                isDisabled={isDisabled}
            />
            {isEditForm &&
                contractType === CONTRACT_TYPES.NEIGHBOURING_RIGHTS && (
                    <CollectionPeriod
                        contractLifecycleSchedule={currentSchedule}
                        errors={errors}
                        handleFormChange={handleFormChange}
                        isCollectionPeriodVisible={isCollectionPeriodVisible}
                        isDisabled={isDisabled}
                        setIsCollectionPeriodVisible={
                            setIsCollectionPeriodVisible!
                        }
                    />
                )}
            <RenewalTypeSelect
                contractLifecycleSchedule={currentSchedule}
                errors={errors}
                handleFormChange={handleFormChange}
                isDisabled={isDisabled}
                isEditForm={isEditForm}
                renewalTypeOptions={CONTRACT_RENEWAL_TYPES_SELECT}
            />
            {renderRenewalTypeFormFields()}
        </>
    );
};
