#include "audio_output.h"
#include <QAudioDeviceInfo>
#include <QDebug>
#include "../base/logger.h"
#include "../utils/utils_synchronizer_v2.h"
#include "AV/code/base/media_common.h"
#include <algorithm>
#include <chrono>
#include <cstring>
#include <thread>

extern "C" {
#include <libavutil/channel_layout.h>
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
}

namespace av {
namespace player {

AudioOutput::AudioOutput(QObject* parent)
    : QObject(parent)
    , m_audioOutput(nullptr)
    , m_audioDevice(nullptr)
    , m_sampleRate(44100)
    , m_channels(2)
    , m_inputFormat(AV_SAMPLE_FMT_S16)
    , m_swrContext(nullptr)
    , m_needResampling(false)
    , m_volume(1.0)
    , m_playbackSpeed(1.0)
    , m_lastAudioPts(0.0)
    , m_initialized(false)
    , m_playing(false)
{
}

AudioOutput::~AudioOutput()
{
    stop();
    cleanupResampler();
    
    if (m_audioOutput) {
        delete m_audioOutput;
        m_audioOutput = nullptr;
    }
}

bool AudioOutput::initialize(int sampleRate, int channels, AVSampleFormat sampleFormat)
{
    QMutexLocker locker(&m_mutex);
    
    if (m_initialized) {
        av::Logger::instance().warning("Audio output already initialized");
        return true;
    }
    
    m_sampleRate = sampleRate;
    m_channels = channels;
    m_inputFormat = sampleFormat;
    
    // 设置Qt音频格式
    m_audioFormat.setSampleRate(sampleRate);
    m_audioFormat.setChannelCount(channels);
    m_audioFormat.setSampleSize(16); // 输出16位
    m_audioFormat.setCodec("audio/pcm");
    m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
    m_audioFormat.setSampleType(QAudioFormat::SignedInt);
    
    // 检查设备是否支持该格式
    QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
    if (!deviceInfo.isFormatSupported(m_audioFormat)) {
        av::Logger::instance().warning("Audio format not supported, using nearest format");
        m_audioFormat = deviceInfo.nearestFormat(m_audioFormat);
        
        // 验证获取的格式是否有效
        if (m_audioFormat.sampleRate() <= 0 || m_audioFormat.channelCount() <= 0) {
            av::Logger::instance().warning("Device returned invalid audio format, using fallback");
            av::Logger::instance().warningf("Invalid format: {}Hz, {}ch", 
                                           m_audioFormat.sampleRate(), 
                                           m_audioFormat.channelCount());
            
            // 使用默认格式作为后备
            m_audioFormat.setSampleRate(44100);
            m_audioFormat.setChannelCount(2);
            m_audioFormat.setSampleSize(16);
            m_audioFormat.setCodec("audio/pcm");
            m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
            m_audioFormat.setSampleType(QAudioFormat::SignedInt);
            
            av::Logger::instance().info("Using fallback audio format: 44100Hz, 2ch, 16bit");
        }
        
        // 记录实际使用的格式
        av::Logger::instance().info("Using audio format: " + 
            std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
            std::to_string(m_audioFormat.channelCount()) + "ch, " +
            std::to_string(m_audioFormat.sampleSize()) + "bit");
    }
    
    // 创建音频输出设备
    m_audioOutput = new QAudioOutput(m_audioFormat, this);
    if (!m_audioOutput) {
        av::Logger::instance().error("Failed to create audio output device");
        return false;
    }
    
    // 设置缓冲区大小
    m_audioOutput->setBufferSize(32768); // 32KB缓冲区
    
    // 连接状态变化信号
    connect(m_audioOutput, &QAudioOutput::stateChanged,
            this, &AudioOutput::onStateChanged);
    
    // 记录音频格式信息
    av::Logger::instance().info("Audio format: " + 
        std::to_string(m_audioFormat.sampleRate()) + "Hz, " +
        std::to_string(m_audioFormat.channelCount()) + "ch, " +
        std::to_string(m_audioFormat.sampleSize()) + "bit, " +
        m_audioFormat.codec().toStdString());
    
    // 初始化重采样器（如果需要）
    if (!initResampler()) {
        av::Logger::instance().error("Failed to initialize audio resampler");
        return false;
    }
    
    m_initialized = true;
    av::Logger::instance().info("Audio output initialized successfully");
    
    return true;
}

void AudioOutput::start()
{
    QMutexLocker locker(&m_mutex);
    
    if (!m_initialized || !m_audioOutput) {
        av::Logger::instance().error("Audio output not initialized");
        return;
    }
    
    if (m_playing) {
        return;
    }
    
    av::Logger::instance().debug("Starting audio output device...");
    av::Logger::instance().debug("Audio output state before start: " + std::to_string(m_audioOutput->state()));
    
    // 检查音频格式
    QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
    av::Logger::instance().debug("Default audio device: " + deviceInfo.deviceName().toStdString());
    av::Logger::instance().debug("Audio format supported: " + std::to_string(deviceInfo.isFormatSupported(m_audioFormat)));
    
    // 确保音频输出设备处于正确状态
    if (m_audioOutput->state() == QAudio::StoppedState) {
        av::Logger::instance().debug("Resetting audio output device");
        m_audioOutput->reset();
        // 给设备一点时间重置
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
    
    // 如果设备不支持当前格式，尝试使用最接近的格式
    if (!deviceInfo.isFormatSupported(m_audioFormat)) {
        av::Logger::instance().warning("Audio format not supported, using nearest format");
        QAudioFormat nearestFormat = deviceInfo.nearestFormat(m_audioFormat);
        // m_audioOutput->setFormat(nearestFormat);
        av::Logger::instance().info("Using nearest format: " + 
            std::to_string(nearestFormat.sampleRate()) + "Hz, " +
            std::to_string(nearestFormat.channelCount()) + "ch, " +
            std::to_string(nearestFormat.sampleSize()) + "bit");
    }
    
    // 尝试多次启动音频设备
    int retryCount = 0;
    const int maxRetries = 5; // 增加重试次数
    bool deviceStarted = false;
    
    while (retryCount < maxRetries && !deviceStarted) {
        if (retryCount > 0) {
            av::Logger::instance().info("Retrying audio device start (attempt " + std::to_string(retryCount + 1) + "/" + std::to_string(maxRetries) + ")");
            
            // 重新创建音频输出设备
            if (m_audioOutput) {
                m_audioOutput->stop();
                delete m_audioOutput;
                m_audioOutput = nullptr;
            }
            
            // 等待更长时间让系统释放音频资源
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            
            m_audioOutput = new QAudioOutput(m_audioFormat, this);
            if (!m_audioOutput) {
                av::Logger::instance().error("Failed to recreate audio output device");
                return;
            }
            
            m_audioOutput->setBufferSize(32768);
            connect(m_audioOutput, &QAudioOutput::stateChanged, this, &AudioOutput::onStateChanged);
        }
        
        // 检查音频设备可用性
        QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultOutputDevice();
        if (deviceInfo.isNull()) {
            av::Logger::instance().error("No audio output device available");
            return;
        }
        
        av::Logger::instance().debug("Starting audio device (attempt " + std::to_string(retryCount + 1) + ")");
        m_audioDevice = m_audioOutput->start();
        if (!m_audioDevice) {
            av::Logger::instance().warning("Failed to start audio output device (attempt " + std::to_string(retryCount + 1) + ")");
            retryCount++;
            continue;
        }
        
        av::Logger::instance().debug("Audio device started, waiting for active state...");
        
        // 写入一些静音数据来激活设备
        QByteArray silentData(2048, 0); // 增加静音数据大小
        qint64 written = m_audioDevice->write(silentData);
        av::Logger::instance().debug("Written silent data: " + std::to_string(written) + " bytes");
        
        // 等待音频设备进入活动状态
        int maxWaitMs = 2000; // 增加等待时间到2秒
        int waitMs = 0;
        while (m_audioOutput->state() != QAudio::ActiveState && waitMs < maxWaitMs) {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            waitMs += 100;
            
            if (waitMs % 500 == 0) {
                av::Logger::instance().debug("Audio output state: " + std::to_string(m_audioOutput->state()) + 
                    " (waited " + std::to_string(waitMs) + "ms)");
                
                // 尝试再次写入数据激活设备
                if (m_audioDevice && m_audioOutput->state() == QAudio::IdleState) {
                    QByteArray moreData(1024, 0);
                    m_audioDevice->write(moreData);
                }
            }
        }
        
        if (m_audioOutput->state() == QAudio::ActiveState) {
            deviceStarted = true;
            av::Logger::instance().info("Audio device successfully entered active state");
        } else if (m_audioOutput->state() == QAudio::IdleState) {
            // IdleState也可以接受，表示设备已准备好但暂时没有数据
            deviceStarted = true;
            av::Logger::instance().info("Audio device in idle state, ready for playback");
        } else {
            av::Logger::instance().warning("Audio device failed to enter active/idle state: " + std::to_string(m_audioOutput->state()) + " (attempt " + std::to_string(retryCount + 1) + ")");
            m_audioDevice = nullptr;
            retryCount++;
        }
    }
    
    if (!deviceStarted) {
        av::Logger::instance().error("Failed to start audio device after " + std::to_string(maxRetries) + " attempts");
        m_initialized = false;
        return;
    }
    
    av::Logger::instance().debug("Audio device entered active state");
    
    m_playing = true;
    av::Logger::instance().info("Audio output started successfully");
}

void AudioOutput::stop()
{
    QMutexLocker locker(&m_mutex);
    
    if (!m_playing || !m_audioOutput) {
        return;
    }
    
    m_audioOutput->stop();
    m_audioDevice = nullptr;
    m_playing = false;
    
    av::Logger::instance().info("Audio output stopped");
}

void AudioOutput::pause()
{
    QMutexLocker locker(&m_mutex);
    
    if (!m_playing || !m_audioOutput) {
        return;
    }
    
    m_audioOutput->suspend();
    av::Logger::instance().info("Audio output paused");
}

void AudioOutput::resume()
{
    QMutexLocker locker(&m_mutex);
    
    if (!m_playing || !m_audioOutput) {
        return;
    }
    
    m_audioOutput->resume();
    av::Logger::instance().info("Audio output resumed");
}

bool AudioOutput::writeFrame(const AVFramePtr& frame)
{
    if (!frame || !m_playing || !m_audioDevice) {
        av::Logger::instance().debug("Audio write failed: frame=" + std::to_string(frame != nullptr) + 
            ", playing=" + std::to_string(m_playing) + ", device=" + std::to_string(m_audioDevice != nullptr));
        return false;
    }
    
    // 检查是否是EOF帧，EOF帧不需要处理，直接返回成功
    if (!frame->data[0] && frame->nb_samples == 0) {
        av::Logger::instance().debug("Received EOF frame in audio output, ignoring");
        return true;
    }
    
    // 检查音频设备状态 - 允许ActiveState和IdleState
    if (m_audioOutput) {
        QAudio::State currentState = m_audioOutput->state();
        if (currentState != QAudio::ActiveState && currentState != QAudio::IdleState) {
            av::Logger::instance().warning("Audio device not in playable state: " + std::to_string(currentState));
            
            // 尝试重新启动设备
            if (currentState == QAudio::StoppedState) {
                av::Logger::instance().info("Attempting to restart stopped audio device");
                m_audioDevice = m_audioOutput->start();
                if (!m_audioDevice) {
                    av::Logger::instance().error("Failed to restart audio device");
                    return false;
                }
                
                // 写入静音数据激活设备
                QByteArray silentData(1024, 0);
                m_audioDevice->write(silentData);
                
                // 短暂等待设备状态更新
                std::this_thread::sleep_for(std::chrono::milliseconds(50));
                
                currentState = m_audioOutput->state();
                if (currentState != QAudio::ActiveState && currentState != QAudio::IdleState) {
                    av::Logger::instance().error("Audio device restart failed, state: " + std::to_string(currentState));
                    return false;
                }
            } else {
                return false;
            }
        }
    }
    
    // 使用Synchronizer进行时间同步
    if (frame->pts != AV_NOPTS_VALUE /*&& m_synchronizer*/) {
        // 使用原始PTS值和时间基准
        int64_t audioPts = frame->pts;
        double timeBase = 1.0 / AV_TIME_BASE;  // 假设使用AV_TIME_BASE作为时间基准

        m_lastAudioPts = audioPts * timeBase; // 转换为秒用于记录
    }

    // 转换音频帧格式
    QByteArray audioData = convertFrame(frame);
    if (audioData.isEmpty()) {
        av::Logger::instance().warning("Audio frame conversion failed");
        return false;
    }
    
    // 应用音量控制
    applyVolume(audioData);
    
    // 写入音频设备 - 添加重试机制和异常处理
    const int maxRetries = 10;
    const int retryDelayMs = 5;
    
    for (int retry = 0; retry < maxRetries; ++retry) {
        try {
            qint64 bytesWritten = m_audioDevice->write(audioData);
            if (bytesWritten == audioData.size()) {
                av::Logger::instance().debug("Audio frame written successfully: " + 
                    std::to_string(audioData.size()) + " bytes");
                return true;
            }
            
            // 写入不完整，记录警告并重试
            av::Logger::instance().warning("Audio write incomplete (attempt " + 
                std::to_string(retry + 1) + "/" + std::to_string(maxRetries) + "): " + 
                std::to_string(bytesWritten) + "/" + std::to_string(audioData.size()));
            
            // 如果不是最后一次重试，等待一段时间再重试
            if (retry < maxRetries - 1) {
                std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
            }
            
        } catch (const std::exception& e) {
            av::Logger::instance().error("Exception during audio write (attempt " + 
                std::to_string(retry + 1) + "): " + std::string(e.what()));
            
            if (retry < maxRetries - 1) {
                std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
            }
        } catch (...) {
            av::Logger::instance().error("Unknown exception during audio write (attempt " + 
                std::to_string(retry + 1) + ")");
            
            if (retry < maxRetries - 1) {
                std::this_thread::sleep_for(std::chrono::milliseconds(retryDelayMs));
            }
        }
    }
    
    av::Logger::instance().error("Audio write failed after " + std::to_string(maxRetries) + " attempts");
    return false;
}

void AudioOutput::setVolume(double volume)
{
    m_volume = std::clamp(volume, 0.0, 1.0);
    
    if (m_audioOutput) {
        m_audioOutput->setVolume(m_volume);
    }
}

double AudioOutput::getVolume() const
{
    return m_volume;
}

void AudioOutput::setPlaybackSpeed(double speed)
{
    speed = std::max(0.1, std::min(4.0, speed));
    m_playbackSpeed = speed;

    av::Logger::instance().debug("Audio playback speed set to: " + std::to_string(speed));
}

double AudioOutput::getPlaybackSpeed() const
{
    return m_playbackSpeed;
}

void AudioOutput::flush()
{
    QMutexLocker locker(&m_mutex);
    
    if (m_audioOutput) {
        m_audioOutput->reset();
    }
}

int AudioOutput::getBufferSize() const
{
    if (m_audioOutput) {
        return m_audioOutput->bufferSize() * 1000 / 
               (m_audioFormat.sampleRate() * m_audioFormat.channelCount() * 
                m_audioFormat.sampleSize() / 8);
    }
    return 0;
}

bool AudioOutput::isPlaying() const
{
    return m_playing;
}

void AudioOutput::onStateChanged(QAudio::State state)
{
    switch (state) {
    case QAudio::ActiveState:
        av::Logger::instance().debug("Audio output state: Active");
        break;
    case QAudio::SuspendedState:
        av::Logger::instance().debug("Audio output state: Suspended");
        break;
    case QAudio::StoppedState:
        av::Logger::instance().debug("Audio output state: Stopped");
        break;
    case QAudio::IdleState:
        av::Logger::instance().debug("Audio output state: Idle");
        break;
    }
}

bool AudioOutput::initResampler()
{
    // 检查是否需要重采样
    bool needSampleRateConversion = (m_audioFormat.sampleRate() != m_sampleRate);
    bool needChannelConversion = (m_audioFormat.channelCount() != m_channels);
    bool needFormatConversion = (m_inputFormat != AV_SAMPLE_FMT_S16);
    
    m_needResampling = needSampleRateConversion || needChannelConversion || needFormatConversion;
    
    if (!m_needResampling) {
        av::Logger::instance().info("No audio resampling needed");
        return true;
    }
    
    // 参数验证
    if (m_sampleRate <= 0 || m_sampleRate > 192000) {
        av::Logger::instance().errorf("Invalid input sample rate: {}", m_sampleRate);
        return false;
    }
    
    if (m_audioFormat.sampleRate() <= 0 || m_audioFormat.sampleRate() > 192000) {
        av::Logger::instance().errorf("Invalid output sample rate: {}", m_audioFormat.sampleRate());
        return false;
    }
    
    if (m_channels <= 0 || m_channels > 32) {
        av::Logger::instance().errorf("Invalid input channels: {}", m_channels);
        return false;
    }
    
    if (m_audioFormat.channelCount() <= 0 || m_audioFormat.channelCount() > 32) {
        av::Logger::instance().errorf("Invalid output channels: {}", m_audioFormat.channelCount());
        return false;
    }
    
    // 记录参数信息用于调试
    av::Logger::instance().infof("Resampler config: {}Hz,{}ch,{} -> {}Hz,{}ch,S16",
                                m_sampleRate, m_channels, 
                                av_get_sample_fmt_name(m_inputFormat),
                                m_audioFormat.sampleRate(), m_audioFormat.channelCount());
    
    // 创建重采样上下文
    m_swrContext = swr_alloc();
    if (!m_swrContext) {
        av::Logger::instance().error("Failed to allocate resampler context");
        return false;
    }
    
    // 设置输入参数
    AVChannelLayout inputLayout;
    av_channel_layout_default(&inputLayout, m_channels);
    
    // 设置输出参数
    AVChannelLayout outputLayout;
    av_channel_layout_default(&outputLayout, m_audioFormat.channelCount());
    
    // 使用分步设置方式替代swr_alloc_set_opts2
    av_opt_set_chlayout(m_swrContext, "in_chlayout", &inputLayout, 0);
    av_opt_set_int(m_swrContext, "in_sample_rate", m_sampleRate, 0);
    av_opt_set_sample_fmt(m_swrContext, "in_sample_fmt", m_inputFormat, 0);
    
    av_opt_set_chlayout(m_swrContext, "out_chlayout", &outputLayout, 0);
    av_opt_set_int(m_swrContext, "out_sample_rate", m_audioFormat.sampleRate(), 0);
    av_opt_set_sample_fmt(m_swrContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
    
    // 初始化重采样器
    int ret = swr_init(m_swrContext);
    if (ret < 0) {
        av::Logger::instance().errorf("Failed to initialize resampler: {}", 
                                      ffmpeg_utils::errorToString(ret));
        av::Logger::instance().errorf("Input: {}Hz, {}ch, {}", 
                                      m_sampleRate, m_channels, 
                                      av_get_sample_fmt_name(m_inputFormat));
        av::Logger::instance().errorf("Output: {}Hz, {}ch, S16", 
                                      m_audioFormat.sampleRate(), 
                                      m_audioFormat.channelCount());
        swr_free(&m_swrContext);
        return false;
    }
    
    av::Logger::instance().info("Audio resampler initialized successfully");
    return true;
}

void AudioOutput::cleanupResampler()
{
    if (m_swrContext) {
        swr_free(&m_swrContext);
        m_swrContext = nullptr;
    }
}

QByteArray AudioOutput::convertFrame(const AVFramePtr& frame)
{
    if (!frame) {
        av::Logger::instance().error("convertFrame: null frame pointer");
        return QByteArray();
    }
    
    // 检查帧数据有效性
    if (!frame->data[0] || frame->nb_samples <= 0) {
        av::Logger::instance().error("convertFrame: invalid frame data, nb_samples=" + std::to_string(frame->nb_samples));
        return QByteArray();
    }
    
    av::Logger::instance().debug("convertFrame: input samples=" + std::to_string(frame->nb_samples) + 
                                ", channels=" + std::to_string(m_channels) + 
                                ", format=" + std::to_string(m_inputFormat) + 
                                ", need_resampling=" + std::to_string(m_needResampling));
    
    if (!m_needResampling) {
        // 直接复制数据
        int dataSize = frame->nb_samples * m_channels * sizeof(int16_t);
        av::Logger::instance().debug("convertFrame: direct copy, size=" + std::to_string(dataSize));
        return QByteArray(reinterpret_cast<const char*>(frame->data[0]), dataSize);
    }
    
    if (!m_swrContext) {
        av::Logger::instance().error("convertFrame: resampler not initialized");
        return QByteArray();
    }
    
    // 计算输出采样数
    int outputSamples = swr_get_out_samples(m_swrContext, frame->nb_samples);
    if (outputSamples <= 0) {
        av::Logger::instance().error("convertFrame: invalid output samples=" + std::to_string(outputSamples));
        return QByteArray();
    }
    
    // 分配输出缓冲区
    int outputChannels = m_audioFormat.channelCount();
    int outputDataSize = outputSamples * outputChannels * sizeof(int16_t);
    QByteArray outputData(outputDataSize, 0);
    
    uint8_t* outputBuffer = reinterpret_cast<uint8_t*>(outputData.data());
    
    av::Logger::instance().debug("convertFrame: resampling " + std::to_string(frame->nb_samples) + 
                                " -> " + std::to_string(outputSamples) + " samples");
    
    // 执行重采样
    int convertedSamples = swr_convert(m_swrContext,
                                      &outputBuffer, outputSamples,
                                      const_cast<const uint8_t**>(frame->data), frame->nb_samples);
    
    if (convertedSamples < 0) {
        char errorBuf[256];
        av_strerror(convertedSamples, errorBuf, sizeof(errorBuf));
        av::Logger::instance().error("convertFrame: resampling failed with error " + 
                                    std::to_string(convertedSamples) + ": " + std::string(errorBuf));
        return QByteArray();
    }
    
    // 调整输出数据大小
    int actualDataSize = convertedSamples * outputChannels * sizeof(int16_t);
    outputData.resize(actualDataSize);
    
    av::Logger::instance().debug("convertFrame: successfully converted " + std::to_string(convertedSamples) + 
                                " samples, output size=" + std::to_string(actualDataSize));
    
    return outputData;
}

void AudioOutput::applyVolume(QByteArray& data)
{
    if (std::abs(m_volume - 1.0) < 0.001) {
        return; // 音量为1.0，无需调整
    }
    
    int16_t* samples = reinterpret_cast<int16_t*>(data.data());
    int sampleCount = data.size() / sizeof(int16_t);
    
    for (int i = 0; i < sampleCount; ++i) {
        samples[i] = static_cast<int16_t>(samples[i] * m_volume);
    }
}

} // namespace player
} // namespace av

