import type {
    ChartData,
    ChartTitle,
    ChartTooltip,
    ChartYAxis,
} from '@gravity-ui/chartkit/gravity-charts';

import {
    PlaceholderId,
    WizardVisualizationId,
    isDateField,
    isTooltipSumEnabled,
} from '../../../../../../../shared';
import type {
    ServerChartsConfig,
    ServerCommonSharedExtraSettings,
    ServerPlaceholder,
    ServerPlaceholderSettings,
} from '../../../../../../../shared';
import {getAxisTitle, getTickPixelInterval, isGridEnabled} from '../../utils/axis-helpers';

import {getRangeSliderConfig} from './range-slider';

export {getTotalsPrecisionFromSeriesTooltips} from './tooltip';

export function getChartTitle(settings?: ServerCommonSharedExtraSettings): ChartTitle | undefined {
    if (settings?.titleMode !== 'hide' && settings?.title) {
        return {
            text: settings.title,
        };
    }

    return undefined;
}

export function getAxisLabelsRotationAngle(placeholderSettings?: ServerPlaceholderSettings) {
    switch (placeholderSettings?.labelsView) {
        case 'horizontal': {
            return 0;
        }
        case 'vertical': {
            return 90;
        }
        case 'angle': {
            return 45;
        }
    }

    return undefined;
}

function getAxisMinMax(
    placeholderSettings?: ServerPlaceholderSettings,
): [number | undefined, number | undefined] {
    if (placeholderSettings?.scale === 'manual') {
        if (!Array.isArray(placeholderSettings?.scaleValue)) {
            return [undefined, undefined];
        }

        const min = Number(placeholderSettings.scaleValue[0]);
        const max = Number(placeholderSettings.scaleValue[1]);

        return [Number.isNaN(min) ? undefined : min, Number.isNaN(max) ? undefined : max];
    }

    if (placeholderSettings?.scaleValue === '0-max') {
        return [0, undefined];
    }

    return [undefined, undefined];
}

export function getYAxisBaseConfig({
    placeholder,
}: {
    placeholder: ServerPlaceholder | undefined;
}): ChartYAxis {
    const placeholderSettings = placeholder?.settings || {};
    const yItem = placeholder?.items[0];

    const [yMin, yMax] = getAxisMinMax(placeholderSettings);

    return {
        // todo: the axis type should depend on the type of field
        type: isDateField(yItem) ? 'datetime' : 'linear',
        visible: placeholderSettings?.axisVisibility !== 'hide',
        labels: {
            enabled: Boolean(yItem) && placeholder?.settings?.hideLabels !== 'yes',
            rotation: getAxisLabelsRotationAngle(placeholder?.settings),
        },
        title: {
            text: getAxisTitle(placeholderSettings, yItem) || undefined,
            maxRowCount: 3,
            style: {
                fontSize: '13px',
            },
        },
        grid: {
            enabled: Boolean(yItem) && isGridEnabled(placeholderSettings),
        },
        ticks: {
            pixelInterval: getTickPixelInterval(placeholderSettings) || 72,
        },
        lineColor: 'var(--g-color-line-generic)',
        min: yMin,
        max: yMax,
    };
}

export function getBaseChartConfig(args: {
    shared: ServerChartsConfig;
    visualization: {id: string; placeholders: ServerPlaceholder[]};
}) {
    const {shared, visualization} = args;
    const extraSettings = shared.extraSettings;

    const xPlaceholder = visualization.placeholders.find((p) => p.id === PlaceholderId.X);
    const xItem = xPlaceholder?.items[0];
    const xPlaceholderSettings = xPlaceholder?.settings || {};

    const tooltip: ChartTooltip = {
        enabled: extraSettings?.tooltip !== 'hide',
    };

    if (isTooltipSumEnabled({visualizationId: shared.visualization.id})) {
        tooltip.totals = {
            enabled: extraSettings?.tooltipSum !== 'off',
        };
    }

    const legend: ChartData['legend'] = {};
    if (extraSettings?.legendMode === 'hide') {
        legend.enabled = false;
    }

    let chartWidgetData: Partial<ChartData> = {
        title: getChartTitle(extraSettings),
        tooltip,
        legend,
        series: {
            data: [],
            options: {
                'bar-x': {
                    barMaxWidth: 50,
                    barPadding: 0.05,
                    groupPadding: 0.4,
                    dataSorting: {
                        direction: 'desc',
                    },
                },
                line: {
                    lineWidth: 2,
                },
                area: {
                    lineWidth: 2,
                },
            },
        },
        chart: {
            margin: {
                top: 10,
                left: 10,
                right: 10,
                bottom: 15,
            },
            zoom: {
                enabled: true,
                resetButton: {
                    align: 'top-right',
                    offset: {x: 2, y: 30},
                    relativeTo: 'plot-box',
                },
            },
        },
    };

    const visualizationId = visualization.id as WizardVisualizationId;
    const visualizationWithoutAxis = [
        WizardVisualizationId.Pie,
        WizardVisualizationId.Donut,
        WizardVisualizationId.Treemap,
    ];

    const visualizationWithYMainAxis = [WizardVisualizationId.Bar, WizardVisualizationId.Bar100p];

    if (!visualizationWithoutAxis.includes(visualizationId)) {
        const yPlaceholder = visualization.placeholders.find((p) => p.id === PlaceholderId.Y);
        const [xMin, xMax] = getAxisMinMax(xPlaceholderSettings);

        chartWidgetData = {
            ...chartWidgetData,
            xAxis: {
                visible: xPlaceholderSettings?.axisVisibility !== 'hide',
                labels: {
                    enabled: xPlaceholderSettings?.hideLabels !== 'yes',
                    rotation: getAxisLabelsRotationAngle(xPlaceholderSettings),
                    maxWidth: '20%',
                },
                title: {
                    text: getAxisTitle(xPlaceholderSettings, xItem) || undefined,
                    maxRowCount: 3,
                    style: {
                        fontSize: '13px',
                    },
                },
                grid: {
                    enabled: isGridEnabled(xPlaceholderSettings),
                },
                ticks: {
                    pixelInterval: getTickPixelInterval(xPlaceholderSettings),
                },
                lineColor: 'var(--g-color-line-generic)',
                min: xMin,
                max: xMax,
                rangeSlider: getRangeSliderConfig({extraSettings, shared}),
            },
            yAxis: [getYAxisBaseConfig({placeholder: yPlaceholder})],
        };

        if (visualizationWithYMainAxis.includes(visualizationId)) {
            chartWidgetData.xAxis = {...chartWidgetData.xAxis, lineColor: 'transparent'};
        } else {
            chartWidgetData.yAxis = (chartWidgetData.yAxis || []).map((yAxis) => ({
                ...yAxis,
                lineColor: 'transparent',
            }));
        }
    }

    return chartWidgetData;
}
