#import "XSLog.h"

static NSString *kLogFilePath = @"app.log";
static unsigned long long kMaxFileSize = 10 * 1024 * 1024; // 10 MB
static NSFileHandle *logFileHandle;
static dispatch_queue_t logQueue;
static int logCount = 0;                   // 用于控制滚动检查频率
static const int kLogCheckFrequency = 100; // 每100条日志检查一次文件大小

// 内部函数声明
static void setupLogFileHandle(NSString *logFilePath);
static void checkAndRollLogFile(NSString *logFilePath);
static NSString *getLogFilePath(NSString *logFileName);



void XSLogSetupLogWithFilePath(NSString *logFilePath,
                           unsigned long long maxFileSize) {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    kLogFilePath = logFilePath;
    kMaxFileSize = maxFileSize;
    logQueue = dispatch_queue_create("com.yourcompany.app.logQueue",
                                     DISPATCH_QUEUE_SERIAL);

    // 初始化文件句柄
    setupLogFileHandle(logFilePath);
  });
}

void XSLogSetupLogWithFileName(NSString *logFileName,
                               unsigned long long maxFileSize) {
  kLogFilePath = getLogFilePath(logFileName);
  XSLogSetupLogWithFilePath(kLogFilePath,maxFileSize);
}

static NSString *getLogFilePath(NSString *logFileName) {
  // 获取Documents目录路径
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                       NSUserDomainMask, YES);
  NSString *documentsDirectory = [paths firstObject];
  NSString *logFilePath =
      [documentsDirectory stringByAppendingPathComponent:logFileName];
  return logFilePath;
}

static void setupLogFileHandle(NSString *logFilePath) {
  // 检查文件大小，如果超过最大值则进行滚动
  checkAndRollLogFile(logFilePath);

  // 关闭旧的句柄（如果存在）
  if (logFileHandle) {
    [logFileHandle closeFile];
    logFileHandle = nil;
  }

  // 打开文件句柄
  logFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
  if (!logFileHandle) {
    // 如果文件不存在，则创建
    [[NSFileManager defaultManager] createFileAtPath:logFilePath
                                            contents:nil
                                          attributes:nil];
    logFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
  }

  if (logFileHandle) {
    // 将文件句柄移动到文件末尾
    [logFileHandle seekToEndOfFile];
  } else {
    fprintf(stderr, "Error: Could not open log file for writing.\n");
  }
}


static void checkAndRollLogFile(NSString *logFilePath) {
  NSFileManager *fileManager = [NSFileManager defaultManager];
  if ([fileManager fileExistsAtPath:logFilePath]) {
    NSError *error = nil;
    NSDictionary *fileAttributes =
        [fileManager attributesOfItemAtPath:logFilePath error:&error];
    if (fileAttributes) {
      unsigned long long fileSize = [fileAttributes fileSize];
      if (fileSize > kMaxFileSize) {
        // 文件过大，进行滚动
        NSString *backupFilePath =
            [logFilePath stringByAppendingString:@".bak"];
        [fileManager removeItemAtPath:backupFilePath
                                error:nil]; // 移除旧的备份文件
        [fileManager moveItemAtPath:logFilePath
                             toPath:backupFilePath
                              error:&error]; // 将当前文件备份
        if (error) {
          fprintf(stderr, "Error rolling log file: %s\n",
                  error.localizedDescription.UTF8String);
        }
        // 创建新的空日志文件
        [fileManager createFileAtPath:logFilePath contents:nil attributes:nil];
        // 重新设置文件句柄
        setupLogFileHandle(kLogFilePath);
      }
    } else {
      fprintf(stderr, "Error getting file attributes: %s\n",
              error.localizedDescription.UTF8String);
    }
  }
}

void XSLogRedirectNSLog(void) {
    if (logFileHandle) {
        int fd = [logFileHandle fileDescriptor];
        if (fd != -1) {
            // 将标准错误输出重定向到日志文件
            if (dup2(fd, STDERR_FILENO) == -1) {
                fprintf(stderr, "Error redirecting stderr to log file.\n");
            }
        } else {
            fprintf(stderr, "Error: logFileHandle has an invalid file descriptor.\n");
        }
    } else {
        fprintf(stderr, "Error: logFileHandle is not initialized. Cannot redirect stderr.\n");
    }
}

void XSLogMessage(NSString *format, ...) {
  va_list args;
  va_start(args, format);
  NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
  va_end(args);

  dispatch_async(logQueue, ^{
    // 获取当前时间
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
    NSString *timestamp = [dateFormatter stringFromDate:[NSDate date]];

    // 格式化日志消息
    NSString *logString =
        [NSString stringWithFormat:@"%@ %@\n", timestamp, message];

    // 将日志写入文件
    NSData *data = [logString dataUsingEncoding:NSUTF8StringEncoding];
    if (logFileHandle) {
      @try {
        [logFileHandle writeData:data];
        // 每次写入后，递增计数器
        logCount++;
        // 每隔 kLogCheckFrequency 条日志检查一次文件大小
        if (logCount >= kLogCheckFrequency) {
          logCount = 0; // 重置计数器
          checkAndRollLogFile(kLogFilePath);
        }
      } @catch (NSException *exception) {
        fprintf(stderr, "Error writing to log file: %s\n",
                exception.reason.UTF8String);
      }
    }

    // 同时输出到控制台，以便调试
    fprintf(stderr, "%s", [logString UTF8String]);
  });
}
