#include "app.hpp"
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <random>
#include <ctime>

namespace bmp {

// ============================================================================
// 辅助函数
// ============================================================================

/**
 * @brief 生成唯一ID（基于时间戳和随机数）
 */
static std::string generateId() {
    auto now = std::chrono::system_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        now.time_since_epoch()).count();
    std::mt19937 rng(static_cast<unsigned>(ms));
    std::uniform_int_distribution<int> dist(1000, 9999);
    std::ostringstream oss;
    oss << ms << "_" << dist(rng);
    return oss.str();
}

/**
 * @brief 获取当前时间点
 */
static std::chrono::system_clock::time_point now() {
    return std::chrono::system_clock::now();
}

/**
 * @brief 将时间点格式化为字符串
 */
static std::string timeToString(const std::chrono::system_clock::time_point& tp) {
    auto tt = std::chrono::system_clock::to_time_t(tp);
    std::tm tm;
#if defined(_WIN32)
    localtime_s(&tm, &tt);
#else
    localtime_r(&tt, &tm);
#endif
    std::ostringstream oss;
    oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
    return oss.str();
}

// ============================================================================
// EventService 实现
// ============================================================================

/**
 * @requirement(name="事件接收与处理", id="SU-01")
 * 接收原始事件数据，进行基本格式校验后存入内部存储。
 * 规则：非空检查、JSON/XML格式头识别，校验通过后创建事件对象。
 */
bool EventService::receiveEvent(const std::string& rawData) {
    if (rawData.empty()) {
        return false;
    }
    // 简单格式校验：检查是否以 { 或 < 开头
    if (rawData[0] != '{' && rawData[0] != '<') {
        return false;
    }
    Event evt;
    evt.id = generateId();
    evt.rawData = rawData;
    evt.status = EventStatus::PENDING;
    evt.priority = EventPriority::NORMAL;
    evt.occurTime = now();
    evt.createTime = now();
    evt.receiveNodeId = "NODE-001";
    evt.title = "未命名事件";
    evt.description = "从上游系统接收的原始事件";
    events_[evt.id] = evt;
    return true;
}

/**
 * @requirement(name="事件接收与处理", id="SU-01")
 * 生成确认消息，包含事件ID和时间戳。
 */
std::string EventService::sendAck(const std::string& eventId) {
    if (events_.count(eventId) == 0) {
        return "ACK:UNKNOWN";
    }
    return "ACK:" + eventId + "@" + timeToString(now());
}

/**
 * @requirement(name="事件标准化处理", id="SU-02")
 * 根据事件ID获取原始事件对象指针。
 */
const Event* EventService::getRawEvent(const std::string& eventId) const {
    auto it = events_.find(eventId);
    if (it != events_.end()) {
        return &(it->second);
    }
    return nullptr;
}

/**
 * @requirement(name="事件标准化处理", id="SU-02")
 * 执行事件标准化处理：
 * 1. 过滤无用字段，精简数据
 * 2. 统一时间戳格式
 * 3. 添加元数据（接收时间、处理节点ID）
 * 4. 标记状态为 PROCESSING
 */
bool EventService::processEvent(const std::string& eventId) {
    auto it = events_.find(eventId);
    if (it == events_.end()) {
        return false;
    }
    Event& evt = it->second;
    if (evt.status != EventStatus::PENDING) {
        return false;
    }
    // 模拟标准化处理：精简原始数据（保留前200字符）
    if (evt.rawData.size() > 200) {
        evt.rawData = evt.rawData.substr(0, 200) + "...(trimmed)";
    }
    evt.receiveNodeId = "NODE-001";
    evt.status = EventStatus::PROCESSING;
    return true;
}

/**
 * @requirement(name="事件标准化处理", id="SU-02")
 * 保存标准化事件到内部存储。如果事件已存在则覆盖。
 */
void EventService::saveStandardEvent(const Event& event) {
    events_[event.id] = event;
}

/**
 * @requirement(name="事件展示与操作", id="SU-03")
 * 根据过滤条件查询事件列表。
 * 支持按时间范围（time_from, time_to）、优先级（priority）、状态（status）过滤。
 */
std::vector<Event> EventService::queryEvents(
    const std::unordered_map<std::string, std::string>& filters) const
{
    std::vector<Event> result;
    for (const auto& pair : events_) {
        const Event& evt = pair.second;
        bool match = true;
        auto it = filters.find("priority");
        if (it != filters.end()) {
            int prio = std::stoi(it->second);
            if (static_cast<int>(evt.priority) != prio) {
                match = false;
            }
        }
        it = filters.find("status");
        if (it != filters.end()) {
            if (it->second == "PENDING" && evt.status != EventStatus::PENDING) match = false;
            else if (it->second == "PROCESSING" && evt.status != EventStatus::PROCESSING) match = false;
            else if (it->second == "ACCEPTED" && evt.status != EventStatus::ACCEPTED) match = false;
            else if (it->second == "REJECTED" && evt.status != EventStatus::REJECTED) match = false;
        }
        if (match) {
            result.push_back(evt);
        }
    }
    // 按时间降序排列
    std::sort(result.begin(), result.end(),
        [](const Event& a, const Event& b) {
            return a.createTime > b.createTime;
        });
    return result;
}

/**
 * @requirement(name="事件展示与操作", id="SU-03")
 * 获取所有状态为 PENDING 的待处理事件。
 */
std::vector<Event> EventService::getPendingEvents() const {
    std::vector<Event> result;
    for (const auto& pair : events_) {
        if (pair.second.status == EventStatus::PENDING) {
            result.push_back(pair.second);
        }
    }
    return result;
}

// ============================================================================
// TemplateService 实现
// ============================================================================

/**
 * @requirement(name="任务模板管理", id="SU-05")
 * 接收并解析模板集合。支持JSON数组或XML格式的批量模板。
 * 每个模板需包含 id, name, scenario, content, version 字段。
 */
size_t TemplateService::receiveTemplates(const std::string& rawData) {
    if (rawData.empty()) {
        return 0;
    }
    size_t count = 0;
    // 简易解析：按行分割，模拟从JSON/XML中提取模板
    std::istringstream stream(rawData);
    std::string line;
    TaskTemplate tmpl;
    bool inTemplate = false;
    while (std::getline(stream, line)) {
        if (line.find("\"id\"") != std::string::npos ||
            line.find("<id>") != std::string::npos) {
            auto pos = line.find(':');
            if (pos == std::string::npos) pos = line.find('>');
            if (pos != std::string::npos) {
                tmpl.id = line.substr(pos + 1);
                tmpl.id.erase(std::remove(tmpl.id.begin(), tmpl.id.end(), '\"'), tmpl.id.end());
                tmpl.id.erase(std::remove(tmpl.id.begin(), tmpl.id.end(), '>'), tmpl.id.end());
                tmpl.id.erase(std::remove(tmpl.id.begin(), tmpl.id.end(), '<'), tmpl.id.end());
                tmpl.id.erase(std::remove(tmpl.id.begin(), tmpl.id.end(), '/'), tmpl.id.end());
                tmpl.id.erase(std::remove(tmpl.id.begin(), tmpl.id.end(), ','), tmpl.id.end());
                tmpl.id.erase(std::remove(tmpl.id.begin(), tmpl.id.end(), ' '), tmpl.id.end());
                inTemplate = true;
            }
        }
        if (inTemplate && (line.find("\"name\"") != std::string::npos ||
                           line.find("<name>") != std::string::npos)) {
            auto pos = line.find(':');
            if (pos == std::string::npos) pos = line.find('>');
            if (pos != std::string::npos) {
                tmpl.name = line.substr(pos + 1);
                tmpl.name.erase(std::remove(tmpl.name.begin(), tmpl.name.end(), '\"'), tmpl.name.end());
                tmpl.name.erase(std::remove(tmpl.name.begin(), tmpl.name.end(), '>'), tmpl.name.end());
                tmpl.name.erase(std::remove(tmpl.name.begin(), tmpl.name.end(), '<'), tmpl.name.end());
                tmpl.name.erase(std::remove(tmpl.name.begin(), tmpl.name.end(), '/'), tmpl.name.end());
                tmpl.name.erase(std::remove(tmpl.name.begin(), tmpl.name.end(), ','), tmpl.name.end());
            }
        }
        // 简单判断模板结束
        if (inTemplate && (line.find("}") != std::string::npos ||
                           line.find("</template>") != std::string::npos)) {
            if (!tmpl.id.empty()) {
                if (tmpl.name.empty()) tmpl.name = "未命名模板";
                if (tmpl.scenario.empty()) tmpl.scenario = "通用场景";
                tmpl.version = "1.0";
                tmpl.createTime = now();
                tmpl.effectiveTime = now();
                tmpl.expireTime = now() + std::chrono::hours(24 * 365);
                templates_[tmpl.id] = tmpl;
                ++count;
            }
            tmpl = TaskTemplate();
            inTemplate = false;
        }
    }
    return count;
}

/**
 * @requirement(name="任务模板管理", id="SU-05")
 * 返回所有已存储的模板列表。
 */
std::vector<TaskTemplate> TemplateService::getTemplateList() const {
    std::vector<TaskTemplate> result;
    result.reserve(templates_.size());
    for (const auto& pair : templates_) {
        result.push_back(pair.second);
    }
    return result;
}

/**
 * @requirement(name="任务模板管理", id="SU-05")
 * 用户选择指定ID的模板。
 */
bool TemplateService::selectTemplate(const std::string& templateId) {
    return templates_.count(templateId) > 0;
}

/**
 * @requirement(name="任务模板管理", id="SU-05")
 * 基于事件类型匹配推荐最优模板。
 * 匹配规则：模板的scenario字段包含事件类型关键字则推荐。
 */
std::string TemplateService::recommendTemplate(const std::string& eventType) const {
    if (templates_.empty()) {
        return "";
    }
    // 查找scenario字段包含事件类型关键字的模板
    for (const auto& pair : templates_) {
        if (pair.second.scenario.find(eventType) != std::string::npos) {
            return pair.second.id;
        }
    }
    // 无精确匹配，返回第一个模板
    return templates_.begin()->second.id;
}

/**
 * @requirement(name="任务模板管理", id="SU-05")
 * 获取配置参数。
 */
std::unordered_map<std::string, std::string> TemplateService::getConfig() const {
    return {
        {"version_check", "enabled"},
        {"auto_recommend", "enabled"},
        {"max_templates", "1000"}
    };
}

// ============================================================================
// PlanService 实现
// ============================================================================

/**
 * @requirement(name="任务生成", id="SU-04")
 * 基于事件和模板生成任务草案。
 * 规则：
 * 1. 检查事件和模板是否存在
 * 2. 创建计划对象，生成唯一ID
 * 3. 创建默认计划节点（根节点）
 * 4. 保存计划为DRAFT状态
 * 5. 支持失败重试：如果计划已存在则返回空
 */
std::string PlanService::generateTask(
    const std::string& eventId,
    const std::string& templateId,
    const std::unordered_map<std::string, std::string>& params)
{
    if (eventId.empty() || templateId.empty()) {
        return "";
    }
    // 生成唯一计划ID
    std::string planId = "PLAN_" + generateId();
    TaskPlan plan;
    plan.id = planId;
    plan.eventId = eventId;
    plan.templateId = templateId;
    plan.status = PlanStatus::DRAFT;
    plan.generateTime = now();
    plan.responsiblePerson = "系统自动生成";
    // 从参数中提取备注
    auto it = params.find("remarks");
    if (it != params.end()) {
        plan.remarks = it->second;
    }
    // 创建根节点
    PlanNode rootNode;
    rootNode.nodeId = "NODE_" + generateId();
    rootNode.planId = planId;
    rootNode.parentNodeId = "";
    rootNode.taskType = "主任务";
    rootNode.executeUnit = "联合作战指挥部";
    rootNode.startTime = now();
    rootNode.endTime = now() + std::chrono::hours(24);
    rootNode.status = PlanStatus::DRAFT;
    plan.nodes.push_back(rootNode);

    plans_[planId] = plan;
    return planId;
}

/**
 * @requirement(name="任务生成", id="SU-04")
 * 提交任务草案，将状态从DRAFT更新为CONFIRMED。
 */
TaskPlan PlanService::submitTask(const std::string& planId) {
    TaskPlan emptyPlan;
    auto it = plans_.find(planId);
    if (it == plans_.end()) {
        return emptyPlan;
    }
    if (it->second.status == PlanStatus::DRAFT) {
        it->second.status = PlanStatus::CONFIRMED;
    }
    return it->second;
}

/**
 * @requirement(name="计划管理", id="SU-06")
 * 获取所有计划列表。
 */
std::vector<TaskPlan> PlanService::getPlanList() const {
    std::vector<TaskPlan> result;
    result.reserve(plans_.size());
    for (const auto& pair : plans_) {
        result.push_back(pair.second);
    }
    return result;
}

/**
 * @requirement(name="计划管理", id="SU-06")
 * 基于权重对计划排序。支持 priority（优先级权重）和 time（时间权重）。
 */
void PlanService::sortPlans(const std::unordered_map<std::string, int>& weights) {
    // 将计划转为向量
    std::vector<std::pair<std::string, TaskPlan>> items(plans_.begin(), plans_.end());
    // 根据权重排序
    int priorityWeight = 1;
    int timeWeight = 1;
    auto it = weights.find("priority");
    if (it != weights.end()) priorityWeight = it->second;
    it = weights.find("time");
    if (it != weights.end()) timeWeight = it->second;
    std::sort(items.begin(), items.end(),
        [priorityWeight, timeWeight](const auto& a, const auto& b) {
            // 按状态优先级和时间综合排序
            int scoreA = static_cast<int>(a.second.status) * priorityWeight;
            int scoreB = static_cast<int>(b.second.status) * priorityWeight;
            if (scoreA != scoreB) return scoreA > scoreB;
            if (timeWeight > 0) {
                return a.second.generateTime > b.second.generateTime;
            }
            return a.second.generateTime < b.second.generateTime;
        });
    // 重新构建map保持顺序（用unordered_map无法保持顺序，这里简化处理）
    // 实际工程中应使用有序容器，此处仅作演示
    std::unordered_map<std::string, TaskPlan> sortedPlans;
    for (const auto& item : items) {
        sortedPlans[item.first] = item.second;
    }
    plans_ = sortedPlans;
}

/**
 * @requirement(name="计划管理", id="SU-06")
 * 计划重配置：替换计划的所有节点，并将状态重置为DRAFT。
 * 返回true表示重配置成功。
 */
bool PlanService::reconfigurePlan(const std::string& planId,
                                  const std::vector<PlanNode>& newNodes)
{
    auto it = plans_.find(planId);
    if (it == plans_.end()) {
        return false;
    }
    it->second.nodes = newNodes;
    it->second.status = PlanStatus::DRAFT;
    it->second.generateTime = now();
    return true;
}

/**
 * @requirement(name="计划管理", id="SU-06")
 * 发送人机协同（HITL）干预通知。
 * 记录通知消息到计划备注中。
 */
void PlanService::notifyHITL(const std::string& planId, const std::string& message) {
    auto it = plans_.find(planId);
    if (it == plans_.end()) {
        return;
    }
    it->second.remarks += "\n[HITL通知@" + timeToString(now()) + "] " + message;
}

// ============================================================================
// DistributionService 实现
// ============================================================================

/**
 * @requirement(name="方案分发", id="SU-07")
 * 启动分发流程：为计划的每个节点创建分发日志，模拟发送过程。
 * 初始状态设为等待响应，retryCount为0。
 */
std::vector<DistributionLog> DistributionService::distributePlan(const std::string& planId) {
    std::vector<DistributionLog> result;
    // 为每个目标资产创建分发日志（简化：生成3条模拟记录）
    std::vector<std::string> assets = {"SATELLITE-01", "UAV-05", "RADAR-03"};
    for (const auto& asset : assets) {
        DistributionLog log;
        log.logId = "DLOG_" + generateId();
        log.planId = planId;
        log.targetAsset = asset;
        log.sendTime = now();
        log.response = DistributionResponse::TIMEOUT;
        log.retryCount = 0;
        log.errorCode = "";
        logs_.push_back(log);
        result.push_back(log);
    }
    return result;
}

/**
 * @requirement(name="方案分发", id="SU-07")
 * 接收资产返回的确认响应。
 * 查找匹配的分发日志，更新响应状态。
 */
bool DistributionService::receiveAck(const std::string& logId, DistributionResponse response) {
    for (auto& log : logs_) {
        if (log.logId == logId) {
            log.response = response;
            if (response == DistributionResponse::NACK || response == DistributionResponse::TIMEOUT) {
                log.retryCount++;
                if (log.retryCount >= 3) {
                    log.errorCode = "MAX_RETRY_EXCEEDED";
                }
            }
            return true;
        }
    }
    return false;
}

/**
 * @requirement(name="方案分发", id="SU-07")
 * 更新UI状态指示。在实际系统中会触发前端渲染更新。
 */
void DistributionService::updateStatus(const std::string& planId) {
    // 在实际系统中，此方法会通过消息队列通知前端更新UI
    // 当前实现为占位
    (void)planId;
}

/**
 * @requirement(name="方案分发", id="SU-07")
 * 查询指定计划的所有分发日志。
 */
std::vector<DistributionLog> DistributionService::getLogsByPlan(const std::string& planId) const {
    std::vector<DistributionLog> result;
    for (const auto& log : logs_) {
        if (log.planId == planId) {
            result.push_back(log);
        }
    }
    return result;
}

// ============================================================================
// StatusMonitorService 实现
// ============================================================================

/**
 * @requirement(name="状态监控", id="SU-08")
 * 接收遥测数据并解析。
 * 模拟从二进制数据中提取状态信息。
 */
StatusLog StatusMonitorService::receiveTelemetry(const std::vector<uint8_t>& rawData) {
    StatusLog log = parseData(rawData);
    latestStatus_[log.assetId] = log;
    return log;
}

/**
 * @requirement(name="状态监控", id="SU-08")
 * 解析二进制遥测数据。
 * 格式假设：[4字节资产ID][8字节时间戳][2字节状态码][N字节详细信息]
 */
StatusLog StatusMonitorService::parseData(const std::vector<uint8_t>& rawData) {
    StatusLog log;
    log.recordId = "STATUS_" + generateId();
    log.timestamp = now();
    log.isAbnormal = false;
    if (rawData.size() < 14) {
        log.assetId = "UNKNOWN";
        log.statusCode = "ERR_INVALID_DATA";
        log.detailInfo = "数据长度不足";
        log.isAbnormal = true;
        return log;
    }
    // 模拟解析资产ID（前4字节转字符串）
    log.assetId = "AST_" + std::to_string((rawData[0] << 24) | (rawData[1] << 16) |
                                           (rawData[2] << 8) | rawData[3]);
    // 模拟解析状态码（第12-13字节）
    uint16_t statusCode = (rawData[12] << 8) | rawData[13];
    log.statusCode = std::to_string(statusCode);
    log.detailInfo = "遥测数据已解析";
    // 异常判断：状态码大于9000视为异常
    if (statusCode > 9000) {
        log.isAbnormal = true;
        log.detailInfo = "遥测异常：状态码 " + log.statusCode;
    }
    return log;
}

/**
 * @requirement(name="状态监控", id="SU-08")
 * 检测到异常状态时生成报警消息。
 */
std::string StatusMonitorService::triggerAlarm(const StatusLog& statusLog) {
    if (!statusLog.isAbnormal) {
        return "";
    }
    std::ostringstream oss;
    oss << "[ALARM] 资产 " << statusLog.assetId
        << " 状态异常：" << statusLog.detailInfo
        << " @ " << timeToString(statusLog.timestamp);
    return oss.str();
}

/**
 * @requirement(name="状态监控", id="SU-08")
 * 获取指定资产的最新状态日志。
 */
StatusLog StatusMonitorService::getLatestStatus(const std::string& assetId) const {
    StatusLog emptyLog;
    auto it = latestStatus_.find(assetId);
    if (it != latestStatus_.end()) {
        return it->second;
    }
    emptyLog.assetId = assetId;
    emptyLog.statusCode = "NO_DATA";
    emptyLog.detailInfo = "无遥测数据";
    emptyLog.isAbnormal = true;
    return emptyLog;
}

/**
 * @requirement(name="状态监控", id="SU-08")
 * 检查并标记数据陈旧。如果最新状态更新时间超过阈值，标记为STALE。
 */
void StatusMonitorService::checkStaleData(uint64_t thresholdMs) {
    auto nowTime = now();
    for (auto& pair : latestStatus_) {
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
            nowTime - pair.second.timestamp).count();
        if (elapsed > static_cast<int64_t>(thresholdMs)) {
            pair.second.isAbnormal = true;
            pair.second.statusCode = "STALE";
            pair.second.detailInfo = "数据陈旧，最后更新于 " + timeToString(pair.second.timestamp);
        }
    }
}

// ============================================================================
// BattlefieldMissionPlanner 实现
// ============================================================================

/**
 * @requirement(name="业务目标", id="REQ-BMP-001")
 * 构造系统外观类，初始化各子系统服务实例。
 */
BattlefieldMissionPlanner::BattlefieldMissionPlanner()
    : eventService_()
    , templateService_()
    , planService_()
    , distributionService_()
    , statusMonitorService_()
{
}

/**
 * @requirement(name="业务目标", id="REQ-BMP-001")
 * 初始化系统，加载配置。
 * 当前实现为占位，实际工程中会加载配置文件、连接数据库等。
 */
bool BattlefieldMissionPlanner::initialize() {
    // 实际工程中此处将加载配置文件、初始化数据库连接池、启动消息队列等
    return true;
}

/**
 * @requirement(name="业务目标", id="REQ-BMP-001")
 * 运行主循环。
 * 当前实现为演示，输出系统启动信息。
 */
void BattlefieldMissionPlanner::run() {
    // 在实际系统中，此方法将启动事件监听循环、消息队列处理、定时任务等
    // 当前为占位实现
}

} // namespace bmp
