import 'package:flutter/foundation.dart';
import 'package:json_annotation/json_annotation.dart';

part 'dev_tools_settings.g.dart';

enum MarianumConnectEndpoint { live, beta, custom }

@JsonSerializable()
class DevToolsSettings {
  bool showPerformanceOverlay;
  bool checkerboardOffscreenLayers;
  bool checkerboardRasterCacheImages;

  @JsonKey(defaultValue: MarianumConnectEndpoint.live)
  MarianumConnectEndpoint marianumConnectEndpoint;

  @JsonKey(defaultValue: '')
  String marianumConnectCustomUrl;

  /// Optional override for the backend-independent emergency-notice source.
  /// Empty falls back to [emergencyNoticeDefaultUrl].
  @JsonKey(defaultValue: '')
  String emergencyNoticeUrl;

  DevToolsSettings({
    required this.showPerformanceOverlay,
    required this.checkerboardOffscreenLayers,
    required this.checkerboardRasterCacheImages,
    this.marianumConnectEndpoint = MarianumConnectEndpoint.live,
    this.marianumConnectCustomUrl = '',
    this.emergencyNoticeUrl = '',
  });

  // Resolves the effective base URL, falling back to live when the custom URL
  // is empty or malformed. HTTP custom endpoints are allowed only outside
  // release builds so a leaked debug URL never ships a plaintext bearer token.
  String resolveMarianumConnectBaseUrl() {
    switch (marianumConnectEndpoint) {
      case MarianumConnectEndpoint.live:
        return liveUrl;
      case MarianumConnectEndpoint.beta:
        return betaUrl;
      case MarianumConnectEndpoint.custom:
        final sanitized = sanitizeCustomUrl(marianumConnectCustomUrl);
        return sanitized ?? liveUrl;
    }
  }

  static const String liveUrl = 'https://connect.marianum-fulda.de';
  static const String betaUrl = 'https://connect-beta.marianum-fulda.de';

  /// Compiled-in source for the backend-independent emergency notice. Must live
  /// on infrastructure that is reachable even when MarianumConnect is down.
  static const String emergencyNoticeDefaultUrl = 'https://www.marianum-fulda.de/~aushang/marMobile.override';

  String? resolveEmergencyNoticeUrl() =>
      sanitizeCustomUrl(emergencyNoticeUrl) ??
      sanitizeCustomUrl(emergencyNoticeDefaultUrl);

  /// `true` in builds where plaintext HTTP custom endpoints are still allowed
  /// (debug, profile). Release builds keep this `false` and the picker
  /// rejects `http://` entirely.
  static bool get allowsHttpCustomEndpoint => !kReleaseMode;

  /// Returns the trimmed URL without a trailing slash, or null when the input
  /// is not a usable HTTP/HTTPS URL. HTTP is only accepted when
  /// [allowsHttpCustomEndpoint] is `true` — i.e. outside release builds.
  static String? sanitizeCustomUrl(String raw) {
    final trimmed = raw.trim();
    if (trimmed.isEmpty) return null;
    final uri = Uri.tryParse(trimmed);
    if (uri == null || !uri.hasScheme) return null;
    if (uri.scheme == 'https') {
      // always fine
    } else if (uri.scheme == 'http' && allowsHttpCustomEndpoint) {
      // dev only
    } else {
      return null;
    }
    if (uri.host.isEmpty) return null;
    return trimmed.endsWith('/')
        ? trimmed.substring(0, trimmed.length - 1)
        : trimmed;
  }

  /// `true` when the configured custom URL is plain HTTP — the picker shows
  /// this as a warning so developers don't accidentally ship a debug URL.
  bool get marianumConnectCustomUrlIsInsecure {
    final sanitized = sanitizeCustomUrl(marianumConnectCustomUrl);
    return sanitized != null && Uri.parse(sanitized).scheme == 'http';
  }

  factory DevToolsSettings.fromJson(Map<String, dynamic> json) =>
      _$DevToolsSettingsFromJson(json);
  Map<String, dynamic> toJson() => _$DevToolsSettingsToJson(this);
}
