import 'dart:io';
import 'package:logger/logger.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';

/// Global logger instance
late final Logger appLogger;
late final FileLogOutput fileLogOutput;

/// Initialize logging
Future<void> initLogging() async {
  fileLogOutput = FileLogOutput();

  appLogger = Logger(
    printer: PrettyPrinter(
      methodCount: 0,
      printTime: true,
      colors: true,
      printEmojis: true,
    ),
    output: MultiOutput([
      ConsoleOutput(),
      fileLogOutput,
    ]),
    level: Level.debug,
  );
}

/// Safe logger wrapper
void logSafe(
  String message, {
  LogLevel level = LogLevel.info,
  dynamic error,
  StackTrace? stackTrace,
  bool sensitive = false,
}) {
  if (sensitive) return;

  switch (level) {
    case LogLevel.debug:
      appLogger.d(message, error: error, stackTrace: stackTrace);
      break;
    case LogLevel.warning:
      appLogger.w(message, error: error, stackTrace: stackTrace);
      break;
    case LogLevel.error:
      appLogger.e(message, error: error, stackTrace: stackTrace);
      break;
    case LogLevel.verbose:
      appLogger.v(message, error: error, stackTrace: stackTrace);
      break;
    default:
      appLogger.i(message, error: error, stackTrace: stackTrace);
  }
}

/// Log output to file (safe path, no permission required)
class FileLogOutput extends LogOutput {
  File? _logFile;

  Future<void> _init() async {
    if (_logFile != null) return;

    final baseDir = await getExternalStorageDirectory();
    final directory = Directory('${baseDir!.path}/marco_logs');
    if (!await directory.exists()) {
      await directory.create(recursive: true);
    }

    final date = DateFormat('yyyy-MM-dd').format(DateTime.now());
    final filePath = '${directory.path}/log_$date.txt';
    _logFile = File(filePath);

    if (!await _logFile!.exists()) {
      await _logFile!.create();
    }

    await _cleanOldLogs(directory);
  }

  @override
  void output(OutputEvent event) async {
    await _init();

    if (event.lines.isEmpty) return;

    final logMessage = event.lines.join('\n') + '\n';
    await _logFile!.writeAsString(
      logMessage,
      mode: FileMode.append,
      flush: true,
    );
  }

  Future<String> getLogFilePath() async {
    await _init();
    return _logFile!.path;
  }

  Future<void> clearLogs() async {
    await _init();
    await _logFile!.writeAsString('');
  }

  Future<String> readLogs() async {
    await _init();
    return _logFile!.readAsString();
  }

  Future<void> _cleanOldLogs(Directory directory) async {
    final files = directory.listSync();
    final now = DateTime.now();

    for (var file in files) {
      if (file is File && file.path.endsWith('.txt')) {
        final stat = await file.stat();
        if (now.difference(stat.modified).inDays > 3) {
          await file.delete();
        }
      }
    }
  }
}

/// Simple log printer for file output
class SimpleFileLogPrinter extends LogPrinter {
  @override
  List<String> log(LogEvent event) {
    final message = event.message.toString();

    if (message.contains('[SENSITIVE]')) return [];

    final timestamp = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
    final level = event.level.name.toUpperCase();
    final error = event.error != null ? ' | ERROR: ${event.error}' : '';
    final stack =
        event.stackTrace != null ? '\nSTACKTRACE:\n${event.stackTrace}' : '';
    return ['[$timestamp] [$level] $message$error$stack'];
  }
}

/// Optional enum for log levels
enum LogLevel { debug, info, warning, error, verbose }
