import type { IncomingMessage, ServerResponse } from 'http';

export type IncomingMessage = IncomingMessage;
export type ServerResponse = ServerResponse;

export type MetadataHandlers = Partial<Record<keyof RequestMetadata, () => string>>;

export type GraphQLOperationType = 'mutation' | 'query' | 'subscription';

export interface GraphQLData {
    name: string;
    type: GraphQLOperationType;
    count: number;
}

export interface Logger {
    debug: (message: string) => void;
    info: (message: string) => void;
    warn: (message: string) => void;
    error: (message: string) => void;
}

export interface DataDomeParameters {
    moduleName: string;
    moduleVersion: string;
    maxSockets?: number;
    maximumBodySize?: number;
    enableGraphQLSupport?: boolean;
    endpointHost?: string;
    urlPatternInclusion?: RegExp;
    urlPatternExclusion?: RegExp;
    timeout?: number;
    logger?: Logger;
}

export interface MetadataParameters {
    enableGraphQLSupport: boolean;
    logger: Logger;
    maximumBodySize: number;
    moduleName: string;
    moduleVersion: string;
    serverSideKey: string;
}

export interface RequestMetadata {
    Accept?: string;
    AcceptCharset?: string;
    AcceptEncoding?: string;
    AcceptLanguage?: string;
    APIConnectionState?: string;
    AuthorizationLen?: number;
    CacheControl?: string;
    ClientID?: string;
    Connection?: string;
    ContentType?: string;
    CookiesLen?: number;
    From?: string;
    GraphQLOperationCount?: number;
    GraphQLOperationName?: string;
    GraphQLOperationType?: GraphQLOperationType;
    HeadersList?: string;
    Host?: string;
    IP: string;
    Key: string;
    Method?: string;
    ModuleVersion?: string;
    Origin?: string;
    Port?: number;
    PostParamLen?: number;
    Pragma?: string;
    Protocol?: string;
    Referer?: string;
    Request?: string;
    RequestModuleName?: string;
    ServerHostname?: string;
    ServerName?: string;
    TimeRequest?: number;
    TrueClientIP?: string;
    UserAgent?: string;
    Via?: string;
    'X-Real-IP'?: string;
    'X-Requested-With'?: string;
    XForwardedForIP?: string;
}

export interface ValidationParameters {
    request: IncomingMessage;
    response: ServerResponse;
    headers?: Record<string, string>;
    nonce?: string;
}

export interface ValidationResult {
    ok: boolean;
    apiResponse: ServerResponse;
    request: IncomingMessage;
    response: ServerResponse;
}

export default class DataDomeCore {
    constructor(serverSideKey: string, parameters: Partial<DataDomeParameters>);

    getRequestMetadata(request: IncomingMessage, handlers: MetadataHandlers): RequestMetadata;
    validateRequest(
        metadata: RequestMetadata,
        parameters: ValidationParameters
    ): Promise<ValidationResult>;
}
