import type {Link, Meta} from '@gravity-ui/app-layout';
import type {Request, Response} from '@gravity-ui/expresskit';

import type {CtxUser} from '../server/components/auth/types/user';
import type {ChartTemplates} from '../server/components/charts-engine/components/chart-generator';
import type {SourceConfig} from '../server/components/charts-engine/types';
import type {RedisConfig} from '../server/utils/redis';
import type {AppEnvironment, LandingPageSettings} from '../shared';
import type {UserRole} from '../shared/components/auth/constants/role';
import type {FeatureConfig} from '../shared/types';

export interface SharedAppConfig {
    endpoints: Endpoints;
    features: FeatureConfig;
    metrika: MetrikaCounter;

    usMasterToken?: string;
    usDynamicMasterTokenPrivateKey?: string;

    regionalEnvConfig?: {allowLanguages?: string[]; defaultLang?: string; langRegion?: string};

    faviconUrl: string;

    links?: Link[];
    meta?: Meta[];

    chartkitSettings?: ChartkitGlobalSettings;
    defaultColorPaletteId?: string;
    serviceName: string;
    // CHARTS ENGINE -- START
    usEndpoint: string;
    getSourcesByEnv: (appEnv: AppEnvironment) => Record<string, SourceConfig>;
    sources: Record<string, SourceConfig>;
    appMode?: string;

    enablePreloading?: boolean;
    fetchingTimeout: number;
    singleFetchingTimeout: number;
    runnerExecutionTimeouts?: Record<string, Record<string, number>>;
    runResponseWhitelist?: string[];
    allowBodyConfig: boolean;
    chartsEngineConfig: {
        secrets: Record<string, string>;
        enableTelemetry: boolean;
        flags?: Record<string, boolean>;
        usEndpointPostfix: string;
        dataFetcherProxiedHeaders?: string[];
        maxWorkers?: number;
        includeServicePlan?: boolean;
        includeTenantFeatures?: true;
        tvmAllowedSources?: Record<string, number>;
        tvmAllowedSourcesWithoutUserTicket?: Record<string, number>;
        privateApiPrefixes?: string[];
    };
    // CHARTS ENGINE -- FINISH

    useIPV6?: boolean;
    workers?: number;

    requestIdHeaderName: string;
    gatewayProxyHeaders: string[];
    headersMap: Record<string, string>;

    iamResources?: {
        collection: {
            roles: {
                admin: string;
                editor: string;
                viewer: string;
                limitedViewer?: string;
                entryBindingCreator?: string;
                limitedEntryBindingCreator?: string;
            };
        };
        workbook: {
            roles: {
                admin: string;
                editor: string;
                viewer: string;
                limitedViewer?: string;
            };
        };
        sharedEntry: {
            roles: {
                admin: string;
                editor: string;
                viewer: string;
                limitedViewer?: string;
                entryBindingCreator?: string;
                limitedEntryBindingCreator?: string;
            };
        };
    };

    // auth
    isAuthEnabled: boolean;
    authTokenPublicKey?: string;
    authManageLocalUsersDisabled?: boolean;
    authSignupDisabled?: boolean;
    authCookieName?: string;
    // sorted roles from the role with the most rights to the role with the least
    orderedAuthRoles?: `${UserRole}`[];

    chartTemplates: Partial<Record<keyof ChartTemplates, unknown>>;
    redis: RedisConfig | null;
    apiPrefix: string;
    preloadList?: string[];
    releaseVersion?: string;
    docsUrl?: string;
}

export interface SharedAppDynamicConfig {
    features?: FeatureConfig;
}

export interface SharedAppContextParams {
    userId: string;
    gateway: {
        reqBody: Request['body'];
        requestId: string;

        checkRequestForDeveloperModeAccess: (args: {
            ctx: AppContext;
        }) => Promise<DeveloperModeCheckStatus>;
        markdown: MarkdownContextAction;

        resolveEntryByLink: (
            args: ResolveEntryByLinkComponentArgs,
        ) => Promise<ResolveEntryByLinkComponentResponse>;
    };

    sources: {
        reqBody: Request['body'];
    };

    getAppLayoutSettings: (req: Request, res: Response, name?: string) => AppLayoutSettings;
    landingPageSettings?: LandingPageSettings;

    i18n: ServerI18n;
    tenantId?: string;

    user?: CtxUser;

    usDynamicMasterToken?: string;

    isEnabledServerFeature: (feature: string) => boolean;
}

declare module '@gravity-ui/nodekit' {
    export interface AppConfig extends SharedAppConfig {}

    export interface AppDynamicConfig extends SharedAppDynamicConfig {}

    export interface AppContextParams extends SharedAppContextParams {}
}
