import {Module} from ".";

export type Exam = ReadingExam | ListeningExam | WritingExam | SpeakingExam | LevelExam;
export type Variant = "full" | "partial";
export type InstructorGender = "male" | "female" | "varied";
export type Difficulty = "easy" | "medium" | "hard";

interface ExamBase {
	id: string;
	module: Module;
	minTimer: number;
	isDiagnostic: boolean;
	variant?: Variant;
	difficulty?: Difficulty;
	shuffle?: boolean;
	createdBy?: string; // option as it has been added later
	createdAt?: string; // option as it has been added later
	private?: boolean;
}
export interface ReadingExam extends ExamBase {
	module: "reading";
	parts: ReadingPart[];
	type: "academic" | "general";
}

export interface ReadingPart {
	text: {
		title: string;
		content: string;
	};
	exercises: Exercise[];
}

export interface LevelExam extends ExamBase {
	module: "level";
	parts: LevelPart[];
}

export interface LevelPart {
	context?: string;
	intro?: string;
	exercises: Exercise[];
}

export interface ListeningExam extends ExamBase {
	parts: ListeningPart[];
	module: "listening";
}

export interface ListeningPart {
	audio: {
		source: string;
		repeatableTimes: number; // *The amount of times the user is allowed to repeat the audio, 0 for unlimited
	};
	exercises: Exercise[];
}

export interface UserSolution {
	id?: string;
	solutions: any[];
	module?: Module;
	exam?: string;
	type: string;
	score: {
		correct: number;
		total: number;
		missing: number;
	};
	exercise: string;
	isDisabled?: boolean;
	shuffleMaps?: ShuffleMap[];
}

export interface WritingExam extends ExamBase {
	module: "writing";
	exercises: WritingExercise[];
}

interface WordCounter {
	type: "min" | "max";
	limit: number;
}

export interface SpeakingExam extends ExamBase {
	module: "speaking";
	exercises: (SpeakingExercise | InteractiveSpeakingExercise)[];
	instructorGender: InstructorGender;
}

export type Exercise =
	| FillBlanksExercise
	| TrueFalseExercise
	| MatchSentencesExercise
	| MultipleChoiceExercise
	| WriteBlanksExercise
	| WritingExercise
	| SpeakingExercise
	| InteractiveSpeakingExercise;

export interface Evaluation {
	comment: string;
	overall: number;
	task_response: {[key: string]: number | {grade: number; comment: string}};
	misspelled_pairs?: {correction: string | null; misspelled: string}[];
}

type InteractivePerfectAnswerKey = `perfect_answer_${number}`;
type InteractiveTranscriptKey = `transcript_${number}`;
type InteractiveFixedTextKey = `fixed_text_${number}`;

type InteractivePerfectAnswerType = {[key in InteractivePerfectAnswerKey]: {answer: string}};
type InteractiveTranscriptType = {[key in InteractiveTranscriptKey]?: string};
type InteractiveFixedTextType = {[key in InteractiveFixedTextKey]?: string};

interface InteractiveSpeakingEvaluation extends Evaluation, InteractivePerfectAnswerType, InteractiveTranscriptType, InteractiveFixedTextType {}

interface SpeakingEvaluation extends CommonEvaluation {
	perfect_answer_1?: string;
	transcript_1?: string;
	fixed_text_1?: string;
}

interface CommonEvaluation extends Evaluation {
	perfect_answer?: string;
	fixed_text?: string;
}

export interface WritingExercise {
	id: string;
	type: "writing";
	prefix: string; //* The information about the task, like the amount of time they should spend on it
	suffix: string;
	prompt: string; //* The context given to the user containing what they should write about
	wordCounter: WordCounter; //* The minimum or maximum amount of words that should be written
	attachment?: {
		url: string;
		description: string;
	}; //* The url for an image to work as an attachment to show the user
	userSolutions: {
		id: string;
		solution: string;
		evaluation?: WritingEvaluation;
	}[];
	topic?: string;
}

export interface AIDetectionAttributes {
	predicted_class: "ai" | "mixed" | "human";
	confidence_category: "high" | "medium" | "low";
	class_probabilities: {
		ai: number;
		human: number;
		mixed: number;
	};
	sentences: {
		sentence: string;
		highlight_sentence_for_ai: boolean;
	}[];
}

export interface WritingEvaluation extends CommonEvaluation {
	ai_detection?: AIDetectionAttributes;
}

export interface SpeakingExercise {
	id: string;
	type: "speaking";
	title: string;
	text: string;
	prompts: string[];
	suffix?: string;
	video_url: string;
	userSolutions: {
		id: string;
		solution: string;
		evaluation?: SpeakingEvaluation;
	}[];
	topic?: string;
}

export interface InteractiveSpeakingExercise {
	id: string;
	type: "interactiveSpeaking";
	title: string;
	first_title?: string;
	second_title?: string;
	text: string;
	prompts: {text: string; video_url: string}[];
	userSolutions: {
		id: string;
		solution: {questionIndex: number; question: string; answer: string}[];
		evaluation?: InteractiveSpeakingEvaluation;
	}[];
	topic?: string;
	first_topic?: string;
	second_topic?: string;
	variant?: "initial" | "final";
}

export interface FillBlanksMCOption {
	id: string;
	options: {
		A: string;
		B: string;
		C: string;
		D: string;
	};
}

export interface FillBlanksExercise {
	prompt: string; // *EXAMPLE: "Complete the summary below. Click a blank to select the corresponding word for it."
	type: "fillBlanks";
	id: string;
	words: (string | {letter: string; word: string} | FillBlanksMCOption)[]; // *EXAMPLE: ["preserve", "unaware"]
	text: string; // *EXAMPLE: "They tried to {{1}} burning"
	allowRepetition?: boolean;
	solutions: {
		id: string; // *EXAMPLE: "1"
		solution: string; // *EXAMPLE: "preserve"
	}[];
	userSolutions: {
		id: string; // *EXAMPLE: "1"
		solution: string; // *EXAMPLE: "preserve"
	}[];
	variant?: string;
}

export interface TrueFalseExercise {
	type: "trueFalse";
	id: string;
	prompt: string; // *EXAMPLE: "Select the appropriate option."
	questions: TrueFalseQuestion[];
	userSolutions: {id: string; solution: "true" | "false" | "not_given"}[];
}

export interface TrueFalseQuestion {
	id: string; // *EXAMPLE: "1"
	prompt: string; // *EXAMPLE: "What does her briefcase look like?"
	solution: "true" | "false" | "not_given"; // *EXAMPLE: "True"
}

export interface WriteBlanksExercise {
	prompt: string; // *EXAMPLE: "Complete the notes below by writing NO MORE THAN THREE WORDS in the spaces provided."
	maxWords: number; // *EXAMPLE: 3 - The maximum amount of words allowed per blank, 0 for unlimited
	type: "writeBlanks";
	id: string;
	text: string; // *EXAMPLE: "The Government plans to give ${{14}}"
	solutions: {
		id: string; // *EXAMPLE: "14"
		solution: string[]; // *EXAMPLE: ["Prescott"] - All possible solutions (case sensitive)
	}[];
	userSolutions: {
		id: string;
		solution: string;
	}[];
}

export interface MatchSentencesExercise {
	type: "matchSentences";
	id: string;
	prompt: string;
	userSolutions: {question: string; option: string}[];
	sentences: MatchSentenceExerciseSentence[];
	allowRepetition: boolean;
	options: MatchSentenceExerciseOption[];
}

export interface MatchSentenceExerciseSentence {
	id: string;
	sentence: string;
	solution: string;
	color: string;
}

export interface MatchSentenceExerciseOption {
	id: string;
	sentence: string;
}

export interface MultipleChoiceExercise {
	type: "multipleChoice";
	id: string;
	prompt: string; // *EXAMPLE: "Select the appropriate option."
	questions: MultipleChoiceQuestion[];
	userSolutions: {question: string; option: string}[];
}

export interface MultipleChoiceQuestion {
	variant: "image" | "text";
	id: string; // *EXAMPLE: "1"
	prompt: string; // *EXAMPLE: "What does her briefcase look like?"
	solution: string; // *EXAMPLE: "A"
	options: {
		id: string; // *EXAMPLE: "A"
		src?: string; // *EXAMPLE: "https://i.imgur.com/rEbrSqA.png" (only used if the variant is "image")
		text?: string; // *EXAMPLE: "wallet, pens and novel" (only used if the variant is "text")
	}[];
	shuffleMap?: Record<string, string>;
}

export interface ShuffleMap {
	questionID: string;
	map: {
		[key: string]: string;
	};
}

export interface Shuffles {
	exerciseID: string;
	shuffles: ShuffleMap[];
}
