/**
 * @file    com_router.cpp
 * @brief   通信路由中枢 — 通道管理 + JSON配置 + 转发TCP accept + 主循环
 */

#include "mySystem.h"
#include "myComm.h"
#include "myLog.h"
#include "myFunc.h"
#include "myDatacenter.h"
#include "cJSON.h"
#include "com_router.h"

#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <string>

/* =========================== 全局配置 =========================== */

#define MAX_CHANNELS       8
#define MAX_FORWARD_RULES  4

com_channel_t       g_channels[MAX_CHANNELS];
int                 g_channel_count = 0;

com_forward_rule_t  g_forward_rules[MAX_FORWARD_RULES];
int                 g_forward_count = 0;

static int          g_config_loaded = 0;

/* =========================== 协议分发注册表 =========================== */

typedef struct
{
	char                     bind_app[16];
	com_router_dispatch_cb   cb;
} dispatch_entry_t;

static dispatch_entry_t g_dispatch_table[MAX_DISPATCH_APPS];
static int              g_dispatch_count = 0;

int com_router_register_dispatch(const char *bind_app, com_router_dispatch_cb cb)
{
	if(NULL == bind_app || NULL == cb || g_dispatch_count >= MAX_DISPATCH_APPS)
	{
		return -1;
	}

	strncpy(g_dispatch_table[g_dispatch_count].bind_app, bind_app, 15);
	g_dispatch_table[g_dispatch_count].cb = cb;
	g_dispatch_count++;

	LOG_I("com_router: registered dispatch for [%s]", bind_app);
	return 0;
}

/* 内部查找: 按 bind_app 取回调, 未找到返回 NULL */
com_router_dispatch_cb com_router_dispatch_find(const char *bind_app)
{
	int i;

	if(NULL == bind_app || '\0' == bind_app[0])
	{
		return NULL;
	}

	for(i = 0; i < g_dispatch_count; i++)
	{
		if(0 == strcmp(g_dispatch_table[i].bind_app, bind_app))
		{
			return g_dispatch_table[i].cb;
		}
	}

	return NULL;
}

/* =========================== 前向声明 =========================== */

extern void com_router_recv_cb(int id, int fd, const unsigned char *data, int len);
static void com_router_state_cb(int id, int fd, int state);
static int  com_router_channel_create(void);
static int  com_router_channel_connect(void);

/* =========================== JSON 配置解析 =========================== */

static int com_router_parse_channels(cJSON *arr)
{
	int i;
	int count = cJSON_GetArraySize(arr);

	if(count > MAX_CHANNELS)
	{
		count = MAX_CHANNELS;
	}

	for(i = 0; i < count; i++)
	{
		cJSON *item = cJSON_GetArrayItem(arr, i);
		com_channel_t *ch = &g_channels[i];

		memset(ch, 0, sizeof(*ch));
		ch->id        = -1;
		ch->socket_fd = -1;

		cJSON *key  = cJSON_GetObjectItem(item, "key");
		cJSON *type = cJSON_GetObjectItem(item, "type");
		cJSON *bind = cJSON_GetObjectItem(item, "bind_app");
		cJSON *desc = cJSON_GetObjectItem(item, "desc");
		(void)desc;

		if(NULL == key || NULL == type) continue;

		strncpy(ch->key, key->valuestring, 31);
		if(NULL != bind) { strncpy(ch->bind_app, bind->valuestring, 15); }
		else             { ch->bind_app[0] = '\0'; }

		if(0 == strcmp(type->valuestring, "uart"))
		{
			cJSON *dev = cJSON_GetObjectItem(item, "device");
			cJSON *baud = cJSON_GetObjectItem(item, "baudrate");
			cJSON *dbits = cJSON_GetObjectItem(item, "data_bits");
			cJSON *sbits = cJSON_GetObjectItem(item, "stop_bits");
			cJSON *par = cJSON_GetObjectItem(item, "parity");

			ch->type = COMM_TYPE_UART;
			if(dev)  { ch->para.uart.device[0] = '\0'; strcat(ch->para.uart.device, dev->valuestring); }
			if(baud)  ch->para.uart.baudrate  = baud->valueint;
			if(dbits) ch->para.uart.data_bits = dbits->valueint;
			if(sbits) ch->para.uart.stop_bits = sbits->valueint;
			if(par)   ch->para.uart.parity    = par->valuestring[0];
		}
		else if(0 == strcmp(type->valuestring, "tcp_server"))
		{
			cJSON *lip = cJSON_GetObjectItem(item, "local_ip");
			cJSON *lport = cJSON_GetObjectItem(item, "local_port");

			ch->type = COMM_TYPE_TCP_SERVER;
			if(lip)   { ch->para.tcp.local_ip[0] = '\0'; strcat(ch->para.tcp.local_ip, lip->valuestring); }
			if(lport)  ch->para.tcp.local_port = lport->valueint;
			ch->para.tcp.remote_ip[0] = '\0';
			ch->para.tcp.remote_port = 0;
		}
		else if(0 == strcmp(type->valuestring, "tcp_client"))
		{
			cJSON *rip = cJSON_GetObjectItem(item, "remote_ip");
			cJSON *rport = cJSON_GetObjectItem(item, "remote_port");

			ch->type = COMM_TYPE_TCP_CLIENT;
			ch->para.tcp.local_ip[0] = '\0';
			ch->para.tcp.local_port = 0;
			if(rip)   { ch->para.tcp.remote_ip[0] = '\0'; strcat(ch->para.tcp.remote_ip, rip->valuestring); }
			if(rport)  ch->para.tcp.remote_port = rport->valueint;
		}
	}

	g_channel_count = count;
	return 0;
}

static int com_router_parse_forwards(cJSON *arr)
{
	int i;
	int count = cJSON_GetArraySize(arr);

	if(count > MAX_FORWARD_RULES)
	{
		count = MAX_FORWARD_RULES;
	}

	for(i = 0; i < count; i++)
	{
		cJSON *item = cJSON_GetArrayItem(arr, i);
		com_forward_rule_t *fw = &g_forward_rules[i];

		memset(fw, 0, sizeof(*fw));
		fw->listen_ch_id = -1;
		fw->sock_fd       = -1;
		fw->target_ch_id  = -1;

		cJSON *lip   = cJSON_GetObjectItem(item, "listen_ip");
		cJSON *lport = cJSON_GetObjectItem(item, "listen_port");
		cJSON *tgt   = cJSON_GetObjectItem(item, "target_channel");

		if(NULL == lip || NULL == lport || NULL == tgt) continue;

		strncpy(fw->listen_ip, lip->valuestring, 31);
		fw->listen_port = lport->valueint;
		strncpy(fw->target_channel, tgt->valuestring, 31);
	}

	g_forward_count = count;
	return 0;
}

int com_router_config_load(const char *json_path)
{
	if(NULL == json_path)
	{
		LOG_E("com_router_config_load: NULL path");
		return -1;
	}

	uint32_t fsize = 0;
	uint8_t *buf = func_read_file_alloc(json_path, &fsize);

	if(NULL == buf || 0 == fsize)
	{
		LOG_E("com_router_config_load: read failed, using default");
		return -1;
	}

	cJSON *root = cJSON_Parse((const char *)buf);
	free(buf);

	if(NULL == root)
	{
		LOG_E("com_router_config_load: parse failed");
		return -1;
	}

	cJSON *ch_arr = cJSON_GetObjectItem(root, "channels");
	cJSON *fw_arr = cJSON_GetObjectItem(root, "forward_rules");

	if(NULL != ch_arr && cJSON_Array == ch_arr->type)
	{
		com_router_parse_channels(ch_arr);
	}

	if(NULL != fw_arr && cJSON_Array == fw_arr->type)
	{
		com_router_parse_forwards(fw_arr);
	}

	cJSON_Delete(root);
	g_config_loaded = 1;

	LOG_I("com_router: config loaded, %d channels, %d forward_rules",
		g_channel_count, g_forward_count);

	return 0;
}

/* =========================== 默认配置 =========================== */

static int com_router_config_default(void)
{
	/* 通道 0: FTU 串口 */
	{
		com_channel_t *ch = &g_channels[0];
		strcpy(ch->key, "serial_ftu");
		strcpy(ch->bind_app, "");
		ch->type = COMM_TYPE_UART;
		ch->para.uart.device[0] = '\0';
		strcat(ch->para.uart.device, "/dev/ttyS1");
		ch->para.uart.baudrate  = 115200;
		ch->para.uart.data_bits = 8;
		ch->para.uart.stop_bits = 1;
		ch->para.uart.parity    = 'N';
		ch->id = -1;
		ch->socket_fd = -1;
	}

	/* 通道 1: TCP 主站 */
	{
		com_channel_t *ch = &g_channels[1];
		strcpy(ch->key, "tcp_master");
		strcpy(ch->bind_app, "");
		ch->type = COMM_TYPE_TCP_SERVER;
		ch->para.tcp.local_ip[0] = '\0';
		strcat(ch->para.tcp.local_ip, "0.0.0.0");
		ch->para.tcp.local_port  = 2404;
		ch->para.tcp.remote_ip[0] = '\0';
		ch->para.tcp.remote_port = 0;
		ch->id = -1;
		ch->socket_fd = -1;
	}

	/* 通道 2: FTU 网口 (TCP 客户端 → 127.0.0.1:54321) */
	{
		com_channel_t *ch = &g_channels[2];
		strcpy(ch->key, "tcp_ftu");
		strcpy(ch->bind_app, "");
		ch->type = COMM_TYPE_TCP_CLIENT;
		ch->para.tcp.local_ip[0] = '\0';
		ch->para.tcp.local_port = 0;
		ch->para.tcp.remote_ip[0] = '\0';
		strcat(ch->para.tcp.remote_ip, "127.0.0.1");
		ch->para.tcp.remote_port = 54321;
		ch->id = -1;
		ch->socket_fd = -1;
	}

	/* 转发规则: TCP:2405 → serial_ftu */
	{
		com_forward_rule_t *fw = &g_forward_rules[0];
		strcpy(fw->listen_ip, "0.0.0.0");
		fw->listen_port   = 2405;
		strcpy(fw->target_channel, "serial_ftu");
		fw->listen_ch_id  = -1;
		fw->sock_fd       = -1;
		fw->target_ch_id  = -1;
	}

	g_channel_count = 3;
	g_forward_count = 1;
	g_config_loaded = 1;

	LOG_I("com_router: default config (3 channels + 1 forward)");

	return 0;
}

/* =========================== 转发 TCP 服务端创建 =========================== */

/**
 * @brief 为转发规则创建 TCP 服务端 (通过 libcomm)
 * @details 每条转发规则创建一个 COMM_TYPE_TCP_SERVER 通道,
 *          客户端连接后由 com_router_state_cb 更新 fw->sock_fd。
 */
static int com_router_forward_create(void)
{
	int i;

	for(i = 0; i < g_forward_count; i++)
	{
		com_forward_rule_t *fw = &g_forward_rules[i];
		union_comm_para para;

		memset(&para, 0, sizeof(para));
		para.tcp.local_port = fw->listen_port;
		para.tcp.local_ip[0] = '\0';
		strcat(para.tcp.local_ip, fw->listen_ip);
		para.tcp.remote_ip[0] = '\0';
		para.tcp.remote_port = 0;

		fw->listen_ch_id = comm_create(COMM_TYPE_TCP_SERVER, 0, &para);
		if(fw->listen_ch_id < 0)
		{
			LOG_E("com_router: forward create failed for port %d", fw->listen_port);
			continue;
		}

		if(0 != comm_recv_register(fw->listen_ch_id, com_router_recv_cb))
		{
			LOG_E("com_router: forward recv_register failed");
		}

		if(0 != comm_state_register(fw->listen_ch_id, com_router_state_cb))
		{
			LOG_E("com_router: forward state_register failed");
		}

		LOG_I("com_router: forward created, port=%d → %s, ch_id=%d",
			fw->listen_port, fw->target_channel, fw->listen_ch_id);
	}

	return 0;
}

/**
 * @brief 解析转发规则中的目标通道 key → ch_id
 * @note 必须在通道创建完成后调用
 */
static int com_router_forward_resolve_targets(void)
{
	int i, j;

	for(i = 0; i < g_forward_count; i++)
	{
		com_forward_rule_t *fw = &g_forward_rules[i];

		for(j = 0; j < g_channel_count; j++)
		{
			if(0 == strcmp(g_channels[j].key, fw->target_channel))
			{
				fw->target_ch_id = g_channels[j].id;
				LOG_I("com_router: forward %s:%d → %s (id=%d)",
					fw->listen_ip, fw->listen_port,
					fw->target_channel, fw->target_ch_id);
				break;
			}
		}
	}

	return 0;
}

/* =========================== 通道创建/连接 =========================== */

static int com_router_channel_create(void)
{
	int i;

	for(i = 0; i < g_channel_count; i++)
	{
		com_channel_t *ch = &g_channels[i];

		ch->id = comm_create(ch->type, 0, &ch->para);
		if(ch->id < 0)
		{
			LOG_E("com_router: create failed for %s", ch->key);
			return -1;
		}

		if(0 != comm_recv_register(ch->id, com_router_recv_cb))
		{
			LOG_E("com_router: recv_reg failed for %s", ch->key);
			return -1;
		}

		if(0 != comm_state_register(ch->id, com_router_state_cb))
		{
			LOG_E("com_router: state_reg failed for %s", ch->key);
			return -1;
		}

		LOG_I("com_router: channel %s created, id=%d", ch->key, ch->id);
	}

	/* 创建转发 TCP 服务端 */
	com_router_forward_create();

	return 0;
}

static void *com_router_connect_thread(void *arg)
{
	int id = *(int *)arg;

	if(0 != comm_connect(id))
	{
		LOG_E("com_router: connect failed for id=%d", id);
	}

	return NULL;
}

static int com_router_channel_connect(void)
{
	int i;
	pthread_t tid;

	/* 连接常规通道 */
	for(i = 0; i < g_channel_count; i++)
	{
		com_channel_t *ch = &g_channels[i];

		if(ch->id < 0) continue;

		if(0 != pthread_create(&tid, NULL, com_router_connect_thread, &ch->id))
		{
			LOG_E("com_router: thread create failed for %s", ch->key);
		}
		else
		{
			pthread_detach(tid);
		}
		memset(&tid, 0, sizeof(tid));
	}

	/* 连接转发 TCP 服务端 (开始 listen) */
	for(i = 0; i < g_forward_count; i++)
	{
		com_forward_rule_t *fw = &g_forward_rules[i];

		if(fw->listen_ch_id < 0) continue;

		if(0 != pthread_create(&tid, NULL, com_router_connect_thread, &fw->listen_ch_id))
		{
			LOG_E("com_router: forward thread failed for port %d", fw->listen_port);
		}
		else
		{
			pthread_detach(tid);
		}
	}

	/* 解析转发目标 */
	com_router_forward_resolve_targets();

	return 0;
}

/* =========================== 状态回调 =========================== */

static void com_router_state_cb(int id, int fd, int state)
{
	int i;

	LOG_I("com_router_state: id=%d, fd=%d, state=%d", id, fd, state);

	/* 更新常规通道 */
	for(i = 0; i < g_channel_count; i++)
	{
		com_channel_t *ch = &g_channels[i];

		if(ch->id != id) continue;

		if(COMM_STATE_CONNECTED == state)
		{
			ch->socket_fd = fd;
			ch->interface = ((uint32_t)id << 16) | (uint32_t)fd;
		}
		else if(COMM_STATE_DISCONNECTED == state)
		{
			ch->socket_fd = -1;
			ch->interface = ((uint32_t)id << 16);
		}

		LOG_I("com_router: %s if=0x%08X", ch->key, ch->interface);
		return;
	}

	/* 更新转发 TCP 服务端的客户端 fd */
	for(i = 0; i < g_forward_count; i++)
	{
		com_forward_rule_t *fw = &g_forward_rules[i];

		if(fw->listen_ch_id != id) continue;

		if(COMM_STATE_CONNECTED == state)
		{
			fw->sock_fd = fd;
			LOG_I("com_router: forward port=%d client connected, fd=%d",
				fw->listen_port, fd);
		}
		else if(COMM_STATE_DISCONNECTED == state)
		{
			LOG_I("com_router: forward port=%d client disconnected, fd=%d",
				fw->listen_port, fw->sock_fd);
			fw->sock_fd = -1;
		}

		return;
	}
}


/* =========================== 查询 API =========================== */

uint32_t com_router_interface_get(const char *key)
{
	int i;

	for(i = 0; i < g_channel_count; i++)
	{
		if(0 == strcmp(g_channels[i].key, key))
		{
			return g_channels[i].interface;
		}
	}

	return 0;
}

int com_router_fd_get(const char *key)
{
	int i;

	for(i = 0; i < g_channel_count; i++)
	{
		if(0 == strcmp(g_channels[i].key, key))
		{
			return g_channels[i].socket_fd;
		}
	}

	return -1;
}

int com_router_id_get_by_bind(const char *bind_app)
{
	int i;

	for(i = 0; i < g_channel_count; i++)
	{
		if(0 == strcmp(g_channels[i].bind_app, bind_app))
		{
			return g_channels[i].id;
		}
	}

	return -1;
}

/* =========================== 应用线程入口 =========================== */

int app_com_router_init1(void *arg)
{
	(void)arg;

	/* 尝试加载 JSON, 失败则用默认 */
	if(0 == g_config_loaded)
	{
		const char *path = "config/CHANNEL/channel_cfg.json";

		if(0 != com_router_config_load(path))
		{
			com_router_config_default();
		}
	}

	if(0 != com_router_channel_create())
	{
		return -1;
	}

	return 0;
}

int app_com_router_init2(void *arg)
{
	(void)arg;

	if(0 != com_router_channel_connect())
	{
		return -1;
	}

	return 0;
}

void *app_com_router(void *arg)
{
	stru_app *p_app = (stru_app *)arg;
	uint32_t  event;

	while(1)
	{
		task_event_recv(p_app->p_event,
			EV_TIMER1 | EV_TIMER2 | EV_TIMER3 | EV_COM_RX_SELF_PTL | EV_STOP,
			TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
			TASK_EVENT_WAIT_FOREVER,
			&event);

		if(EV_TIMER1 & event)
		{
			/*
			 * 通道健康检测 (10ms):
			 *   巡检通道 socket_fd, 断开则记录。
			 *   未来可在此加自动重连逻辑。
			 */
			static int last_state[MAX_CHANNELS];
			int i;

			for(i = 0; i < g_channel_count; i++)
			{
				com_channel_t *ch = &g_channels[i];

				if(ch->socket_fd < 0)
				{
					/* 已断开, 仅第一次打印 */
					if(last_state[i] >= 0)
					{
						LOG_I("com_router: %s disconnected", ch->key);
						last_state[i] = -1;
					}
				}
				else
				{
					if(last_state[i] <= 0)
					{
						LOG_I("com_router: %s connected", ch->key);
					}
					last_state[i] = 1;
				}
			}
		}

		if(EV_COM_RX_SELF_PTL & event)
		{
			/*
			 * self_ptl → MQ_SELF_PTL_TO_COM → com_router:
			 *   解析 stru_msg_head → comm_send
			 */
			stru_app_msg_queue *p_mq = app_get_msg_queue_ptr(ENUM_MQ_SELF_PTL_TO_COM);

			if(NULL != p_mq && NULL != p_mq->p_msg_queue)
			{
				while(0 == task_msg_queue_try_recv(p_mq->p_msg_queue, p_app->rtx.rx, p_mq->msg_size))
				{
					stru_msg_head *p_head = (stru_msg_head *)p_app->rtx.rx;
					int ch_id = (int)(p_head->interface >> 16);
					int fd    = (int)(p_head->interface & 0xFFFF);

					comm_send(ch_id, fd, (const unsigned char *)p_head->data, (int)p_head->len);
				}
			}
		}

		if(EV_TIMER3 & event)
		{
			p_app->run_cnt++;
		}

		if(EV_STOP & event)
		{
			LOG_I("app_com_router: received EV_STOP, exiting");
			break;
		}
	}

	return NULL;
}
