package com.prodhack.moscow2025.data.dto

import com.prodhack.moscow2025.data.data_providers.local_db.entities.JsonTypeConverters
import com.prodhack.moscow2025.data.data_providers.local_db.entities.ResumeEntity
import com.prodhack.moscow2025.domain.models.Education
import com.prodhack.moscow2025.domain.models.EducationGrades
import com.prodhack.moscow2025.domain.models.ExperienceType
import com.prodhack.moscow2025.domain.models.Project
import com.prodhack.moscow2025.domain.models.ResumeCreationModel
import com.prodhack.moscow2025.domain.models.ResumeModel
import com.prodhack.moscow2025.domain.models.WorkExperience
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
enum class ExperienceTypeDTO {
	@SerialName("noExperience")
	NoExperience,


	@SerialName("between1And3")
	Between1And3,

	@SerialName("between3And6")
	Between3And6,

	@SerialName("moreThan6")
	MoreThan6;

	fun mapToDomain(): ExperienceType = when (this) {
		NoExperience -> ExperienceType.NoExperience
		Between1And3 -> ExperienceType.Between1And3
		Between3And6 -> ExperienceType.Between3And6
		MoreThan6 -> ExperienceType.MoreThan6
	}
}

fun ExperienceType.mapToData(): ExperienceTypeDTO = when (this) {
	ExperienceType.NoExperience -> ExperienceTypeDTO.NoExperience
	ExperienceType.Between1And3 -> ExperienceTypeDTO.Between1And3
	ExperienceType.Between3And6 -> ExperienceTypeDTO.Between3And6
	ExperienceType.MoreThan6 -> ExperienceTypeDTO.MoreThan6
}

@Serializable
data class ResumeDTO(
	val id: String,
	@SerialName("experience_type")
	val experienceType: ExperienceTypeDTO,
	@SerialName("about_me")
	val aboutMe: String,
	@SerialName("key_skills")
	val keySkills: List<String>,
	val position: String,
	@SerialName("location")
	val city: String,
	val experience: List<ExperienceDTO> = emptyList(),
	val education: List<EducationDTO> = emptyList(),
	@SerialName("projects")
	val project: List<ProjectDTO> = emptyList(),
	val prediction: PredictionDTO? = null
) {
	fun mapToDomain(): ResumeModel = ResumeModel(
		id = id,
		about = aboutMe,
		skills = keySkills,
		position = position,
		experienceType = experienceType.mapToDomain(),
		prediction = prediction?.let {
			Pair(
				it.fromSalary.toFloatOrNull(),
				it.toSalary.toFloatOrNull()
			)
		},
		recommendedSkills = prediction?.recommendedSkills,
		city = city,
		experience = experience.map { it.mapToDomain() },
		education = education.map { it.mapToDomain() },
		projects = project.map { it.mapToDomain() }
	)

	fun mapToDB(): ResumeEntity = ResumeEntity(
		id = id,
		aboutMe = aboutMe,
		keySkills = keySkills.joinToString("|"),
		position = position,
		fromSalary = prediction?.fromSalary?.toFloatOrNull(),
		toSalary = prediction?.toSalary?.toFloatOrNull(),
		recommendedSkills = prediction?.recommendedSkills?.joinToString("|") ?: "",
		experienceType = experienceType.mapToDomain().name,
		city = city,
		experience = JsonTypeConverters.fromWorkExperienceList(experience.map { it.mapToDomain() }),
		education = JsonTypeConverters.fromEducationList(education.map { it.mapToDomain() }),
		projects = JsonTypeConverters.fromProjectList(project.map { it.mapToDomain() }),
	)
}

@Serializable
data class ExperienceDTO(
	val place: String,
	val description: String,
	@SerialName("months_duration")
	val monthDuration: Int,
) {
	fun mapToDomain(): WorkExperience = WorkExperience(
		place = place,
		description = description,
		monthDuration = monthDuration
	)
}

fun WorkExperience.mapToData(): ExperienceDTO = ExperienceDTO(
	place = place,
	description = description,
	monthDuration = monthDuration ?: 0
)

@Serializable
data class EducationDTO(
	val place: String,
	val grade: EducationGradesDTO,
	val specialization: String,
	val description: String
) {
	fun mapToDomain(): Education = Education(
		place = place,
		grade = grade.mapToDomain(),
		specialization = specialization,
		description = description
	)
}

fun Education.mapToData(): EducationDTO = EducationDTO(
	place = place,
	grade = grade.mapToData(),
	specialization = specialization,
	description = description
)

@Serializable
enum class EducationGradesDTO {
	@SerialName("basic_general_education")
	BasicGeneralEducation,

	@SerialName("secondary_general_education")
	SecondaryGeneralEducation,

	@SerialName("secondary_professional_education")
	SecondaryProfessionalEducation,

	@SerialName("bachelor")
	Bachelor,

	@SerialName("specialist")
	Specialist,

	@SerialName("master")
	Master,

	@SerialName("postgraduate_studies")
	PostgraduateStudies,

	@SerialName("other")
	Other;

	fun mapToDomain(): EducationGrades = when (this) {
		BasicGeneralEducation -> EducationGrades.BasicGeneralEducation
		SecondaryGeneralEducation -> EducationGrades.SecondaryGeneralEducation
		SecondaryProfessionalEducation -> EducationGrades.SecondaryProfessionalEducation
		Bachelor -> EducationGrades.Bachelor
		Specialist -> EducationGrades.Specialist
		Master -> EducationGrades.Master
		PostgraduateStudies -> EducationGrades.PostgraduateStudies
		Other -> EducationGrades.Other
	}
}

fun EducationGrades.mapToData(): EducationGradesDTO =
	when (this) {
		EducationGrades.BasicGeneralEducation -> EducationGradesDTO.BasicGeneralEducation
		EducationGrades.SecondaryGeneralEducation -> EducationGradesDTO.SecondaryGeneralEducation
		EducationGrades.SecondaryProfessionalEducation -> EducationGradesDTO.SecondaryProfessionalEducation
		EducationGrades.Bachelor -> EducationGradesDTO.Bachelor
		EducationGrades.Specialist -> EducationGradesDTO.Specialist
		EducationGrades.Master -> EducationGradesDTO.Master
		EducationGrades.PostgraduateStudies -> EducationGradesDTO.PostgraduateStudies
		EducationGrades.Other -> EducationGradesDTO.Other
	}

@Serializable
data class ProjectDTO(
	val name: String,
	val description: String
) {
	fun mapToDomain(): Project = Project(
		name = name,
		description = description
	)
}

fun Project.mapToData(): ProjectDTO = ProjectDTO(
	name = name,
	description = description
)

@Serializable
data class ResumeCreateDTO(
	@SerialName("experience_type")
	val experienceType: ExperienceTypeDTO,
	@SerialName("about_me")
	val aboutMe: String,
	@SerialName("key_skills")
	val keySkills: List<String>,
	val position: String,
	@SerialName("location")
	val city: String,
	val experience: List<ExperienceDTO>? = null,
	val education: List<EducationDTO>? = null,
	@SerialName("projects")
	val project: List<ProjectDTO>? = null,
)

fun ResumeCreationModel.mapToData(): ResumeCreateDTO = ResumeCreateDTO(
	experienceType = experienceType.mapToData(),
	aboutMe = about,
	keySkills = skills,
	position = position,
	city = city,
	experience = experience.map { it.mapToData() },
	education = education.map { it.mapToData() },
	project = projects.map { it.mapToData() }
)

@Serializable
data class PredictionDTO(
	@SerialName("from_salary")
	val fromSalary: String,
	@SerialName("to_salary")
	val toSalary: String,
	@SerialName("recommended_skills")
	val recommendedSkills: List<String>
)

@Serializable
data class ResumeListDTO(
	val resumes: List<ResumeDTO>
)

@Serializable
data class ResumeIdDTO(
	@SerialName("resume_id")
	val resumeId: String
)

@Serializable
data class ResumeSkillDTO(
	val name: String
)