import 'package:flutter_test/flutter_test.dart';
import 'package:userfront/core/i18n/locale_storage_backend.dart';
import 'package:userfront/core/i18n/locale_storage_engine.dart';
import 'package:userfront/core/i18n/locale_storage_policy.dart';

class _FakeTarget implements LocaleStorageTarget {
  _FakeTarget();

  final Map<String, String> store = {};
  bool throwOnRead = false;
  bool throwOnWrite = false;
  bool throwOnRemove = false;
  bool throwOnClear = false;

  @override
  String? read(String key) {
    if (throwOnRead) {
      throw StateError('read blocked');
    }
    return store[key];
  }

  @override
  bool write(String key, String value) {
    if (throwOnWrite) {
      throw StateError('write blocked');
    }
    store[key] = value;
    return true;
  }

  @override
  bool remove(String key) {
    if (throwOnRemove) {
      throw StateError('remove blocked');
    }
    store.remove(key);
    return true;
  }

  @override
  void clear() {
    if (throwOnClear) {
      throw StateError('clear blocked');
    }
    store.clear();
  }
}

void main() {
  late _FakeTarget localTarget;
  late _FakeTarget sessionTarget;
  late LocaleStorageEngine engine;

  setUp(() {
    localTarget = _FakeTarget();
    sessionTarget = _FakeTarget();
    engine = LocaleStorageEngine(
      localTarget: localTarget,
      sessionTarget: sessionTarget,
    );
    engine.clearForTests();
  });

  test('기본 모드에서는 local 우선으로 저장/조회한다', () {
    engine.write('ko');
    expect(engine.read(), 'ko');

    final state = engine.debugStateForTests();
    expect(state.localCurrent, 'ko');
    expect(state.sessionCurrent, isNull);
    expect(state.memoryCurrent, isNull);
  });

  test('legacy key를 읽으면 current key로 마이그레이션한다', () {
    localTarget.store[LocaleStoragePolicy.legacyKey] = 'en';

    expect(engine.read(), 'en');

    final state = engine.debugStateForTests();
    expect(state.localCurrent, 'en');
    expect(state.localLegacy, isNull);
  });

  test('localStorage가 차단되면 sessionStorage로 fallback 한다', () {
    localTarget
      ..throwOnRead = true
      ..throwOnWrite = true
      ..throwOnRemove = true;

    engine.write('ko');
    expect(engine.read(), 'ko');

    final state = engine.debugStateForTests();
    expect(state.localCurrent, isNull);
    expect(state.sessionCurrent, 'ko');
    expect(state.memoryCurrent, isNull);
  });

  test('local/session 모두 차단되면 memory fallback 한다', () {
    localTarget
      ..throwOnRead = true
      ..throwOnWrite = true
      ..throwOnRemove = true;
    sessionTarget
      ..throwOnRead = true
      ..throwOnWrite = true
      ..throwOnRemove = true;

    engine.write('en');
    expect(engine.read(), 'en');

    final state = engine.debugStateForTests();
    expect(state.localCurrent, isNull);
    expect(state.sessionCurrent, isNull);
    expect(state.memoryCurrent, 'en');
  });

  test('sessionOnly 모드에서는 session + memory만 사용한다', () {
    engine.setTestMode(LocaleStorageTestMode.sessionOnly);
    engine.write('ko');

    final state = engine.debugStateForTests();
    expect(state.localCurrent, isNull);
    expect(state.sessionCurrent, 'ko');
    expect(state.memoryCurrent, isNull);
  });

  test('memoryOnly 모드에서는 memory만 사용한다', () {
    engine.setTestMode(LocaleStorageTestMode.memoryOnly);
    engine.write('en');

    final state = engine.debugStateForTests();
    expect(state.localCurrent, isNull);
    expect(state.sessionCurrent, isNull);
    expect(state.memoryCurrent, 'en');
  });
}
