import {
    Button,
    MarketSelector,
    MultiSelect,
    SegmentedButton,
    Select,
    Tooltip,
} from '@theorchard/suite-components';
import { useToast } from '@theorchard/suite-frontend';
import React, { useEffect, useState } from 'react';
import { useIsYouTubeFingerprintRulesEnabled } from 'shared/features';
import DeliverySummary from 'src/components/fingerprintRulesOAPanel/deliveryRules/deliverySummary';
import UpdatedAddRule from 'src/components/fingerprintRulesOAPanel/updatedAddRule';
import {
    useSetFingerprintRulesForSubaccountMutation,
    useSetFingerprintRulesForVendorMutation,
} from 'src/data/mutations';
import { PolicyType } from 'src/types';
import DeliveryRulesTable from './deliveryRulesTable';
import type { CountryOption } from '@theorchard/suite-components';
import type { FC } from 'react';
import type {
    AccountFingerprintRules,
    FingerprintRule,
    FingerprintRuleInput,
    Profile,
    Territory,
} from 'src/types';
import type {
    PolicyFilter,
    ServiceFilter,
} from '../fingerprint-rules-oa-panel';

const ALL_COUNTRIES_LENGTH = 249;
const GLOBAL_TITLE = 'Global';
const GLOBAL_CODE = 'GLOBAL';

export interface DeliveryRulesProps {
    rules: AccountFingerprintRules;
    territories: Territory[] | undefined;
    territoriesFilter: string[];
    policiesFilter?: PolicyFilter;
    servicesFilter?: ServiceFilter[];
    editable?: boolean;
}

interface DeliveryRule {
    countryName: string | undefined;
    active: boolean;
    policy: string;
    service: string;
    territory: string;
    startDate?: string | undefined;
    endDate?: string | undefined;
    createdDate: string;
    lastModifiedDate: string;
    createdBy: Profile;
    lastModifiedBy: Profile;
    level: string;
}

interface LevelFilter {
    label: string;
    value: string;
}

interface Filter {
    countries: string[];
    service?: ServiceFilter[];
    policy?: PolicyFilter;
    level?: LevelFilter;
    timeRule: TimeRule;
}

interface FormattedRules {
    currentRules: DeliveryRule[];
    scheduledRules: DeliveryRule[];
    expiredRules: DeliveryRule[];
}

export enum TimeRule {
    active,
    scheduled,
    expired,
}

const formatDeliveryRules = (
    vendorRules: FingerprintRule[],
    subaccountRules: FingerprintRule[],
    territories: Territory[] | undefined,
    filter: Filter
): FormattedRules => {
    if (territories) {
        const formattedVendorRules = vendorRules.map(rule => {
            if (rule.territory === '*')
                return {
                    ...rule,
                    service: rule.service === '*' ? GLOBAL_TITLE : rule.service,
                    countryName: GLOBAL_TITLE,
                    territory: GLOBAL_CODE,
                    level: 'Account',
                };

            const foundCountry = territories.find(
                (t: Territory) => t.territoryCodeA2 === rule.territory
            );
            return {
                ...rule,
                service: rule.service === '*' ? GLOBAL_TITLE : rule.service,
                countryName: foundCountry?.territoryName,
                level: 'Account',
            };
        });
        const formattedSubaccountRules = subaccountRules.map(rule => {
            if (rule.territory === '*')
                return {
                    ...rule,
                    service: rule.service === '*' ? GLOBAL_TITLE : rule.service,
                    countryName: GLOBAL_TITLE,
                    territory: GLOBAL_CODE,
                    level: 'Subaccount',
                };

            const foundCountry = territories.find(
                (t: Territory) => t.territoryCodeA2 === rule.territory
            );
            return {
                ...rule,
                service: rule.service === '*' ? GLOBAL_TITLE : rule.service,
                countryName: foundCountry?.territoryName,
                level: 'Subaccount',
            };
        });
        const formattedRules = formattedVendorRules.concat(
            formattedSubaccountRules
        );

        if (formattedRules.length === 0) {
            return {
                currentRules: [],
                scheduledRules: [],
                expiredRules: [],
            };
        }
        let filteredRules = formattedRules;
        const foundGlobalCountry = filter.countries.find(
            country => country === GLOBAL_CODE
        );
        if (
            filter.countries.length > 0 &&
            !foundGlobalCountry &&
            filter.countries.length < ALL_COUNTRIES_LENGTH
        ) {
            filteredRules = filteredRules.filter(rule => {
                const foundCountry = filter.countries.find(
                    country => country === rule.territory
                );
                if (foundCountry) return rule;
            });
        }
        if (filter.service && filter.service.length > 0) {
            filteredRules = filteredRules.filter(rule => {
                const foundService = filter.service?.find(
                    service => service.value === rule.service
                );
                return foundService;
            });
        }
        if (filter.policy)
            filteredRules = filteredRules.filter(
                rule => rule.policy === filter.policy?.value
            );
        if (filter.level)
            filteredRules = filteredRules.filter(
                rule => rule.level === filter.level?.value
            );

        const filteredCurrentRules = filteredRules.filter(rule => {
            if (rule.policy === PolicyType['carveout']) return rule;

            if (rule.startDate && new Date(rule.startDate) <= new Date()) {
                if (
                    rule.endDate &&
                    (rule.endDate === '-' ||
                        new Date(rule.endDate) > new Date())
                ) {
                    return rule;
                }
            }
        });
        return {
            currentRules: filteredCurrentRules,
            scheduledRules: filteredRules.filter(
                rule => rule.startDate && new Date(rule.startDate) > new Date()
            ),
            expiredRules: filteredRules.filter(
                rule => rule.endDate && new Date(rule.endDate) < new Date()
            ),
        };
    }

    return {
        currentRules: [],
        scheduledRules: [],
        expiredRules: [],
    };
};

export const CLASS_NAME = 'DeliveryRules';

export const SERVICE_OPTIONS = [
    {
        value: 'TikTok',
        label: 'TikTok',
    },
    {
        value: 'YouTube',
        label: 'YouTube',
    },
];
export const POLICY_OPTIONS: PolicyFilter[] = [
    {
        value: PolicyType['monetize'],
        label: PolicyType['monetize'],
    },
    {
        value: PolicyType['block_access'],
        label: PolicyType['block_access'],
    },
    {
        value: PolicyType['carveout'],
        label: PolicyType['carveout'],
    },
];
const LEVEL_OPTIONS = [
    {
        value: 'Account',
        label: 'Account',
    },
    {
        value: 'Subaccount',
        label: 'Subaccount',
    },
];

export const DeliveryRules: FC<DeliveryRulesProps> = ({
    rules,
    territories,
    territoriesFilter,
    policiesFilter,
    servicesFilter,
    editable,
}) => {
    const isYouTubeFingerprintRulesEnabled =
        useIsYouTubeFingerprintRulesEnabled();

    const { accountType, accountId, vendorRules, subaccountRules } = rules;
    const dropdownCountries =
        territories?.map(country => ({
            value: country.territoryCodeA2,
            continent: country.continent,
        })) ?? [];

    const [countryFilter, setCountryFilter] = useState(territoriesFilter);
    const [policyFilter, setPolicyFilter] = useState<PolicyFilter | undefined>(
        policiesFilter
    );
    const [serviceFilter, setServiceFilter] = useState<
        ServiceFilter[] | undefined
    >(servicesFilter);
    const [levelFilter, setLevelFilter] = useState<LevelFilter | undefined>();
    const [openSidecar, setOpenSidecar] = useState(false);
    const [timeRuleFilter, setTimeRuleFilter] = useState<TimeRule>(
        TimeRule.active
    );

    const [updateSubaccountRulesMutation] =
        useSetFingerprintRulesForSubaccountMutation();
    const [updateVendorRulesMutation] =
        useSetFingerprintRulesForVendorMutation();

    useEffect(() => {
        setCountryFilter(territoriesFilter);
        setPolicyFilter(policiesFilter);
        setServiceFilter(servicesFilter);
    }, [territoriesFilter, policiesFilter, servicesFilter]);

    const toast = useToast();

    const handleCountryChange = (events: CountryOption[]) => {
        if (events.length === 0) return setCountryFilter([]);

        setCountryFilter(events.map(e => e.value));
    };
    const handlePolicyChange = (
        event: { value: string; label: string } | undefined
    ) => setPolicyFilter(event);

    const handleLevelChange = (
        event: { value: string; label: string } | undefined
    ) => setLevelFilter(event);

    const handleServiceChange = (
        event: { value: string; label: string }[] | undefined
    ) => setServiceFilter(event);

    const handleSaveRule = (
        rules: FingerprintRuleInput[],
        timeFiler: TimeRule | null,
        message?: string
    ) => {
        if (!editable) return;
        if (accountType === 'Vendor') {
            updateVendorRulesMutation({
                variables: {
                    id: String(accountId),
                    rules: JSON.parse(JSON.stringify(rules)),
                },
            });
        } else {
            updateSubaccountRulesMutation({
                variables: {
                    id: String(accountId),
                    rules: JSON.parse(JSON.stringify(rules)),
                },
            });
        }
        const messageToUse = message
            ? message
            : $t('fingerprintRules.deliveryRules.defaultCreateToast');

        setCountryFilter([]);
        setLevelFilter(LEVEL_OPTIONS[0]);

        closeSidecar();
        toast(messageToUse);

        // the comparison with `null` should be explicit,
        // as timeFilter could be `0` — which equals FALSE
        if (timeFiler !== null) setTimeRuleFilter(timeFiler);
    };
    const handleDeleteRule = (
        message: string,
        rules: FingerprintRuleInput[]
    ) => {
        if (accountType === 'Vendor') {
            updateVendorRulesMutation({
                variables: {
                    id: String(accountId),
                    rules: JSON.parse(JSON.stringify(rules)),
                },
            });
        } else {
            updateSubaccountRulesMutation({
                variables: {
                    id: String(accountId),
                    rules: JSON.parse(JSON.stringify(rules)),
                },
            });
        }

        toast(message);
    };

    const closeSidecar = () => {
        setOpenSidecar(false);
    };

    const filter = {
        countries: countryFilter,
        policy: policyFilter,
        service: serviceFilter,
        level: levelFilter,
        timeRule: timeRuleFilter,
    };
    const formattedRules = formatDeliveryRules(
        vendorRules,
        subaccountRules,
        territories,
        filter
    );

    const renderSegmentedFilterBtnText = (
        testId: string,
        id: TimeRule,
        disabled: boolean,
        text: string,
        tooltipMessage: string
    ) => {
        if (disabled)
            return (
                <Tooltip message={tooltipMessage} id={`${id}-tooltip`}>
                    <SegmentedButton.Text
                        testId={testId}
                        id={id}
                        disabled={disabled}
                    >
                        {text}
                    </SegmentedButton.Text>
                </Tooltip>
            );
        return (
            <SegmentedButton.Text testId={testId} id={id} disabled={disabled}>
                {text}
            </SegmentedButton.Text>
        );
    };

    // logic to auto-switch from inactive tab to tab with the rules
    useEffect(() => {
        const shouldBeSwitched =
            (timeRuleFilter === TimeRule.active &&
                formattedRules.currentRules.length === 0) ||
            (timeRuleFilter === TimeRule.scheduled &&
                formattedRules.scheduledRules.length === 0) ||
            (timeRuleFilter === TimeRule.expired &&
                formattedRules.expiredRules.length === 0);

        if (!shouldBeSwitched) return;

        if (
            formattedRules.currentRules.length === 0 &&
            (formattedRules.scheduledRules.length > 0 ||
                formattedRules.expiredRules.length > 0)
        ) {
            return setTimeRuleFilter(
                formattedRules.scheduledRules.length > 0
                    ? TimeRule.scheduled
                    : TimeRule.expired
            );
        }

        if (
            formattedRules.scheduledRules.length === 0 &&
            (formattedRules.currentRules.length > 0 ||
                formattedRules.expiredRules.length > 0)
        ) {
            return setTimeRuleFilter(
                formattedRules.currentRules.length > 0
                    ? TimeRule.active
                    : TimeRule.expired
            );
        }

        if (
            formattedRules.expiredRules.length === 0 &&
            (formattedRules.currentRules.length > 0 ||
                formattedRules.scheduledRules.length > 0)
        ) {
            return setTimeRuleFilter(
                formattedRules.currentRules.length > 0
                    ? TimeRule.active
                    : TimeRule.scheduled
            );
        }
    }, [
        formattedRules.currentRules.length,
        formattedRules.scheduledRules.length,
        formattedRules.expiredRules.length,
    ]);

    let tableRulesToUse;
    if (timeRuleFilter === TimeRule.active)
        tableRulesToUse = formattedRules.currentRules;
    else if (timeRuleFilter === TimeRule.scheduled)
        tableRulesToUse = formattedRules.scheduledRules;
    else if (timeRuleFilter === TimeRule.expired)
        tableRulesToUse = formattedRules.expiredRules;
    else tableRulesToUse = formattedRules.currentRules;

    return (
        <div className={`${CLASS_NAME}-rules-body`}>
            <div className={`${CLASS_NAME}-rules-section-title`}>
                <div className={`${CLASS_NAME}-rules-section-title-left`}>
                    <h2 className={`${CLASS_NAME}-rules-title`}>
                        {$t(
                            'fingerprintRules.deliveryRules.deliveryRulesTitle'
                        )}
                    </h2>
                    <p className={`${CLASS_NAME}-rules-subtitle`}>
                        {$t(
                            'fingerprintRules.deliveryRules.deliveryRulesSubTitle'
                        )}
                    </p>
                </div>

                <div className={`${CLASS_NAME}-rules-section-title-right`}>
                    <Button
                        onClick={() => setOpenSidecar(true)}
                        data-testid="btn-add-rule"
                        variant="primary"
                        disabled={!editable}
                    >
                        {$t('fingerprintRules.deliveryRules.buttons.addRule')}
                    </Button>
                </div>
            </div>
            <div className={`${CLASS_NAME}-data`}>
                <div className={`${CLASS_NAME}-filters`}>
                    <div className={`${CLASS_NAME}-first-filters`}>
                        <SegmentedButton
                            variant="primary"
                            onChange={setTimeRuleFilter}
                            defaultValue={timeRuleFilter}
                            value={timeRuleFilter}
                        >
                            {renderSegmentedFilterBtnText(
                                'btn-active',
                                TimeRule.active,
                                formattedRules.currentRules.length === 0,
                                $t(
                                    'fingerprintRules.deliveryRules.filters.active'
                                ),
                                $t(
                                    'fingerprintRules.deliveryRules.filters.emptyActive'
                                )
                            )}
                            {renderSegmentedFilterBtnText(
                                'btn-scheduled',
                                TimeRule.scheduled,
                                formattedRules.scheduledRules.length === 0,
                                $t(
                                    'fingerprintRules.deliveryRules.filters.scheduled'
                                ),
                                $t(
                                    'fingerprintRules.deliveryRules.filters.emptyScheduled'
                                )
                            )}
                            {renderSegmentedFilterBtnText(
                                'btn-expired',
                                TimeRule.expired,
                                formattedRules.expiredRules.length === 0,
                                $t(
                                    'fingerprintRules.deliveryRules.filters.expired'
                                ),
                                $t(
                                    'fingerprintRules.deliveryRules.filters.emptyExpired'
                                )
                            )}
                        </SegmentedButton>
                    </div>
                    <div className={`${CLASS_NAME}-secondary-filters`}>
                        <div
                            className={`${CLASS_NAME}-secondary-filters-dropdown`}
                        >
                            {accountType === 'Subaccount' && (
                                <Select
                                    className={`${CLASS_NAME}-secondary-filters-dropdown-level`}
                                    selectedValue={levelFilter}
                                    options={LEVEL_OPTIONS}
                                    onChange={handleLevelChange}
                                    testId="dpd-level"
                                    placeholder="Rule Level"
                                    compact
                                    hideFilter
                                />
                            )}

                            <Select
                                className={`${CLASS_NAME}-secondary-filters-dropdown-policy`}
                                selectedValue={policyFilter}
                                options={POLICY_OPTIONS}
                                onChange={handlePolicyChange}
                                testId="dpd-policy"
                                placeholder="Rule"
                                compact
                                hideFilter
                            />

                            <MarketSelector
                                className={`${CLASS_NAME}-secondary-filters-dropdown-country`}
                                selectedValue={countryFilter}
                                onChange={handleCountryChange}
                                countries={dropdownCountries}
                                testId="dpd-country"
                                variant="compact"
                                placeholder="Country"
                                sectionGroupSelect
                            />

                            {isYouTubeFingerprintRulesEnabled && (
                                <MultiSelect
                                    className={`${CLASS_NAME}-secondary-filters-dropdown-service`}
                                    options={SERVICE_OPTIONS}
                                    onChange={handleServiceChange}
                                    testId="dpd-service"
                                    placeholder="Service"
                                    variant="compact"
                                    hideFilter
                                />
                            )}
                        </div>
                    </div>
                </div>
                <DeliverySummary
                    vendorRules={vendorRules}
                    subaccountRules={subaccountRules}
                    timeRuleFilter={timeRuleFilter}
                    isSubaccount={accountType.toLowerCase() === 'subaccount'}
                />
                <DeliveryRulesTable
                    accountType={
                        accountType === 'Vendor' ? 'Account' : 'Subaccount'
                    }
                    tableRules={tableRulesToUse}
                    higherLevelRules={
                        accountType === 'Vendor' ? [] : vendorRules
                    }
                    currentRules={
                        accountType === 'Vendor' ? vendorRules : subaccountRules
                    }
                    current
                    scheduled={false}
                    expired={false}
                    onDeleteRow={handleDeleteRule}
                    editable={editable}
                    onEditRow={handleSaveRule}
                    territories={territories}
                />
            </div>
            {editable && (
                <UpdatedAddRule
                    title={$t('fingerprintRules.deliveryRules.sidecar.title')}
                    isOpen={openSidecar}
                    onClose={closeSidecar}
                    onConfirm={handleSaveRule}
                    higherLevelRules={
                        accountType === 'Vendor' ? [] : vendorRules
                    }
                    currentRules={
                        accountType === 'Vendor' ? vendorRules : subaccountRules
                    }
                    editRowData={undefined}
                    territories={territories}
                />
            )}
        </div>
    );
};

export default DeliveryRules;
