package com.prodhack.moscow2025.presentation.utils

import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import com.prodhack.moscow2025.domain.models.PhoneNumberPattern

class PhoneVisualTransformation(val mask: String, val maskNumber: Char) : VisualTransformation {

	private val maxLength = mask.count { it == maskNumber }

	override fun filter(text: AnnotatedString): TransformedText {
		val trimmed = if (text.length > maxLength) text.take(maxLength) else text

		val annotatedString = buildAnnotatedString {
			if (trimmed.isEmpty()) return@buildAnnotatedString
			var maskIndex = 0
			var textIndex = 0
			while (textIndex < trimmed.length && maskIndex < mask.length) {
				if (mask[maskIndex] != maskNumber) {
					val nextDigitIndex = mask.indexOf(maskNumber, maskIndex)
					append(mask.substring(maskIndex, nextDigitIndex))
					maskIndex = nextDigitIndex
				}
				append(trimmed[textIndex++])
				maskIndex++
			}
		}

		if (annotatedString.isEmpty()) {
			return TransformedText(annotatedString, OffsetMapping.Identity)
		}

		return TransformedText(
			annotatedString,
			PhoneOffsetMapper(
				mask = mask,
				numberChar = maskNumber,
				transformedLength = annotatedString.length,
				maxDigits = trimmed.length
			)
		)
	}

	override fun equals(other: Any?): Boolean {
		if (this === other) return true
		if (other !is PhoneVisualTransformation) return false
		if (mask != other.mask) return false
		if (maskNumber != other.maskNumber) return false
		return true
	}

	override fun hashCode(): Int {
		return mask.hashCode()
	}
}

private class PhoneOffsetMapper(
	val mask: String,
	val numberChar: Char,
	private val transformedLength: Int,
	private val maxDigits: Int
) : OffsetMapping {

	override fun originalToTransformed(offset: Int): Int {
		if (offset <= 0) return 0
		var digitsSeen = 0
		var index = 0
		val targetDigits = offset.coerceAtMost(maxDigits)

		while (index < mask.length && digitsSeen < targetDigits) {
			if (mask[index] == numberChar) {
				digitsSeen++
			}
			index++
		}
		return index.coerceAtMost(transformedLength)
	}

	override fun transformedToOriginal(offset: Int): Int =
		mask.take(offset.coerceAtMost(transformedLength)).count { it == numberChar }
}

fun convertNumberToPattern(pattern: PhoneNumberPattern, number: String): String {
	var answer = pattern.pattern.replace('0', '*')
	for (i in number){
		answer = answer.replaceFirst('*', i)
	}
	return "${pattern.countryCode} $answer"
}
