#include "concurrent_calculator.h"
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cmath>

namespace jtjai_media {

std::vector<StreamScheduleInfo> ConcurrentCalculator::calculate_schedule(
    const std::vector<StreamConfig>& streams,
    int total_duration,
    int max_concurrent
) {
    if (streams.empty() || total_duration <= 0 || max_concurrent <= 0) {
        return {};
    }
    
    // 使用贪心算法进行初始调度
    auto schedule = greedy_schedule(streams, total_duration, max_concurrent);
    
    // 优化调度方案
    schedule = optimize_schedule(std::move(schedule), total_duration, max_concurrent);
    
    return schedule;
}

std::vector<StreamScheduleInfo> ConcurrentCalculator::greedy_schedule(
    const std::vector<StreamConfig>& streams,
    int total_duration,
    int max_concurrent
) {
    std::vector<StreamScheduleInfo> schedule;
    
    // 创建带优先级的流信息列表
    std::vector<std::pair<int, double>> stream_priorities;
    for (size_t i = 0; i < streams.size(); ++i) {
        double priority = calculate_priority_score(streams[i]);
        stream_priorities.emplace_back(i, priority);
    }
    
    // 按优先级排序（优先级高的先调度）
    std::sort(stream_priorities.begin(), stream_priorities.end(),
        [](const auto& a, const auto& b) {
            return a.second > b.second;
        });
    
    // 贪心调度每个流
    for (const auto& [stream_idx, priority] : stream_priorities) {
        const auto& stream = streams[stream_idx];
        
        // 寻找最早可用的时间段
        int start_time = find_earliest_slot(schedule, stream.duration_seconds, max_concurrent, total_duration);
        
        if (start_time >= 0 && start_time + stream.duration_seconds <= total_duration) {
            schedule.emplace_back(stream_idx, start_time, stream.duration_seconds, priority);
        } else {
            std::cout << "警告: 无法为流 " << stream_idx << " (" << stream.rtsp_url 
                      << ") 找到合适的时间段" << std::endl;
        }
    }
    
    // 按开始时间排序
    std::sort(schedule.begin(), schedule.end(),
        [](const auto& a, const auto& b) {
            return a.start_time < b.start_time;
        });
    
    return schedule;
}

double ConcurrentCalculator::calculate_priority_score(const StreamConfig& stream) const {
    // 基于权重和时长的优先级计算
    // 权重越高、时长越短的流优先级越高
    return stream.weight / std::max(1.0, static_cast<double>(stream.duration_seconds) / 60.0);
}

int ConcurrentCalculator::find_earliest_slot(
    const std::vector<StreamScheduleInfo>& current_schedule,
    int duration,
    int max_concurrent,
    int total_duration
) const {
    // 从时间0开始，逐秒检查是否可以调度
    for (int start_time = 0; start_time <= total_duration - duration; ++start_time) {
        if (can_schedule_at_time(current_schedule, start_time, duration, max_concurrent)) {
            return start_time;
        }
    }
    return -1; // 无法找到合适的时间段
}

bool ConcurrentCalculator::can_schedule_at_time(
    const std::vector<StreamScheduleInfo>& current_schedule,
    int start_time,
    int duration,
    int max_concurrent
) const {
    int end_time = start_time + duration;
    
    // 检查在整个时间段内并发数是否超出限制
    for (int t = start_time; t < end_time; ++t) {
        int concurrent_count = get_concurrent_count_at_time(current_schedule, t);
        if (concurrent_count >= max_concurrent) {
            return false;
        }
    }
    
    return true;
}

int ConcurrentCalculator::get_concurrent_count_at_time(
    const std::vector<StreamScheduleInfo>& schedule,
    int time_point
) const {
    int count = 0;
    for (const auto& info : schedule) {
        if (time_point >= info.start_time && time_point < info.end_time) {
            count++;
        }
    }
    return count;
}

bool ConcurrentCalculator::validate_schedule(
    const std::vector<StreamScheduleInfo>& schedule,
    int total_duration,
    int max_concurrent
) const {
    // 检查时间范围
    for (const auto& info : schedule) {
        if (info.start_time < 0 || info.end_time > total_duration) {
            return false;
        }
        if (info.duration <= 0) {
            return false;
        }
    }
    
    // 检查并发约束
    for (int t = 0; t < total_duration; ++t) {
        if (get_concurrent_count_at_time(schedule, t) > max_concurrent) {
            return false;
        }
    }
    
    return true;
}

ConcurrentCalculator::ScheduleStats ConcurrentCalculator::get_schedule_stats(
    const std::vector<StreamScheduleInfo>& schedule,
    int total_duration
) const {
    ScheduleStats stats;
    stats.total_streams = schedule.size();
    stats.max_concurrent_used = 0;
    stats.total_scheduled_duration = 0;
    
    int total_concurrent_sum = 0;
    
    for (int t = 0; t < total_duration; ++t) {
        int concurrent_count = get_concurrent_count_at_time(schedule, t);
        stats.max_concurrent_used = std::max(stats.max_concurrent_used, concurrent_count);
        total_concurrent_sum += concurrent_count;
    }
    
    for (const auto& info : schedule) {
        stats.total_scheduled_duration += info.duration;
    }
    
    stats.average_concurrent = total_duration > 0 ? 
        static_cast<double>(total_concurrent_sum) / total_duration : 0.0;
    
    stats.utilization_rate = total_duration > 0 ? 
        static_cast<double>(total_concurrent_sum) / (total_duration * stats.max_concurrent_used) : 0.0;
    
    return stats;
}

std::string ConcurrentCalculator::format_schedule(
    const std::vector<StreamScheduleInfo>& schedule,
    const std::vector<StreamConfig>& streams,
    int total_duration
) const {
    std::stringstream ss;
    
    ss << "调度方案详情:\\n";
    ss << "============\\n";
    
    for (const auto& info : schedule) {
        if (info.stream_index < streams.size()) {
            const auto& stream = streams[info.stream_index];
            ss << "流 " << info.stream_index << ": " << stream.rtsp_url << "\\n";
            ss << "  时间段: " << info.start_time << "s - " << info.end_time << "s";
            ss << " (持续 " << info.duration << "s)\\n";
            ss << "  权重: " << stream.weight << ", 优先级: " << std::fixed 
               << std::setprecision(2) << info.priority_score << "\\n";
            ss << "  输出文件: " << stream.output_filename << "\\n\\n";
        }
    }
    
    // 添加时间线视图
    ss << "时间线视图 (每10秒一个标记):\\n";
    ss << "============================\\n";
    
    const int timeline_resolution = 10; // 每10秒显示一次
    for (int t = 0; t < total_duration; t += timeline_resolution) {
        int concurrent_count = get_concurrent_count_at_time(schedule, t);
        ss << std::setw(4) << t << "s: ";
        
        // 显示活跃的流
        std::vector<int> active_streams;
        for (const auto& info : schedule) {
            if (t >= info.start_time && t < info.end_time) {
                active_streams.push_back(info.stream_index);
            }
        }
        
        ss << "[并发:" << concurrent_count << "] 活跃流: ";
        for (size_t i = 0; i < active_streams.size(); ++i) {
            if (i > 0) ss << ",";
            ss << active_streams[i];
        }
        ss << "\\n";
    }
    
    // 添加统计信息
    auto stats = get_schedule_stats(schedule, total_duration);
    ss << "\\n统计信息:\\n";
    ss << "==========\\n";
    ss << "总流数: " << stats.total_streams << "\\n";
    ss << "最大并发数: " << stats.max_concurrent_used << "\\n";
    ss << "平均并发数: " << std::fixed << std::setprecision(2) << stats.average_concurrent << "\\n";
    ss << "总调度时长: " << stats.total_scheduled_duration << "s\\n";
    ss << "资源利用率: " << std::fixed << std::setprecision(2) << (stats.utilization_rate * 100) << "%\\n";
    
    return ss.str();
}

std::vector<StreamScheduleInfo> ConcurrentCalculator::optimize_schedule(
    std::vector<StreamScheduleInfo> schedule,
    int total_duration,
    int max_concurrent
) {
    // 简单的优化：尝试向前移动任务以减少碎片
    bool improved = true;
    while (improved) {
        improved = false;
        
        for (auto& info : schedule) {
            // 尝试将任务向前移动
            for (int new_start = 0; new_start < info.start_time; ++new_start) {
                // 临时移除当前任务
                auto temp_schedule = schedule;
                temp_schedule.erase(
                    std::find_if(temp_schedule.begin(), temp_schedule.end(),
                        [&info](const auto& item) { return &item == &info; })
                );
                
                // 检查新位置是否可行
                if (can_schedule_at_time(temp_schedule, new_start, info.duration, max_concurrent)) {
                    info.start_time = new_start;
                    info.end_time = new_start + info.duration;
                    improved = true;
                    break;
                }
            }
        }
        
        // 重新排序
        std::sort(schedule.begin(), schedule.end(),
            [](const auto& a, const auto& b) {
                return a.start_time < b.start_time;
            });
    }
    
    return schedule;
}

} // namespace jtjai_media