import 'dart:math';

class HangulUtils {
  static const int FIRST_HANGUL = 44032; // '가'
  static const int LAST_HANGUL = 55203; // '힣'

  static const List<String> CHOSUNG_LIST = [
    'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 
    'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
  ];
  static const List<String> JUNGSUNG_LIST = [
    'ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', 
    'ㅙ', 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ', 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ'
  ];
  static const List<String> JONGSUNG_LIST = [
    '', 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄹ', 'ㄺ', 
    'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ', 'ㅂ', 'ㅄ', 'ㅅ', 
    'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
  ];

  static final Random _random = Random();

  /// 단어를 입력받아, 랜덤한 한 글자를 아주 살짝 변형해서 반환
  static String generateSimilarWord(String original) {
    if (original.isEmpty) return original;

    // 1. 한글인 문자들의 인덱스만 찾음
    List<int> hangulIndices = [];
    for (int i = 0; i < original.length; i++) {
      int code = original.codeUnitAt(i);
      if (code >= FIRST_HANGUL && code <= LAST_HANGUL) {
        hangulIndices.add(i);
      }
    }

    if (hangulIndices.isEmpty) return original; // 한글 없으면 그대로 반환

    // 2. 바꿀 글자 위치 랜덤 선택
    int targetIndex = hangulIndices[_random.nextInt(hangulIndices.length)];
    String targetChar = original[targetIndex];

    // 3. 글자 변형
    String modifiedChar = _tweakHangul(targetChar);

    // 4. 조합해서 반환
    return original.replaceRange(targetIndex, targetIndex + 1, modifiedChar);
  }

  /// 한 글자를 분해해서 초/중/종성 중 하나를 살짝 바꿈
  static String _tweakHangul(String char) {
    int code = char.codeUnitAt(0) - FIRST_HANGUL;

    int choIndex = code ~/ (21 * 28);
    int jungIndex = (code % (21 * 28)) ~/ 28;
    int jongIndex = code % 28;

    // 무엇을 바꿀지 결정 (0:초성, 1:중성, 2:종성)
    // 종성이 없는 글자('가')라면 종성을 추가하는 것도 방법이지만, 
    // 너무 티가 나므로 초/중성 위주로 변경
    int type = _random.nextInt(3);

    if (type == 0) {
      // [초성 변경] 비슷한 모양으로 변경 시도
      choIndex = _getSimilarIndex(choIndex, CHOSUNG_LIST.length);
    } else if (type == 1) {
      // [중성 변경] (ㅏ -> ㅑ, ㅗ -> ㅜ 등)
      jungIndex = _getSimilarIndex(jungIndex, JUNGSUNG_LIST.length);
    } else {
      // [종성 변경]
      jongIndex = _getSimilarIndex(jongIndex, JONGSUNG_LIST.length);
    }

    // 재조립
    int newCode = FIRST_HANGUL + (choIndex * 21 * 28) + (jungIndex * 28) + jongIndex;
    return String.fromCharCode(newCode);
  }

  /// 인덱스를 랜덤하게 +-1 하거나 변경하여 "비슷한" 느낌을 줌
  static int _getSimilarIndex(int current, int max) {
    // 단순히 랜덤이 아니라, 현재 값과 가까운 값으로 변경하면 더 헷갈림
    int offset = _random.nextBool() ? 1 : -1;
    int next = current + offset;
    
    if (next < 0) next = 1;
    if (next >= max) next = max - 2;
    
    // 만약 원래랑 같아져버리면 강제로 변경
    if (next == current) next = (current + 1) % max;
    
    return next;
  }
}