package com.prodhack.moscow2025.domain.usecase.auth

import android.util.Patterns
import com.prodhack.moscow2025.domain.models.AuthField
import com.prodhack.moscow2025.domain.models.Education
import com.prodhack.moscow2025.domain.models.ExperienceType
import com.prodhack.moscow2025.domain.models.PhoneNumberPattern
import com.prodhack.moscow2025.domain.models.Project
import com.prodhack.moscow2025.domain.models.ResumeField
import com.prodhack.moscow2025.domain.models.WorkExperience
import org.koin.core.annotation.Single

data class ValidationResult<T>(
	val errors: Map<T, String> = emptyMap()
) {
	val isValid: Boolean
		get() = errors.isEmpty()
}

@Single
class ValidateFieldsUseCase {
	fun validateProfile(
		chosenPattern: PhoneNumberPattern?,
		firstName: String,
		lastName: String,
		email: String,
		phone: String
	): ValidationResult<AuthField> {
		val errors = buildMap {
			if (firstName.isBlank()) put(AuthField.FirstName, "Введите имя")
			if (lastName.isBlank()) put(AuthField.LastName, "Введите фамилию")
			if (!isEmailValid(email)) put(AuthField.Email, "Некорректный email")
			val maxCount = chosenPattern!!.pattern.count { it == '0' }
			if (phone.isNotBlank() && !isPhoneValid(phone) && phone.length != maxCount) put(
				AuthField.Phone,
				"Некорректный номер телефона"
			)
		}
		return ValidationResult(errors)
	}

	fun validateFillProfile(
		chosenPattern: PhoneNumberPattern?,
		firstName: String,
		lastName: String,
		phone: String
	): ValidationResult<AuthField> {
		val errors = buildMap {
			if (firstName.isBlank()) put(AuthField.FirstName, "Введите имя")
			if (lastName.isBlank()) put(AuthField.LastName, "Введите фамилию")
			val maxCount = chosenPattern!!.pattern.count { it == '0' }
			if (phone.isNotBlank() && !isPhoneValid(phone) && phone.length != maxCount) put(
				AuthField.Phone,
				"Некорректный номер телефона"
			)
		}
		return ValidationResult(errors)
	}

	fun validateSignUp(
		email: String,
		password: String,
		confirmPassword: String
	): ValidationResult<AuthField> {
		val errors = buildMap {
			if (!isEmailValid(email)) put(AuthField.Email, "Некорректный email")
			validatePassword(password)?.let { put(AuthField.Password, it) }
			if (confirmPassword.isBlank()) put(AuthField.ConfirmPassword, "Повторите пароль")

			if (password != confirmPassword) {
				put(AuthField.ConfirmPassword, "Пароли не совпадают")
			}
		}
		return ValidationResult(errors)
	}

	fun validateLogin(
		email: String,
		password: String
	): ValidationResult<AuthField> {
		val errors = buildMap {
			if (!isEmailValid(email)) put(AuthField.Email, "Некорректный email")
			validatePassword(password)?.let { put(AuthField.Password, it) }
		}
		return ValidationResult(errors)
	}


	fun validateResume(
		about: String,
		position: String,
		experience: ExperienceType?,
		keySkills: List<String>,
		city: String,
		workExperience: List<WorkExperience>,
		education: List<Education>,
		projects: List<Project>
	): ValidationResult<ResumeField> {
		val errors = buildMap {
			if (about.isBlank()) put(ResumeField.About, "Без этого мы не сможем рассчитать вашу ЗП")
			if (position.isBlank()) put(
				ResumeField.Position,
				"Без этого мы не сможем рассчитать вашу ЗП"
			)
			if (experience == null) put(
				ResumeField.Experience,
				"Без этого мы не сможем рассчитать вашу ЗП"
			)
			if (keySkills.isEmpty()) put(ResumeField.KeySkills, "Укажите хотя бы один навык")

			if (city.isEmpty()) put(ResumeField.City, "Без этого мы не сможем рассчитать вашу ЗП")
			workExperience.forEachIndexed { index, exp ->
				if (exp.place.isBlank()) put(
					ResumeField.WorkExperiencePlace(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
				if (exp.description.isBlank()) put(
					ResumeField.WorkExperienceDescription(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
				if (exp.monthDuration == null) put(
					ResumeField.WorkExperienceMonthDuration(index),
					"Введите корректное число"
				)
			}

			education.forEachIndexed { index, educ ->
				if (educ.place.isBlank()) put(
					ResumeField.EducationPlace(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
				if (educ.description.isBlank()) put(
					ResumeField.EducationDescription(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
				if (educ.specialization.isBlank()) put(
					ResumeField.EducationSpecialization(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
			}

			projects.forEachIndexed { index, prj ->
				if (prj.name.isBlank()) put(
					ResumeField.ProjectName(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
				if (prj.description.isBlank()) put(
					ResumeField.ProjectDescription(index),
					"Без этого мы не сможем рассчитать вашу ЗП"
				)
			}
		}
		return ValidationResult(errors)
	}

	fun validatePassword(password: String): String? {
		if (password.length < 8) {
			return "Пароль должен быть не менее 8 символов"
		}
		if (!password.any { it.isUpperCase() }) {
			return "Пароль должен содержать хотя бы одну заглавную букву"
		}
		if (!password.any { it.isDigit() }) {
			return "Пароль должен содержать хотя бы одну цифру"
		}
		if (!password.any { !it.isLetterOrDigit() }) {
			return "Пароль должен содержать хотя бы один специальный символ"
		}
		return null
	}

	private fun isEmailValid(email: String): Boolean =
		email.isNotBlank() && Patterns.EMAIL_ADDRESS.matcher(email).matches()

	private fun isPhoneValid(phone: String): Boolean =
		Patterns.PHONE.matcher(phone).matches()
}
