package linguistics

import (
	"strings"
)

// PhoneticEncoder encodes words phonetically
type PhoneticEncoder struct{}

// NewPhoneticEncoder creates a new PhoneticEncoder
func NewPhoneticEncoder() *PhoneticEncoder {
	return &PhoneticEncoder{}
}

// Encode encodes a word phonetically and returns the encoding
func (e *PhoneticEncoder) Encode(word string) string {
	// This is a simplified implementation of the Soundex algorithm
	// In a real-world scenario, you would use a library like github.com/jdkato/prose
	// or call an external API for phonetic encoding

	// Convert to uppercase
	word = strings.ToUpper(word)

	// Remove non-alphabetic characters
	var sb strings.Builder
	for _, r := range word {
		if r >= 'A' && r <= 'Z' {
			sb.WriteRune(r)
		}
	}
	word = sb.String()

	// Return empty string for empty input
	if len(word) == 0 {
		return ""
	}

	// Keep the first letter
	result := string(word[0])

	// Map consonants to digits
	for i := 1; i < len(word); i++ {
		c := word[i]
		var code byte

		switch c {
		case 'B', 'F', 'P', 'V':
			code = '1'
		case 'C', 'G', 'J', 'K', 'Q', 'S', 'X', 'Z':
			code = '2'
		case 'D', 'T':
			code = '3'
		case 'L':
			code = '4'
		case 'M', 'N':
			code = '5'
		case 'R':
			code = '6'
		default:
			code = '0' // Vowels and 'H', 'W', 'Y'
		}

		// Skip vowels and 'H', 'W', 'Y'
		if code == '0' {
			continue
		}

		// Skip duplicates
		if i > 1 && code == result[len(result)-1] {
			continue
		}

		result += string(code)

		// Limit to 4 characters
		if len(result) >= 4 {
			break
		}
	}

	// Pad with zeros if necessary
	for len(result) < 4 {
		result += "0"
	}

	return result
}

// DoubleMetaphone is an alternative phonetic algorithm
func (e *PhoneticEncoder) DoubleMetaphone(word string) (string, string) {
	// This is a simplified implementation of the Double Metaphone algorithm
	// In a real-world scenario, you would use a library or call an external API

	// For simplicity, we'll just return the Soundex code and a variation
	soundex := e.Encode(word)

	// Create a variation by replacing the first digit with the next digit
	var variation string
	if len(soundex) > 1 {
		firstDigit := soundex[1]
		var nextDigit byte
		if firstDigit >= '6' {
			nextDigit = '1'
		} else {
			nextDigit = firstDigit + 1
		}
		variation = string(soundex[0]) + string(nextDigit) + soundex[2:]
	} else {
		variation = soundex
	}

	return soundex, variation
}
