import type {ItemDropProps} from '@gravity-ui/dashkit';
import type {ThemeType} from '@gravity-ui/uikit';

import type {ConnectionQueryTypeValues} from '../constants/connections';
import type {Operations} from '../modules';

export type ImpactType = 'allTabs' | 'currentTab' | 'selectedTabs' | 'asGroup';
export type ImpactTabsIds = string[] | null | undefined;

import type {
    ClientChartsConfig,
    ConnectionQueryContent,
    DatasetFieldType,
    Dictionary,
    Entry,
    EntryScope,
    HintSettings,
    StringParams,
    ValueOf,
} from './index';

export enum ControlType {
    Dash = 'control_dash',
}

export type DashChartRequestContext = Record<string, string>;

export enum DashTabItemType {
    Title = 'title',
    Text = 'text',
    Widget = 'widget',
    Control = 'control',
    GroupControl = 'group_control',
    Image = 'image',
}

export const DashTabItemTitleSizes = {
    XL: 'xl',
    L: 'l',
    M: 'm',
    S: 's',
    XS: 'xs',
} as const;

export type DashTabItemTitleSize = ValueOf<typeof DashTabItemTitleSizes>;

export enum DashTabItemControlSourceType {
    Dataset = 'dataset',
    Connection = 'connection',
    Manual = 'manual',
    External = 'external',
}

export enum DashTabItemControlElementType {
    Select = 'select',
    Date = 'date',
    Input = 'input',
    Checkbox = 'checkbox',
}

export enum DashTabConnectionKind {
    Ignore = 'ignore',
}

export enum DashLoadPriority {
    Charts = 'charts',
    Selectors = 'selectors',
}

export interface DashEntryCreateParams extends DashEntry, DashData {}

export interface DashEntry extends Entry {
    scope: EntryScope.Dash;
    type: '';
    data: DashData;
    savedId: string;
    revId: string;
    updatedAt: string;
    publishedId: string;
    asNew?: boolean;
    fake?: boolean;
}

export type DashWidgetsSettings = {
    backgroundSettings?: BackgroundSettings;
    borderRadius?: number;
    internalMarginsEnabled?: boolean;
};

export type DashSettings = {
    autoupdateInterval: null | number;
    maxConcurrentRequests: null | number;
    silentLoading: boolean;
    dependentSelectors: boolean;
    hideTabs: boolean;
    hideDashTitle?: boolean;
    expandTOC: boolean;
    globalParams?: DashSettingsGlobalParams;
    // used only for secure cases
    signedGlobalParams?: DashSettingsGlobalParams;
    loadPriority?: DashLoadPriority;
    loadOnlyVisibleCharts?: boolean;
    margins?: [number, number];
    enableAssistant?: boolean;
    widgetsSettings?: DashWidgetsSettings;
    backgroundSettings?: BackgroundSettings;
};

export interface DashData {
    counter: number;
    tabs: DashTab[];
    salt: string;
    schemeVersion: number;
    settings: DashSettings;
    // only in old dashbords (now migrating to annotation)
    description?: string;
    accessDescription?: string;
    supportDescription?: string;
}

export type DashDragOptions = ItemDropProps;

type OptionalDashDataSettings = Pick<
    DashSettings,
    'margins' | 'enableAssistant' | 'widgetsSettings' | 'backgroundSettings'
>;

// config with strict requirements of settings for new dash
// schemeVersion comes from server
export type FakeDashData = Omit<DashData, 'schemeVersion'> & {
    settings: Required<Omit<DashSettings, 'signedGlobalParams' | keyof OptionalDashDataSettings>> &
        OptionalDashDataSettings;
};

export interface DashTabSettings {
    fixedHeaderCollapsedDefault: boolean;
}
export interface DashTab {
    id: string;
    title: string;
    items: DashTabItem[];
    layout: DashTabLayout[];
    aliases: DashTabAliases;
    connections: DashTabConnection[];
    settings?: DashTabSettings;
    globalItems?: DashGlobalItem[];
}

export type DashSettingsGlobalParams = Record<string, string | string[]>;
export type DashWidgetsConfigsMapper = Record<string, ClientChartsConfig>;

export type DashGlobalItem = DashTabItemControl | DashTabItemGroupControl;

export type DashTabItem =
    | DashTabItemText
    | DashTabItemTitle
    | DashTabItemWidget
    | DashTabItemControl
    | DashTabItemGroupControl
    | DashTabItemImage;

export type ColorByTheme = Partial<Record<ThemeType, string | undefined>>;

export type OldBackgroundSettings = {
    enabled?: boolean;
    color: string;
};

export type ColorSettings = ColorByTheme | string;
export type BackgroundSettings = {color?: ColorSettings};

export type TitleTextSettings = {color?: ColorSettings};

export interface DashTabItemBase {
    id: string;
    namespace: string;
    type: DashTabItemType;
    orderId?: number;
    defaultOrderId?: number;
    title?: string;
}

export type DashTabItemBaseData = {
    background?: OldBackgroundSettings;
    backgroundSettings?: BackgroundSettings;
    borderRadius?: number;
    internalMarginsEnabled?: boolean;
};

export interface DashTabItemText extends DashTabItemBase {
    type: DashTabItemType.Text;
    data: DashTabItemBaseData & {
        text: string;
        autoHeight?: boolean;
    };
}

export type DashTitleSize =
    | DashTabItemTitleSize
    | {
          fontSize: number;
          lineHeight?: number;
      };

export interface DashTabItemTitle extends DashTabItemBase {
    type: DashTabItemType.Title;
    data: DashTabItemBaseData & {
        text: string;
        size: DashTitleSize;
        showInTOC: boolean;
        autoHeight?: boolean;
        textColor?: string;
        textSettings?: TitleTextSettings;
        hint?: HintSettings;
    };
}

export interface DashTabItemWidget extends DashTabItemBase {
    type: DashTabItemType.Widget;
    data: Omit<DashTabItemBaseData, 'background'> & {
        hideTitle: boolean;
        tabs: DashTabItemWidgetTab[];
    };
}

export interface DashTabItemWidgetTab {
    id: string;
    title: string;
    description: string;
    hint?: string;
    enableHint?: boolean;
    enableDescription?: boolean;
    chartId: string;
    isDefault: boolean;
    params: StringParams;
    autoHeight?: boolean;
    enableActionParams?: boolean;
    background?: OldBackgroundSettings;
}

export interface DashTabItemControl extends DashTabItemBase {
    type: DashTabItemType.Control;
    data: Omit<DashTabItemControlData, 'id' | 'namespace'>;
    defaults: StringParams;
}

export interface DashTabItemControlBaseData {
    id?: string;
    title: string;
    placementMode?: 'auto' | '%' | 'px';
    autoHeight?: boolean;
    width?: string;
    defaults?: StringParams;
    namespace?: string;
    impactType?: ImpactType;
    impactTabsIds?: ImpactTabsIds;
}

export interface DashTabItemControlData extends DashTabItemControlBaseData {
    sourceType: DashTabItemControlSourceType;
    source:
        | DashTabItemControlDataset['source']
        | DashTabItemControlManual['source']
        | DashTabItemControlExternal['source'];
}

export type DashTabItemControlSingle = (DashTabItemControlDataset | DashTabItemControlManual) & {
    id: string;
    namespace: string;
};

export type DashItemControlConnectionBaseSource = {
    connectionId?: string;
    connectionQueryType?: ConnectionQueryTypeValues;
    connectionQueryContent?: ConnectionQueryContent;
};

export type DashTabItemControlConnection = DashTabItemControlBaseData & {
    sourceType: DashTabItemControlSourceType.Connection;
    source: DashItemControlConnectionBaseSource & DashTabItemControlElement;
};

export type DashItemControlDatasetBaseSource = {
    datasetId: string;
    datasetFieldId: string;
    datasetFieldType?: DatasetFieldType;
};

export interface DashTabItemControlDataset extends DashTabItemControlData {
    sourceType: DashTabItemControlSourceType.Dataset;
    source: DashItemControlDatasetBaseSource & DashTabItemControlElement;
}

export type DashItemControlManualBaseSource = {
    fieldName: string;
    acceptableValues?:
        | {
              // elementType: select
              value: string;
              title: string;
          }[]
        | {
              // elementType: date
              from: string;
              to: string;
          };
};

export interface DashTabItemControlManual extends DashTabItemControlData {
    sourceType: DashTabItemControlSourceType.Manual;
    source: DashItemControlManualBaseSource & DashTabItemControlElement;
}

export type DashTabItemControlElement =
    | DashTabItemControlElementSelect
    | DashTabItemControlElementInput
    | DashTabItemControlElementDate
    | DashTabItemControlElementCheckbox;

export enum TitlePlacementOption {
    Left = 'left',
    Top = 'top',
}

export const TitlePlacements = {
    Hide: 'hide' as const,
    Left: TitlePlacementOption.Left,
    Top: TitlePlacementOption.Top,
};

export type TitlePlacement = ValueOf<typeof TitlePlacements>;

export type AccentTypeValue = 'info' | null;

export interface DashTabItemControlElementBase {
    showTitle: boolean;
    titlePlacement?: TitlePlacementOption;
    elementType: DashTabItemControlElementType;
    operation?: Operations;
    showInnerTitle?: boolean;
    innerTitle?: string;
    fieldType?: string;
    required?: boolean;
    showHint?: boolean;
    hint?: string;
    accentType?: AccentTypeValue;
}

export type UniversalDefaultValue = StringDefaultValue | string[];
export type StringDefaultValue = string;

export interface DashTabItemControlElementSelectBase {
    multiselectable: boolean;
}

export interface DashTabItemControlElementSelect
    extends DashTabItemControlElementBase,
        DashTabItemControlElementSelectBase {
    elementType: DashTabItemControlElementType.Select;
    defaultValue?: UniversalDefaultValue;
}

export interface DashTabItemControlElementInput extends DashTabItemControlElementBase {
    elementType: DashTabItemControlElementType.Input;
    defaultValue?: StringDefaultValue;
}

export interface DashTabItemControlElementDateBase {
    isRange: boolean;
}

export interface DashTabItemControlElementDate
    extends DashTabItemControlElementBase,
        DashTabItemControlElementDateBase {
    elementType: DashTabItemControlElementType.Date;
    defaultValue?: StringDefaultValue;
}

export interface DashTabItemControlElementCheckbox extends DashTabItemControlElementBase {
    elementType: DashTabItemControlElementType.Checkbox;
    defaultValue: StringDefaultValue;
}

export type DashItemControlExternalBaseSource = {
    chartId: string;
};

export interface DashTabItemControlExternal extends DashTabItemControlData {
    sourceType: DashTabItemControlSourceType.External;
    source: DashItemControlExternalBaseSource;
}

export interface DashTabItemGroupControl extends DashTabItemBase {
    type: DashTabItemType.GroupControl;
    data: DashTabItemGroupControlData;
}

export interface DashTabItemGroupControlBaseData {
    showGroupName: boolean;
    groupName?: string;
    autoHeight: boolean;
    buttonApply: boolean;
    buttonReset: boolean;
    impactType?: ImpactType;
    impactTabsIds?: ImpactTabsIds;

    updateControlsOnChange?: boolean;
}

export interface DashTabItemGroupControlData extends DashTabItemGroupControlBaseData {
    group: DashTabItemControlSingle[];
}

export interface DashTabLayout {
    h: number;
    i: string;
    w: number;
    x: number;
    y: number;
    parent?: string;
}

export interface DashTabAliases extends Dictionary<Array<string[]>> {}

export interface DashTabConnection {
    from: string;
    to: string;
    kind: DashTabConnectionKind;
}

export interface DashStateData
    extends Dictionary<{
        params: StringParams;
        state: {
            // for chart state
            tabId: string;
        };
    }> {}

export interface DashStats {
    dashId: string;
    dashTabId: string;
    dashStateHash: string | null;
    login?: string;
    userId: string;
    tenantId: string;
    traceId?: string;
}

export interface DashTabItemImage extends DashTabItemBase {
    type: DashTabItemType.Image;
    data: DashTabItemBaseData & {
        src: string;
        alt?: string;
        preserveAspectRatio?: boolean;
    };
}
