package web

type graphNodeParam struct {
	Key         string   `json:"key"`
	Label       string   `json:"label"`
	Type        string   `json:"type"`
	Step        string   `json:"step,omitempty"`
	Placeholder string   `json:"placeholder,omitempty"`
	Options     []string `json:"options,omitempty"`
}

type graphNodeTypeInfo struct {
	Type        string           `json:"type"`
	Label       string           `json:"label"`
	Category    string           `json:"category"`
	Icon        string           `json:"icon"`
	Description string           `json:"description"`
	Defaults    map[string]any   `json:"defaults"`
	Params      []graphNodeParam `json:"params,omitempty"`
}

func graphNodeTypesCatalog() []graphNodeTypeInfo {
	return []graphNodeTypeInfo{
		nodeType("input_rtsp", "RTSP 输入", "输入", "camera", "从网络摄像机或流媒体地址读取视频流。", "source", map[string]any{"url": "${slot:video_input_main.url}"}, []graphNodeParam{
			textParam("url", "RTSP 地址", "${slot:video_input_main.url}"),
			numberParam("fps", "输入帧率", "1"),
			numberParam("width", "宽度", "1"),
			numberParam("height", "高度", "1"),
			boolParam("force_tcp", "强制 TCP"),
			numberParam("reconnect_sec", "重连间隔秒", "1"),
		}),
		nodeType("input_file", "文件输入", "输入", "file", "从本地视频文件读取帧，常用于离线验证和回放。", "source", nil, []graphNodeParam{
			textParam("path", "文件路径", ""),
			numberParam("fps", "回放帧率", "1"),
			boolParam("loop", "循环播放"),
		}),
		nodeType("preprocess", "图像预处理", "处理", "adjust", "调整尺寸、格式和硬件加速路径，为后续推理或编码准备图像。", "filter", map[string]any{"dst_format": "rgb"}, []graphNodeParam{
			numberParam("dst_w", "输出宽度", "1"),
			numberParam("dst_h", "输出高度", "1"),
			selectParam("dst_format", "输出格式", []string{"rgb", "nv12", "bgr"}),
			selectParam("resize_mode", "缩放方式", []string{"stretch", "letterbox"}),
			boolParam("use_rga", "使用 RGA"),
			textParam("rga_gate", "RGA 通道", ""),
		}),
		nodeType("ai_scrfd", "SCRFD 人脸检测", "AI 推理", "scan-face", "使用 SCRFD 模型做人脸检测，适合固定输入尺寸场景。", "filter", nil, faceDetParams()),
		nodeType("ai_scrfd_sliding", "滑窗人脸检测", "AI 推理", "scan-face", "使用滑窗方式执行 SCRFD 人脸检测，适合高分辨率画面。", "filter", nil, faceDetParams()),
		nodeType("ai_face_det", "人脸检测", "AI 推理", "face", "通用人脸检测节点，输出人脸框和质量信息。", "filter", nil, faceDetParams()),
		nodeType("ai_face_recog", "人脸识别", "AI 推理", "face-id", "对检测到的人脸进行特征提取和人脸库匹配。", "filter", nil, []graphNodeParam{
			textParam("model_path", "模型路径", ""),
			numberParam("infer_fps", "推理帧率", "0.1"),
			boolParam("align", "人脸对齐"),
			boolParam("emit_embedding", "输出特征"),
			numberParam("max_faces", "最大人脸数", "1"),
		}),
		nodeType("ai_yolo", "YOLO 目标检测", "AI 推理", "target", "使用 YOLO 模型检测人员、PPE 或其他目标。", "filter", nil, []graphNodeParam{
			textParam("model_path", "模型路径", ""),
			numberParam("infer_fps", "推理帧率", "0.1"),
			numberParam("model_w", "模型宽度", "1"),
			numberParam("model_h", "模型高度", "1"),
			numberParam("conf", "置信度", "0.01"),
			numberParam("nms", "NMS", "0.01"),
		}),
		nodeType("ai_shoe_det", "鞋靴检测", "AI 推理", "shoe", "检测鞋靴和工鞋相关目标，可配合逻辑节点判断违规。", "filter", nil, []graphNodeParam{
			textParam("model_path", "模型路径", ""),
			numberParam("infer_fps", "推理帧率", "0.1"),
			numberParam("conf", "置信度", "0.01"),
			numberParam("nms", "NMS", "0.01"),
			boolParam("append_detections", "追加检测结果"),
		}),
		nodeType("tracker", "目标跟踪", "处理", "route", "对检测目标分配跟踪 ID，保持跨帧目标状态。", "filter", nil, []graphNodeParam{
			textParam("mode", "跟踪模式", ""),
			boolParam("per_class", "按类别跟踪"),
			numberParam("high_th", "高阈值", "0.01"),
			numberParam("low_th", "低阈值", "0.01"),
			numberParam("iou_th", "IOU 阈值", "0.01"),
			numberParam("max_age_ms", "最大保留毫秒", "1"),
		}),
		nodeType("logic_gate", "规则判断", "规则", "branch", "根据检测、跟踪或颜色分析结果进行业务规则判断。", "filter", nil, []graphNodeParam{
			textParam("mode", "逻辑模式", ""),
			boolParam("debug", "调试输出"),
			numberParam("anchor_class", "锚点类别", "1"),
			numberParam("boots_class", "鞋靴类别", "1"),
			numberParam("violation_class", "违规类别", "1"),
		}),
		nodeType("event_fusion", "事件融合", "规则", "merge", "融合多路事件，减少重复告警并形成更稳定的业务事件。", "filter", nil, nil),
		nodeType("region_event", "区域事件", "规则", "region", "基于区域、越线或停留规则生成区域行为事件。", "filter", nil, nil),
		nodeType("action_recog", "行为识别", "AI 推理", "activity", "识别人员行为或动作事件。", "filter", nil, nil),
		nodeType("det_post", "检测后处理", "处理", "filter", "对检测结果做过滤、映射、合并或类别转换。", "filter", nil, nil),
		nodeType("osd", "画面叠加", "输出", "overlay", "在视频帧上绘制检测框、文字、人脸识别和事件信息。", "filter", nil, []graphNodeParam{
			boolParam("draw_bbox", "绘制框"),
			boolParam("draw_text", "绘制文字"),
			boolParam("draw_face_det", "绘制人脸检测"),
			boolParam("draw_face_recog", "绘制人脸识别"),
			numberParam("line_width", "线宽", "0.1"),
			numberParam("font_scale", "字体缩放", "0.1"),
		}),
		nodeType("publish", "视频输出", "输出", "broadcast", "编码并发布 RTSP、HLS 或其他视频输出。", "sink", nil, []graphNodeParam{
			selectParam("codec", "编码", []string{"h264", "h265"}),
			numberParam("fps", "输出帧率", "1"),
			numberParam("gop", "GOP", "1"),
			numberParam("bitrate_kbps", "码率 kbps", "1"),
			boolParam("use_mpp", "使用 MPP"),
			boolParam("use_ffmpeg_mux", "FFmpeg 封装"),
		}),
		nodeType("storage", "本地存储", "输出", "database", "保存帧、事件或中间结果到本地存储。", "sink", nil, nil),
		nodeType("alarm", "告警动作", "输出", "bell", "根据规则触发日志、抓图、录像片段、外部接口等动作。", "sink", nil, []graphNodeParam{
			numberParam("eval_fps", "评估帧率", "0.1"),
		}),
		nodeType("gate", "流控闸门", "系统", "gate", "控制流程分支或限流，保护下游节点。", "filter", nil, nil),
		nodeType("zlm_http", "ZLMediaKit HTTP", "系统", "server", "提供 ZLMediaKit 相关 HTTP 文件服务能力。", "sink", nil, nil),
	}
}

func nodeType(t, label, category, icon, description, role string, defaults map[string]any, params []graphNodeParam) graphNodeTypeInfo {
	if defaults == nil {
		defaults = map[string]any{}
	}
	defaults["id"] = t
	defaults["type"] = t
	defaults["role"] = role
	defaults["enable"] = true
	return graphNodeTypeInfo{Type: t, Label: label, Category: category, Icon: icon, Description: description, Defaults: defaults, Params: params}
}

func textParam(key, label, placeholder string) graphNodeParam {
	return graphNodeParam{Key: key, Label: label, Type: "text", Placeholder: placeholder}
}

func numberParam(key, label, step string) graphNodeParam {
	return graphNodeParam{Key: key, Label: label, Type: "number", Step: step}
}

func boolParam(key, label string) graphNodeParam {
	return graphNodeParam{Key: key, Label: label, Type: "boolean"}
}

func selectParam(key, label string, options []string) graphNodeParam {
	return graphNodeParam{Key: key, Label: label, Type: "select", Options: options}
}

func faceDetParams() []graphNodeParam {
	return []graphNodeParam{
		textParam("model_path", "模型路径", ""),
		numberParam("infer_fps", "推理帧率", "0.1"),
		numberParam("model_w", "模型宽度", "1"),
		numberParam("model_h", "模型高度", "1"),
		numberParam("conf_thresh", "置信度", "0.01"),
		numberParam("nms_thresh", "NMS", "0.01"),
		numberParam("max_faces", "最大人脸数", "1"),
	}
}

func knownGraphNodeTypes() map[string]bool {
	out := map[string]bool{}
	for _, item := range graphNodeTypesCatalog() {
		out[item.Type] = true
	}
	return out
}
