import { Conversation } from '@twilio/conversations';
import { JSX as JSX_2 } from 'react/jsx-runtime';
import { LastMessage } from '@twilio/conversations';
import { Media } from '@twilio/conversations';
import { Message } from '@twilio/conversations';
import { Participant } from '@twilio/conversations';
import { User } from '@twilio/conversations';

declare type AvailabilityModule = ChatModule<ModuleName.AVAILABILITY, ModuleType.QUESTION, MultiAnswerQuestions>;

export declare const ChatbotClient: (clientConfig?: IChatbotClient) => JSX_2.Element;

declare type ChatModule<N extends ModuleName, T extends ModuleType, D extends ModuleDataAnswer | EmptyObject = EmptyObject> = {
    id: string;
    name: N;
    type: T;
    completed: boolean;
    data: GenericConfig & D;
};

declare const enum CustomAction {
    SEND_MESSAGE = "sendMessage",
    SHOW_TNC = "showTnc",
    SHOW_FEEDBACK = "showFeedback",
    OPEN_LINK = "openLink"
}

declare const enum DateFormat {
    GBR = "DD/MM/YYYY",
    US = "MM/DD/YYYY"
}

declare type DateFormatData = {
    format: DateFormat;
};

declare type DateModule = ChatModule<ModuleName.DATE, ModuleType.DATE, DateFormatData>;

declare enum DocumentType_2 {
    Passport = "P",
    DriversLicense = "D",
    IdentityCard = "I"
}

declare type DropdownModule = ChatModule<ModuleName.DROPDOWN, ModuleType.DROPDOWN, SingleSelect>;

declare type EmailModule = ChatModule<ModuleName.EMAIL, ModuleType.EMAIL>;

declare type EmptyObject = Record<never, never>;

declare type Feedback = {
    points: 1 | 0 | -1;
    note?: string;
};

declare type FeedbackModule = ChatModule<ModuleName.FEEDBACK, ModuleType.FEEDBACK, Feedback>;

declare type FileUploadModule = ChatModule<ModuleName.FILE_UPLOAD, ModuleType.FILE_UPLOAD>;

declare type FreeTextModule = ChatModule<ModuleName.FREE_TEXT, ModuleType.FREE_TEXT>;

declare type GenericConfig = {
    title: string;
    description: string;
    required?: boolean;
    questionMedia?: QuestionMedia;
    antiCheat?: boolean;
    forceRecording?: boolean;
    buttonText?: string;
};

declare type GenericOption = {
    id: string;
    title: string;
    selected: boolean;
};

declare interface IChatbot {
    config: IConfig;
    candidate_id?: string;
    ai_model?: string;
}

export declare type IChatbotClient = Partial<Omit<IChatbot, 'config'> & {
    config: IConfigClient;
}>;

declare interface IConfig {
    isReady: boolean;
    validationStatus: ValidationStatus;
    auth: string;
    useInbox?: boolean;
    usePopup?: boolean;
    autoOpen?: boolean;
    position?: IPosition;
    offsetX?: string;
    offsetY?: string;
    preferredHeight?: number;
    preferredWidth?: number;
    env?: IEnv;
    debug?: boolean;
    timeFormat?: ITimeFormat;
    theme: ITheme;
    colors: {
        primaryColor: string;
        secondaryColor: string;
        primaryDarkColor: string;
        secondaryDarkColor: string;
    };
    enabledIntercom?: boolean;
    dtnc?: boolean;
    onOpen?: () => void;
    onClose?: () => void;
    onConversationCreated?: ({ sid, candidate_id, user_identity, conversation_attributes }: {
        sid: string;
        candidate_id: string;
        user_identity: IMain['currentUser']['identity'];
        conversation_attributes: IMain['conversations'][number]['attributes'];
    }) => void;
    onHelpClicked?: ({ candidate_id, conversation_sid, user_identity, conversation_attributes }: Partial<{
        candidate_id: string;
        conversation_sid: IMain['selectedConversationId'];
        user_identity: IMain['currentUser']['identity'];
        conversation_attributes: IMain['conversations'][number]['attributes'];
    }>) => void;
    onFinish?: (data: IOnFinishData) => void;
    onError?: (data: IOnErrorData) => void;
}

declare type IConfigClient = Partial<Omit<IConfig, 'usePopup' | 'isReady' | 'validationStatus' | 'dtnc'>>;

declare type IDAnalayzerMethod = {
    methods: DocumentType_2[];
};

declare type IDAnalayzerModule = ChatModule<ModuleName.ID_ANALYZER, ModuleType.ID_ANALYZER, IDAnalayzerMethod>;

declare type IEnv = 'development' | 'staging' | 'production';

declare interface IMain {
    users: {
        [userId: ReduxUser['identity']]: ReduxUser;
    };
    currentUser: ReduxUser;
    conversations: ReduxConversation[];
    messages: {
        [convoSid: Conversation['sid']]: ReduxMessage[];
    };
    participants: {
        [convoSid: Conversation['sid']]: ReduxParticipant[];
    };
    typingData: {
        [convoSid: Conversation['sid']]: ReduxParticipant['sid'][];
    };
    selectedConversationId: string;
}

declare interface IMediaDimensions {
    width: number;
    height: number;
}

declare interface IOnErrorData {
    errorMessage: string;
}

declare interface IOnFinishData {
    video_id: string;
}

declare type IPosition = 'left' | 'right';

declare type ITheme = 'light' | 'dark' | 'deviceDefault';

declare type ITimeFormat = '12h' | '24h' | 'deviceDefault';

declare type JobsModule = ChatModule<ModuleName.JOBS, ModuleType.JOBS, JobsModuleData>;

declare type JobsModuleData = {
    jobs: {
        job_id: string;
        title: string;
    }[];
    count: number;
    selected_id: string;
};

declare type LinkModule = ChatModule<ModuleName.URL, ModuleType.LINK>;

declare type LocationModule = ChatModule<ModuleName.LOCATION, ModuleType.LOCATION>;

declare type MatrixModule = ChatModule<ModuleName.MATRIX_CHOICE, ModuleType.QUESTION, MultiAnswerQuestions>;

declare type MessageModule = (AvailabilityModule | DateModule | DropdownModule | EmailModule | FileUploadModule | FreeTextModule | IDAnalayzerModule | LinkModule | LocationModule | MatrixModule | MultiSelectModule | NumberModule | PhoneNumberModule | ScheduleModule | SingleSelectModule | WidgetModule | YesNoSelectModule | JobsModule | TncModule | FeedbackModule);

declare type ModuleDataAnswer = SingleSelect | MultiSelect | MultiAnswerQuestions | DateFormatData | IDAnalayzerMethod | ScheduleConfig | JobsModuleData | TncConfig | Feedback;

declare const enum ModuleName {
    YES_NO = "YES_NO",
    SINGLE_CHOICE = "SINGLE_CHOICE",
    MULTIPLE_CHOICE = "MULTIPLE_CHOICE",
    FREE_TEXT = "FREE_TEXT",
    LOCATION = "LOCATION",
    DATE = "DATE",
    EMAIL = "EMAIL",
    PHONE_NUMBER = "PHONE_NUMBER",
    FILE_UPLOAD = "FILE_UPLOAD",
    URL = "URL",
    NUMBER = "NUMBER",
    DROPDOWN = "DROPDOWN",
    WIDGET = "WIDGET",
    SCHEDULE = "SCHEDULE",
    MATRIX_CHOICE = "MATRIX_CHOICE",
    AVAILABILITY = "AVAILABILITY",
    ID_ANALYZER = "ID_ANALYZER",
    JOBS = "JOBS",
    TNC = "TNC",
    FEEDBACK = "FEEDBACK",
    THANK_YOU = "THANK_YOU",
    REJECT = "REJECT"
}

declare const enum ModuleType {
    YES_NO = "yesNoSelectInput",
    SINGLE_SELECT = "singleSelectInput",
    MULTI_SELECT = "multiSelectInput",
    DROPDOWN = "dropdownInput",
    FREE_TEXT = "freeTextInput",
    LOCATION = "locationInput",
    DATE = "dateInput",
    EMAIL = "emailInput",
    PHONE_NUMBER = "phoneNumberInput",
    FILE_UPLOAD = "fileUploadInput",
    LINK = "linkInput",
    NUMBER = "numberInput",
    QUESTION = "questions",
    SCHEDULE_MEETING = "scheduleMeeting",
    WIDGET = "widget",
    ID_ANALYZER = "idAnalyzer",
    JOBS = "jobs",
    TNC = "tnc",
    FEEDBACK = "feedback"
}

declare type MultiAnswerQuestions = Questions<{
    selected_ids: GenericOption['id'][];
}>;

declare type MultiSelect = Options<{
    selected_ids: GenericOption['id'][];
    maxSelected: number;
    minSelected: number;
}>;

declare type MultiSelectModule = ChatModule<ModuleName.MULTIPLE_CHOICE, ModuleType.MULTI_SELECT, MultiSelect>;

declare type NumberModule = ChatModule<ModuleName.NUMBER, ModuleType.NUMBER>;

declare type Options<T> = {
    options: GenericOption[];
} & T;

declare type PhoneNumberModule = ChatModule<ModuleName.PHONE_NUMBER, ModuleType.PHONE_NUMBER>;

declare type Question = {
    id: string;
    title: string;
    selectAllTitle?: string;
    answers: GenericOption[];
};

declare type QuestionMedia = {
    questionType?: QuestionType;
    questionUrl?: string;
};

declare type Questions<T> = {
    questions: (Question & T)[];
};

declare const enum QuestionType {
    TEXT_ONLY = "",
    IMAGE = "image",
    VIDEO = "video"
}

declare type ReduxConversation = Pick<Conversation, 'friendlyName' | 'lastReadMessageIndex' | 'notificationLevel' | 'sid'> & {
    readonly dateUpdated: number | null;
    readonly dateCreated: number | null;
    readonly lastMessage: {
        readonly dateCreated: number | undefined;
        readonly index: LastMessage['index'];
    };
    readonly attributes: ReduxConversationAttributes;
};

declare type ReduxConversationAttributes = {
    candidate_id: string;
    video_id: string;
    company_id: string;
    job_id: string;
    locale_calendar: string;
    locale_day: string;
    locale_locale: string;
    locale_month: string;
    locale_numberingSystem: string;
    locale_timeZone: string;
    locale_year: string;
    photoUrl: string;
    bot_action?: string;
    email?: string;
    username?: string;
    lang?: string;
    text?: {
        online?: string;
        offline?: string;
        input_placeholder?: string;
        waiting_for_permission?: string;
        record_answer?: string;
    };
};

declare type ReduxCurrentUserAttributes = {
    thumb?: string;
};

declare type ReduxMedia = Pick<Media, 'sid' | 'filename' | 'contentType' | 'size' | 'category'>;

declare type ReduxMessage = Pick<Message, 'sid' | 'author' | 'body' | 'index' | 'participantSid' | 'type'> & {
    readonly dateCreated: number | null;
    readonly attributes: ReduxMessageAttributes;
    readonly attachedMedia: ReduxMedia[] | null;
    readonly type?: string;
};

declare type ReduxMessageAttributes = {
    module?: MessageModule;
    module_id?: string;
    ts?: number;
    mediaDimensions?: IMediaDimensions;
    photoUrl?: string;
    transcript?: string;
    suggestions?: Suggestion[];
};

declare type ReduxParticipant = Pick<Participant, 'sid' | 'identity' | 'type' | 'lastReadMessageIndex'> & {
    readonly attributes: ReduxParticipantAttributes;
};

declare type ReduxParticipantAttributes = {
    thumb?: string;
};

declare type ReduxUser = Pick<User, 'identity'> & {
    readonly attributes: ReduxCurrentUserAttributes;
};

declare type ScheduleConfig = {
    schedule: {
        availability_days: number;
        conferencing: {
            name: string;
            profile_id: string;
        };
        description: string;
        required_duration: number;
        title: string;
    };
    buttonText?: {
        scheduled: 'Scheduled';
        scheduling: 'Scheduling...';
        schedule: 'Schedule';
    };
};

declare type ScheduleModule = ChatModule<ModuleName.SCHEDULE, ModuleType.SCHEDULE_MEETING, ScheduleConfig>;

declare type SingleSelect = Options<{
    selected_id: GenericOption['id'];
}>;

declare type SingleSelectModule = ChatModule<ModuleName.SINGLE_CHOICE, ModuleType.SINGLE_SELECT, SingleSelect>;

declare type Suggestion = {
    text: string;
    attributes: Record<string, unknown>;
    customActions: CustomAction[];
    layouts?: SuggestionLayouts[];
};

declare type SuggestionLayouts = 'box';

declare type TncConfig = {
    company: string;
    url?: string;
    agreed: boolean;
    header?: string;
    body?: string;
    buttonText?: {
        cta: string;
        agree: string;
        disagree: string;
    };
};

declare type TncModule = ChatModule<ModuleName.TNC, ModuleType.TNC, TncConfig>;

export declare const usePopupChatbot: () => {
    init: (clientConfig: IChatbotClient) => void;
    update: (clientConfig?: IChatbotClient) => void;
    shutdown: () => void;
};

declare const enum ValidationStatus {
    VALID = 0,
    INVALID = 1,
    NOT_FOUND = 2
}

declare type Widget = {
    buttonText?: {
        start: string;
        resume: string;
        completed: string;
    };
};

declare type WidgetModule = ChatModule<ModuleName.WIDGET, ModuleType.WIDGET, Widget>;

declare type YesNoSelectModule = ChatModule<ModuleName.YES_NO, ModuleType.YES_NO, SingleSelect>;

export { }
