#include "video_recorder.h"
#include "capturer/video/VideoCaptureManager.h"

#include <Windows.h>
#include <capturer/finder.h>
#include <vector>
#include <algorithm>
#include <mutex>
#include <string>
using namespace avrecorder::video;

bool VideoRecorder::Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method)
{
    CaptureTarget target;
    target.type = CaptureTargetType::Window;
    target.hwnd = srcHwnd;
    RECT clientRect;
    if (!GetClientRect(srcHwnd, &clientRect))
        return false;
    int width = clientRect.right - clientRect.left;
    int height = clientRect.bottom - clientRect.top;
    _capturer.open(target, method, width, height);
    return _Open(param);
}

bool VideoRecorder::Open(int monitorIdx,
                         Encoder<MediaType::VIDEO>::Param& param,
                         CaptureMethod method)
{
    CaptureTarget target;
    target.type = CaptureTargetType::Monitor;
    target.monitorIdx = monitorIdx;
    auto monitorInfo = MonitorFinder::GetList()[monitorIdx];
    RECT rect = monitorInfo.rect;
    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;
    _capturer.open(target, method, width, height);
    return _Open(param);
}

bool VideoRecorder::_Open(Encoder<MediaType::VIDEO>::Param& param)
{
    // 缓存 _capturer.getFrame() 的结果，避免重复调用
    auto currentFrame = _capturer.getFrame();
    int frameWidth = currentFrame ? currentFrame->width : param.width;
    int frameHeight = currentFrame ? currentFrame->height : param.height;
    
    _encodeFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12, frameWidth, frameHeight);
    if (!_encodeFrame) { return false; }
    {
        std::lock_guard<std::mutex> renderLk(_renderMtx);
        _renderFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12, frameWidth, frameHeight);
        if (!_renderFrame) { return false; }
    }
    // 捕获定时器和帧获取逻辑
    _captureTimer.Start(param.fps, [this] {
        auto srcFrame = _capturer.getFrame();
        if (srcFrame != nullptr) {
            std::lock_guard<std::mutex> muxLk(__mtx);
            if (srcFrame->format != _encodeFrame->format) {
                std::lock_guard<std::mutex> renderLk(_renderMtx);
                Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); });
                _encodeFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(srcFrame->format),
                                                                  srcFrame->width,
                                                                  srcFrame->height);
                if (!_encodeFrame) { return; }
            }
            av_frame_copy(_encodeFrame, srcFrame);
        }
    });
    param.width = frameWidth;
    param.height = frameHeight;
    _param = param;
    return true;
}

AVFrame* VideoRecorder::GetRenderFrame()
{
    std::lock_guard<std::mutex> renderLk(_renderMtx);
    if (_encodeFrame == nullptr) {
        return nullptr;
    }
    if (_renderFrame->format != _encodeFrame->format) {
        Free(_renderFrame, [this] { av_frame_free(&_renderFrame); });
        _renderFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(_encodeFrame->format),
                                                      _encodeFrame->width,
                                                      _encodeFrame->height);
    }
    av_frame_copy(_renderFrame, _encodeFrame);
    return _renderFrame;
}

bool VideoRecorder::LoadMuxer(AvMuxer& muxer)
{
    std::lock_guard<std::mutex> lock(_muxersMtx);
    
    // 检查是否已经加载过这个muxer
    for (const auto& info : _muxers) {
        if (info.muxer == &muxer) {
            return true; // 已经加载过，直接返回成功
        }
    }
    
    int streamIndex = muxer.AddVideoStream(_param);
    if (streamIndex == -1) { return false; }
    
    _muxers.emplace_back(&muxer, streamIndex);
    return true;
}

bool VideoRecorder::UnloadMuxer(AvMuxer& muxer)
{
    std::lock_guard<std::mutex> lock(_muxersMtx);
    
    auto it = std::find_if(_muxers.begin(), _muxers.end(),
                          [&muxer](const MuxerInfo& info) {
                              return info.muxer == &muxer;
                          });
    
    if (it != _muxers.end()) {
        _muxers.erase(it);
        return true;
    }
    
    return false; // 没有找到对应的muxer
}

bool VideoRecorder::StartRecord()
{
    std::lock_guard<std::mutex> lock(_muxersMtx);
    
    if (_muxers.empty()) {
        return false; // 没有加载任何muxer
    }
    
    _totalPts = 0;
    _lossPts = 0;
    {
        std::lock_guard<std::mutex> lock(_lossMtx);
        _lossHistory.clear();
    }
    _muxTimer.Start(_param.fps, [this] {
        ++_totalPts;
        bool anySuccess = false;
        
        // 向所有muxer写入数据
        {
            std::lock_guard<std::mutex> muxerLock(_muxersMtx);
            for (const auto& info : _muxers) {
                if (info.muxer->Write(_encodeFrame, info.streamIndex)) {
                    anySuccess = true;
                }
            }
        }
        
        bool loss = !anySuccess;
        if (loss)
            ++_lossPts;

        {
            std::lock_guard<std::mutex> lock(_lossMtx);
            _lossHistory.push_back(loss);
            if (_lossHistory.size() > LOSS_WINDOW)
                _lossHistory.pop_front();
        }
       
    });
    _isRecord = true;
    return true;
}
void VideoRecorder::StopRecord()
{
    _isRecord = false;
    _muxTimer.Stop();
}

double VideoRecorder::GetLossRate()
{
    std::lock_guard<std::mutex> lock(_lossMtx);
    if (_lossHistory.size() < LOSS_WINDOW)
        return -1.0; // 统计中
    int lossCount = std::count(_lossHistory.begin(), _lossHistory.end(), true);
    if (_lossHistory.empty()) {
        return 0.0;
    }
    return double(lossCount) / _lossHistory.size();
}

void VideoRecorder::Close()
{
    StopRecord();
    _captureTimer.Stop();
    _capturer.close();
    Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); });
    Free(_renderFrame, [this] { av_frame_free(&_renderFrame); });
}

void VideoRecorder::SetCaptureSource(HWND srcHwnd, CaptureMethod method)
{
    // 只切换采集源，不重启编码器和推流
    CaptureTarget target;
    target.type = CaptureTargetType::Window;
    target.hwnd = srcHwnd;
    RECT clientRect;
    if (!GetClientRect(srcHwnd, &clientRect))
        return;
    int width = clientRect.right - clientRect.left;
    int height = clientRect.bottom - clientRect.top;
    _capturer.open(target, method, width, height);
}

void VideoRecorder::SetCaptureSource(int monitorIdx, CaptureMethod method)
{
    // 只切换采集源，不重启编码器和推流
    CaptureTarget target;
    target.type = CaptureTargetType::Monitor;
    target.monitorIdx = monitorIdx;
    auto monitorInfo = MonitorFinder::GetList()[monitorIdx];
    RECT rect = monitorInfo.rect;
    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;
    _capturer.open(target, method, width, height);
}

std::string VideoRecorder::GetEncoderNameForMuxer(AvMuxer& muxer)
{
    std::lock_guard<std::mutex> lock(_muxersMtx);
    auto it = std::find_if(_muxers.begin(), _muxers.end(), [&muxer](const MuxerInfo& info) {
        return info.muxer == &muxer;
    });
    if (it == _muxers.end()) {
        return std::string();
    }
    AVCodecContext* ctx = muxer.GetCodecCtx(it->streamIndex);
    if (ctx && ctx->codec && ctx->codec->name) {
        return std::string(ctx->codec->name);
    }
    return std::string();
}
