import 'dart:developer' as dev;
import 'dart:io';

import 'package:backend/utils/environment.dart';
import 'package:dart_frog/dart_frog.dart';
import 'package:logging/logging.dart';

bool _listening = false;

Future<HttpServer> run(Handler handler, InternetAddress ip, int port) async {
  final isDevelopment = (await dev.Service.getInfo()).serverUri != null;
  // Logic to prevent multiple listeners with hot-reload
  // Changes to this are not hot-reloaded, you must restart the server
  if (!_listening) {
    final logLevel = Platform.environment['LOG_LEVEL'] ?? (isDevelopment ? 'FINEST' : 'INFO');
    Logger.root.level =
        Level.LEVELS.firstWhere((l) => l.name == logLevel, orElse: () => Level.INFO); // defaults to Level.INFO
    Logger.root.onRecord.listen((record) {
      writeLogRecord(record, record.level.value >= Level.SEVERE.value ? stderr : stdout);
    });
    _listening = true;
  }

  checkEnvironment(isDevelopment);

  for (final lvl in Level.LEVELS) {
    writeLogRecord(LogRecord(lvl, 'Test message', 'main'), stdout);
  }

  return serve(handler, ip, port);
}

const Map<String, String> _levelColors = {
  'FINEST': '\x1B[1;37m', // White
  'FINER': '\x1B[1;38m', // Gray
  'FINE': '\x1B[1;35m', // Purple
  'CONFIG': '\x1B[1;36m', // Cyan
  'INFO': '\x1B[1;32m', // Green
  'WARNING': '\x1B[1;33m', // Yellow
  'SEVERE': '\x1B[1;31m', // Red
  'SHOUT': '\x1B[1;38;5;52m\x1B[1;48;5;213m', // Red on pink
};

const String _resetColor = '\x1B[0m';

String _getColoredLevel(String levelName) {
  return '${_levelColors[levelName] ?? ''}$levelName$_resetColor';
}

void writeLogRecord(LogRecord record, IOSink iosink) {
  // Write the basic log message with colored level
  iosink.writeln(
    '[${_getColoredLevel(record.level.name)}]:[${record.loggerName}] '
    '${record.time}: ${record.message}',
  );

  // Additional details for severe logs
  if (record.level.value >= Level.SEVERE.value) {
    iosink.writeln(
      '[${_getColoredLevel(record.level.name)}]:[${record.loggerName}] '
      '${record.error?.toString() ?? "No error provided"}\n'
      '${record.stackTrace?.toString() ?? "No trace provided"}',
    );
  }
}