#include "logger.h"
#include <iostream>
#include <iomanip>

// Qt头文件只在需要时包含
#ifdef QT_CORE_LIB
#include <QString>
#include <QDebug>
#include <QLoggingCategory>
#endif

namespace av {

// ConsoleOutput实现
void ConsoleOutput::write(LogLevel level, const std::string& message) {
    std::ostream& stream = (level >= LogLevel::WARNING) ? std::cerr : std::cout;
    stream << message << std::endl;
    stream.flush();
}

// FileOutput实现
FileOutput::FileOutput(const std::string& filename) {
    m_file.open(filename, std::ios::app);
    if (!m_file.is_open()) {
        std::cerr << "Failed to open log file: " << filename << std::endl;
    }
}

FileOutput::~FileOutput() {
    if (m_file.is_open()) {
        m_file.close();
    }
}

void FileOutput::write(LogLevel level, const std::string& message) {
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_file.is_open()) {
        m_file << message << std::endl;
        m_file.flush();
    }
}

// QtOutput实现
void QtOutput::write(LogLevel level, const std::string& message) {
#ifdef QT_CORE_LIB
    QString qmsg = QString::fromUtf8(message.c_str());
    switch (level) {
    case LogLevel::DEBUG:
        qDebug() << qmsg;
        break;
    case LogLevel::INFO:
        qInfo() << qmsg;
        break;
    case LogLevel::WARNING:
        qWarning() << qmsg;
        break;
    case LogLevel::ERROR:
        qCritical() << qmsg;
        break;
    }
#else
    // 如果没有Qt，回退到控制台输出
    ConsoleOutput console;
    console.write(level, message);
#endif
}

// Logger实现
Logger& Logger::instance() {
    static Logger instance;
    return instance;
}

void Logger::setLevel(LogLevel level) {
    std::lock_guard<std::mutex> lock(m_mutex);
    m_level = level;
}

LogLevel Logger::getLevel() const {
    std::lock_guard<std::mutex> lock(m_mutex);
    return m_level;
}

void Logger::addOutput(std::unique_ptr<LogOutput> output) {
    std::lock_guard<std::mutex> lock(m_mutex);
    m_outputs.push_back(std::move(output));
}

void Logger::clearOutputs() {
    std::lock_guard<std::mutex> lock(m_mutex);
    m_outputs.clear();
}

void Logger::debug(const std::string& message) {
    if (shouldLog(LogLevel::DEBUG)) {
        log(LogLevel::DEBUG, message);
    }
}

void Logger::info(const std::string& message) {
    if (shouldLog(LogLevel::INFO)) {
        log(LogLevel::INFO, message);
    }
}

void Logger::warning(const std::string& message) {
    if (shouldLog(LogLevel::WARNING)) {
        log(LogLevel::WARNING, message);
    }
}

void Logger::error(const std::string& message) {
    if (shouldLog(LogLevel::ERROR)) {
        log(LogLevel::ERROR, message);
    }
}

#ifdef QT_CORE_LIB
void Logger::qtDebug(const QString& message) {
    debug(message.toUtf8().toStdString());
}

void Logger::qtInfo(const QString& message) {
    info(message.toUtf8().toStdString());
}

void Logger::qtWarning(const QString& message) {
    warning(message.toUtf8().toStdString());
}

void Logger::qtError(const QString& message) {
    error(message.toUtf8().toStdString());
}
#endif

void Logger::initialize(const std::string& logFile, 
                       LogLevel level,
                       bool enableConsole,
                       bool enableQt) {
    Logger& logger = instance();
    logger.clearOutputs();
    logger.setLevel(level);
    
    // 添加文件输出
    if (!logFile.empty()) {
        logger.addOutput(std::make_unique<FileOutput>(logFile));
    }
    
    // 添加控制台输出
    if (enableConsole) {
        logger.addOutput(std::make_unique<ConsoleOutput>());
    }
    
    // 添加Qt输出
    if (enableQt) {
        logger.addOutput(std::make_unique<QtOutput>());
    }
    
    logger.info("AV Logger initialized");
}

void Logger::log(LogLevel level, const std::string& message) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    std::string formattedMessage = getCurrentTime() + " [" + levelToString(level) + "] " + message;
    
    for (auto& output : m_outputs) {
        if (output) {
            output->write(level, formattedMessage);
        }
    }
}

bool Logger::shouldLog(LogLevel level) const {
    return level >= m_level;
}

std::string Logger::getCurrentTime() const {
    auto now = std::chrono::system_clock::now();
    auto time_t = std::chrono::system_clock::to_time_t(now);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        now.time_since_epoch()) % 1000;
    
    std::ostringstream oss;
    oss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
    oss << '.' << std::setfill('0') << std::setw(3) << ms.count();
    return oss.str();
}

std::string Logger::levelToString(LogLevel level) const {
    switch (level) {
    case LogLevel::DEBUG:   return "DEBUG";
    case LogLevel::INFO:    return "INFO";
    case LogLevel::WARNING: return "WARN";
    case LogLevel::ERROR:   return "ERROR";
    default:                return "UNKNOWN";
    }
}

} // namespace av