#pragma once
//stl
#include <iostream>
//robotics
#include <robotics/timer.hpp>
#include <robotics/message_bus.hpp>
//local
#include "../xml/xml_update.hpp"
#include "../network/network.hpp"

using namespace robotics;
extern v3::message_bus g_message_bus;

class core {
public:
	/**
	 * @brief 初始化 core 类的事件绑定，包括定时器超时事件和消息总线的请求处理函数。
	 */
	core() {
		network_ = network::instance();
		timer_.timeout_event.bind(&core::on_timeout, this);
		g_message_bus.bind("cloud_drop_request", &core::on_sync_drop_request, this);
		g_message_bus.bind("cloud_general_request", &core::on_sync_general_request, this);
		g_message_bus.bind("cloud_regex_request", &core::on_sync_regex_request, this);

		network_->cloud_drop_event.bind(&core::on_cloud_drop_response, this);
		network_->cloud_general_event.bind(&core::on_cloud_general_response, this);
		network_->cloud_regex_event.bind(&core::on_cloud_regex_response, this);
		network_->local_stepping_event.bind(&core::on_local_stepping, this);
		network_->local_supply_event.bind(&core::on_local_supply, this);
		network_->local_drop_event.bind(&core::on_local_drop, this);
	}
	/**
	 * @brief 析构函数，用于销毁 core 对象并在销毁前调用 stop() 方法。
	 */
	~core() {
		stop();
	}
	/**
	 * @brief 启动定时器，设置为10分钟后触发。
	 */
	void start() {
		network_->start();
		timer_.start(1000 * 60 * 10);
	}
	/**
	 * @brief 停止计时器的运行。
	 */
	void stop() {
		timer_.stop();
		network_->stop();
	}
private:
	/**
	 * @brief 处理同步丢弃请求并更新 XML 配置。
	 */
	void on_sync_drop_request() {
		auto values = network_->sync_drop_request();
		xml_update::update(values);
	}
	/**
	 * @brief 根据给定的键发起同步请求，并用返回的数据更新XML配置。
	 * @param key 用于同步请求的键。
	 */
	void on_sync_general_request(int key) {
		auto values = network_->sync_general_request(key);
		xml_update::update(values);
	}
	/**
	 * @brief 同步正则表达式请求并更新配置。
	 */
	void on_sync_regex_request() {
		auto values = network_->sync_regex_request();
		xml_update::update(values);
	}
private:
	/**
	 * @brief 处理云端拖拽响应并更新配置。
	 * @param values 包含 web_drop_config_info 对象的常量引用向量，表示要更新的配置信息。
	 */
	void on_cloud_drop_response(std::vector<web_drop_config_info>const& values) {
		xml_update::update(values);
	}
	/**
	 * @brief 处理云端通用响应并更新本地配置。
	 * @param values 包含 web_general_config_info 对象的常量引用向量，表示从云端接收到的配置信息。
	 */
	void on_cloud_general_response(std::vector<web_general_config_info>const& values) {
		xml_update::update(values);
	}
	/**
	 * @brief 处理云端正则表达式响应并更新本地配置。
	 * @param values 包含正则表达式配置信息的常量引用向量。
	 */
	void on_cloud_regex_response(std::vector<web_regex_config_info>const& values) {
		xml_update::update(values);
	}
private:
	/**
	 * @brief 处理扫描运单号的操作，并统计相关信息。
	 * @param supply_no 供应编号，用于标识供应商或供应点。
	 * @param waybill_no 运单号，用于识别快递单据。
	 */
	void on_local_supply(int supply_no,std::string const& waybill_no) {
		int type = get_express_type(waybill_no);
		supply_statistics(type, supply_no);
	}
	/**
	 * @brief 处理快递单号投递事件，并统计相关格口信息。
	 * @param lattice_no 格口编号，用于指定投递的格口。
	 * @param drop_type 投递类型，表示投递的方式或类型。
	 * @param waybill_no 快递单号，用于识别快递类型。
	 */
	void on_local_drop(int lattice_no, int drop_type, std::string const& waybill_no) {
		int type = get_express_type(waybill_no);
		if (0 != drop_type) {
			reflux_statistics(type, drop_type);
		}
		else {
			lattice_statistics(type, lattice_no);
		}
	}
	/**
	 * @brief 在本地步进事件发生时，更新同步数据的运行距离。
	 * @param speed 当前步进的速度。
	 * @param lineNo 相关的行号。
	 */
	void on_local_stepping(double speed, int lineNo) {
		auto config = xml_context::from<web_general_config_info>().where([](auto it) {return it->enable && it->key == 5; }).first();
		if (!config) {
			config.reset(new web_general_config_info());
			config->value = "600";
		}
		std::lock_guard<std::mutex> locker(mutex_);
		sync_data_.speed = speed;
		sync_data_.running_distance += std::atoi(config->value.c_str());
	}
private:
	/**
	 * @brief 扫描并处理指定类型和供应编号的统计信息。
	 * @param type 要扫描的统计信息类型。
	 * @param supply_no 相关的供应编号。
	 */
	void supply_statistics(int type, int supply_no) {
		std::lock_guard<std::mutex> locker(mutex_);
		for (auto& it : sync_data_.data) {
			if (it.express_type == type) {
				it.supply_count++;
				statistics(supply_no, it.supply_summay);
				return;
			}
		}
		sync_data_.data.push_back(
			web_sync_item_request_info {
				.express_type = type,
				.lattice_count = 0,
				.supply_count = 0,
				.reflux_count = 0,
				.supply_summay = "",
				.lattice_summay = "",
				.reflux_summay = "" });
		sync_data_.data[sync_data_.data.size() - 1].supply_count++;
		statistics(supply_no, sync_data_.data[sync_data_.data.size() - 1].supply_summay);
	}
	/**
	 * @brief 计算指定类型和编号的晶格的统计信息。
	 * @param type 要统计的晶格类型。
	 * @param lattice_no 要统计的晶格编号。
	 */
	void lattice_statistics(int type, int lattice_no) {
		std::lock_guard<std::mutex> locker(mutex_);
		for (auto& it : sync_data_.data) {
			if (it.express_type == type) {
				it.lattice_count++;
				statistics(lattice_no, it.lattice_summay);
				return;
			}
		}
		sync_data_.data.push_back(
			web_sync_item_request_info{
				.express_type = type,
				.lattice_count = 0,
				.supply_count = 0,
				.reflux_count = 0,
				.supply_summay = "",
				.lattice_summay = "",
				.reflux_summay = "" });
		sync_data_.data[sync_data_.data.size() - 1].lattice_count++;
		statistics(lattice_no, sync_data_.data[sync_data_.data.size() - 1].lattice_summay);
	}
	/**
	 * @brief 统计回流相关信息的函数。
	 * @param type 指定统计的类型。
	 * @param drop_type 指定丢弃类型。
	 */
	void reflux_statistics(int type, int drop_type) {
		std::lock_guard<std::mutex> locker(mutex_);
		for (auto& it : sync_data_.data) {
			if (it.express_type == type) {
				it.reflux_count++;
				statistics(drop_type, it.reflux_summay);
				return;
			}
		}
		sync_data_.data.push_back(
			web_sync_item_request_info{
				.express_type = type,
				.lattice_count = 0,
				.supply_count = 0,
				.reflux_count = 0,
				.supply_summay = "",
				.lattice_summay = "",
				.reflux_summay = "" });
		sync_data_.data[sync_data_.data.size() - 1].reflux_count++;
		statistics(drop_type, sync_data_.data[sync_data_.data.size() - 1].reflux_summay);
	}
	/**
	 * @brief 根据运单号获取快递类型。
	 * @param waybill_no 要查询的运单号字符串。
	 * @return 匹配到的快递类型编号。如果未匹配到，返回0。
	 */
	int get_express_type(std::string const& waybill_no) {
		auto list = xml_context::from<web_regex_config_info>().where([](auto it) {return it->enable; }).value_ptr();
		int type = 0;
		for (auto& it : list) {
			if (!it->regex.empty() && v3::utils::regex_check(waybill_no, it->regex)) {
				type = it->type;
				break;
			}
		}
		return type;
	}
	/**
	 * @brief 统计并更新字符串中指定数字的计数值，如果不存在则添加该数字及其计数。
	 * @param number 要统计的数字。
	 * @param value 包含数字及其计数的字符串，格式如 ",数字|计数"，该参数会被函数修改。
	 */
	void statistics(int number, std::string& value) {
		std::string find_str = "," + std::to_string(number) + "|";
		auto pos = value.find(find_str);
		if (pos != std::string::npos) {
			int begin_pos = pos + find_str.size();
			int end_pos = value.find(",", begin_pos);
			if (end_pos != std::string::npos) {
				std::string substr = value.substr(pos + find_str.size(), end_pos - (pos + find_str.size()));
				value.replace(begin_pos, end_pos - begin_pos, std::to_string(std::atoi(substr.c_str()) + 1));
			}
			else {
				std::string substr = value.substr(pos + find_str.size());
				value.replace(begin_pos, value.size() - begin_pos, std::to_string(std::atoi(substr.c_str()) + 1));
			}
		}
		else {
			value += "," + std::to_string(number) + "|1";
		}
	}
private:
	/**
	 * @brief 在超时时调用的回调函数。
	 */
	void on_timeout() {
		auto config = xml_context::from<web_general_config_info>().where([](auto it) {return it->enable && it->key == 6; }).first();
		if (!config) {
			config.reset(new web_general_config_info());
			config->value = "10";
		}
		timer_.set_timer_interval(1000 * 60 * std::atoi(config->value.c_str()));
		std::lock_guard<std::mutex> locker(mutex_);
		try {
			if (sync_data_.running_distance != 0 || sync_data_.speed != 0 || sync_data_.data.size() != 0) {
				sync_data_.summary_time = v3::datetime::current_time_stamp();
				if (!network_->sync_request(sync_data_)) {
					std::vector<web_sync_config_info> add_datas;
					for (auto& it : sync_data_.data) {
						int id = 0;
						xml_context::from<web_sync_config_info>().max(id, [](auto it) {return it->id; }).inc(id);
						add_datas.push_back(web_sync_config_info{
								.id = id,
								.create_time = v3::datetime::current_time_stamp(),
								.device_id = sync_data_.device_id,
								.summary_time = sync_data_.summary_time,
								.running_distance = sync_data_.running_distance,
								.speed = sync_data_.speed,
								.express_type = it.express_type,
								.lattice_count = it.lattice_count,
								.supply_count = it.supply_count,
								.reflux_count = it.reflux_count,
								.supply_summay = it.supply_summay,
								.lattice_summay = it.lattice_summay,
								.reflux_summay = it.reflux_summay,
								.enable = true,
								.remarks = "未上传" });
					}
					xml_context::from<web_sync_config_info>().append(add_datas).submit();
				}
			}
			sync_data_.running_distance = 0;
			sync_data_.speed = 0;
			sync_data_.summary_time = (time_t)0;
			sync_data_.data.clear();
		}
		catch (std::exception const& ec) {
			LOG_ERROR << ec;
		}
		//把未上传的数据分组
		auto values = xml_context::from<web_sync_config_info>().group_by<v3::datetime>([](auto it) { return it->summary_time; });
		//构建上传数据
		std::map<std::vector<int>, web_sync_request_info> sync_datas;
		for (auto& [key, value] : values) {
			web_sync_request_info item;
			std::vector<int> ids;
			item.device_id = value[0]->device_id;
			item.running_distance = value[0]->running_distance;
			item.speed = value[0]->speed;
			item.summary_time = value[0]->summary_time;
			for (auto& it : value) {
				ids.push_back(it->id);
				item.data.push_back(web_sync_item_request_info{
						.express_type = it->express_type,
						.lattice_count = it->lattice_count,
						.supply_count = it->supply_count,
						.reflux_count = it->reflux_count,
						.supply_summay = it->supply_summay,
						.lattice_summay = it->lattice_summay,
						.reflux_summay = it->reflux_summay });
			}
			sync_datas[ids] = item;
		}
		//循环上传数据
		for (auto& [key, value] : sync_datas) {
			try {
				//上传数据
				if (network_->sync_request(value)) {
					//删除上传完成的数据
					for (auto& id : key) {
						xml_context::from<web_sync_config_info>().remove([id](auto it) {
							return it->id == id; }).submit();
					}
				}
			}
			catch (std::exception const& ec) {
				LOG_ERROR << ec;
			}
		}
	}
private:
	/**
	 * @brief 互斥锁对象，用于多线程同步。
	 */
	std::mutex mutex_;
	/**
	 * @brief 同步请求的信息对象。
	 */
	web_sync_request_info sync_data_;
	/**
	 * @brief v3::timer 类型的计时器对象。
	 */
	v3::timer timer_;
	/**
	 * @brief 定义并初始化一个指向 network 类型的指针变量 network_，初始值为 nullptr。
	 */
	network*  network_ = nullptr;
};