import 'package:flutter_test/flutter_test.dart';

import 'package:ar_autopilot_display/theme/theme_registry.dart';

void main() {
  group('ThemeRegistry — factory themes', () {
    test('exposes exactly 4 factory themes', () {
      expect(ThemeRegistry.all.length, 4);
    });

    test('factory theme ids are light, cyan, wine, ochre', () {
      final ids = ThemeRegistry.all.map((t) => t.id).toList();
      expect(ids, containsAll(['light', 'cyan', 'wine', 'ochre']));
    });

    test('display order is light → cyan → wine → ochre', () {
      final ids = ThemeRegistry.all.map((t) => t.id).toList();
      expect(ids, ['light', 'cyan', 'wine', 'ochre']);
    });

    test('all themes have non-empty id and displayName', () {
      for (final t in ThemeRegistry.all) {
        expect(t.id, isNotEmpty, reason: 'id must not be empty');
        expect(t.displayName, isNotEmpty, reason: 'displayName must not be empty');
      }
    });

    group('byId', () {
      test('returns correct theme for each known id', () {
        for (final t in ThemeRegistry.all) {
          final found = ThemeRegistry.byId(t.id);
          expect(found.id, t.id, reason: 'byId("${t.id}") should return that theme');
        }
      });

      test('falls back to default (cyan) for unknown id', () {
        expect(ThemeRegistry.byId('does_not_exist').id, ThemeRegistry.defaultId);
        expect(ThemeRegistry.byId('').id, ThemeRegistry.defaultId);
      });
    });

    test('default id is cyan', () {
      expect(ThemeRegistry.defaultId, 'cyan');
    });

    test('contains() returns true for factory ids', () {
      for (final t in ThemeRegistry.all) {
        expect(ThemeRegistry.contains(t.id), isTrue);
      }
    });

    test('contains() returns false for unknown id', () {
      expect(ThemeRegistry.contains('unknown_xyz'), isFalse);
    });

    group('Token completeness — no null colours', () {
      for (final t in ThemeRegistry.all) {
        test('${t.id}: all Color tokens are non-null', () {
          // Backgrounds
          expect(t.background, isNotNull, reason: '${t.id}.background');
          expect(t.backgroundMid, isNotNull, reason: '${t.id}.backgroundMid');
          expect(t.backgroundDeep, isNotNull, reason: '${t.id}.backgroundDeep');
          expect(t.backgroundDeepest, isNotNull, reason: '${t.id}.backgroundDeepest');
          expect(t.panelBackground, isNotNull, reason: '${t.id}.panelBackground');
          expect(t.panelBorder, isNotNull, reason: '${t.id}.panelBorder');
          // Text
          expect(t.textMain, isNotNull, reason: '${t.id}.textMain');
          expect(t.textMuted, isNotNull, reason: '${t.id}.textMuted');
          expect(t.textSoft, isNotNull, reason: '${t.id}.textSoft');
          expect(t.textDisabled, isNotNull, reason: '${t.id}.textDisabled');
          // Accent
          expect(t.accentLight, isNotNull, reason: '${t.id}.accentLight');
          expect(t.accentMid, isNotNull, reason: '${t.id}.accentMid');
          expect(t.accentDark, isNotNull, reason: '${t.id}.accentDark');
          expect(t.accentGlowColor, isNotNull, reason: '${t.id}.accentGlowColor');
          // Set-point
          expect(t.setLight, isNotNull, reason: '${t.id}.setLight');
          expect(t.setDark, isNotNull, reason: '${t.id}.setDark');
          expect(t.setGlow, isNotNull, reason: '${t.id}.setGlow');
          // Semantic
          expect(t.okColor, isNotNull, reason: '${t.id}.okColor');
          expect(t.warnColor, isNotNull, reason: '${t.id}.warnColor');
          expect(t.northColor, isNotNull, reason: '${t.id}.northColor');
          // Disengage
          expect(t.disengageBackground, isNotNull, reason: '${t.id}.disengageBackground');
          expect(t.disengageText, isNotNull, reason: '${t.id}.disengageText');
          expect(t.disengageBorder, isNotNull, reason: '${t.id}.disengageBorder');
          expect(t.disengageGlow, isNotNull, reason: '${t.id}.disengageGlow');
          // Action buttons
          expect(t.actionButtonBackground, isNotNull, reason: '${t.id}.actionButtonBackground');
          expect(t.actionButtonBorder, isNotNull, reason: '${t.id}.actionButtonBorder');
          expect(t.actionButtonText, isNotNull, reason: '${t.id}.actionButtonText');
          expect(t.actionButtonGlow, isNotNull, reason: '${t.id}.actionButtonGlow');
        });
      }
    });

    group('Glow rules', () {
      test('light theme has accentGlowRadius == 0 (no glow in daytime)', () {
        expect(ThemeRegistry.byId('light').accentGlowRadius, 0.0);
      });

      test('dark themes have accentGlowRadius > 0', () {
        for (final id in ['cyan', 'wine', 'ochre']) {
          expect(
            ThemeRegistry.byId(id).accentGlowRadius,
            greaterThan(0),
            reason: '$id should have glow',
          );
        }
      });
    });

    group('Background gradient rules', () {
      test('light theme has no backgroundGradient (solid colour)', () {
        expect(ThemeRegistry.byId('light').backgroundGradient, isNull);
      });

      test('dark themes have a backgroundGradient', () {
        for (final id in ['cyan', 'wine', 'ochre']) {
          expect(
            ThemeRegistry.byId(id).backgroundGradient,
            isNotNull,
            reason: '$id should have a radial background gradient',
          );
        }
      });
    });
  });
}
