package handler

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"git.yeij.top/AskaEth/Cyrene/pkg/logger"
	"net/http"

	"github.com/gin-gonic/gin"

	"git.yeij.top/AskaEth/Cyrene/gateway/internal/engine"
	"git.yeij.top/AskaEth/Cyrene/gateway/internal/middleware"
	"git.yeij.top/AskaEth/Cyrene/gateway/internal/store"
)

// AutomationHandler 自动化处理器
type AutomationHandler struct {
	store  *store.AutomationStore
	engine *engine.RuleEngine
}

// NewAutomationHandler 创建自动化处理器
func NewAutomationHandler(s *store.AutomationStore, e *engine.RuleEngine) *AutomationHandler {
	return &AutomationHandler{store: s, engine: e}
}

// ========== 请求/响应体 ==========

// CreateRuleRequest 创建规则请求
type CreateRuleRequest struct {
	Name        string           `json:"name" binding:"required"`
	Description string           `json:"description"`
	TriggerType string           `json:"trigger_type" binding:"required"`
	TriggerConfig json.RawMessage `json:"trigger_config"`
	Conditions   json.RawMessage `json:"conditions"`
	Actions      json.RawMessage `json:"actions" binding:"required"`
	Enabled      *bool           `json:"enabled"`
}

// UpdateRuleRequest 更新规则请求
type UpdateRuleRequest struct {
	Name        *string          `json:"name"`
	Description *string          `json:"description"`
	TriggerType *string          `json:"trigger_type"`
	TriggerConfig *json.RawMessage `json:"trigger_config"`
	Conditions   *json.RawMessage  `json:"conditions"`
	Actions      *json.RawMessage  `json:"actions"`
	Enabled      *bool            `json:"enabled"`
}

// CreateSceneRequest 创建场景请求
type CreateSceneRequest struct {
	Name    string          `json:"name" binding:"required"`
	Icon    string          `json:"icon"`
	RuleIDs json.RawMessage `json:"rule_ids"`
}

// UpdateSceneRequest 更新场景请求
type UpdateSceneRequest struct {
	Name    *string          `json:"name"`
	Icon    *string          `json:"icon"`
	RuleIDs *json.RawMessage `json:"rule_ids"`
}

// ========== Rule Handlers ==========

// ListRules 获取用户的所有规则
// GET /api/v1/automation/rules
func (h *AutomationHandler) ListRules(c *gin.Context) {
	userID := middleware.GetUserID(c)
	if userID == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	rules, err := h.store.GetRulesByUser(userID)
	if err != nil {
		logger.Printf("[automation] 获取规则列表失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则列表失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"rules": rules,
		"count": len(rules),
	})
}

// CreateRule 创建规则
// POST /api/v1/automation/rules
func (h *AutomationHandler) CreateRule(c *gin.Context) {
	userID := middleware.GetUserID(c)
	if userID == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	var req CreateRuleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效: " + err.Error()})
		return
	}

	triggerConfig := ensureRawMessage(req.TriggerConfig)
	conditions := ensureRawMessage(req.Conditions)
	actions := ensureRawMessage(req.Actions)

	enabled := true
	if req.Enabled != nil {
		enabled = *req.Enabled
	}

	rule := &store.AutomationRule{
		ID:            randomHexID(),
		UserID:        userID,
		Name:          req.Name,
		Description:   req.Description,
		TriggerType:   req.TriggerType,
		TriggerConfig: triggerConfig,
		Conditions:    conditions,
		Actions:       actions,
		Enabled:       enabled,
	}

	if err := h.store.CreateRule(rule); err != nil {
		logger.Printf("[automation] 创建规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建规则失败"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"success": true,
		"rule":    rule,
	})
}

// GetRule 获取单条规则
func (h *AutomationHandler) GetRule(c *gin.Context) {
	id := c.Param("id")
	rule, err := h.store.GetRule(id)
	if err != nil {
		logger.Printf("[automation] 获取规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
		return
	}
	if rule == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "规则不存在"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"rule": rule})
}

// UpdateRule 更新规则
// PUT /api/v1/automation/rules/:id
func (h *AutomationHandler) UpdateRule(c *gin.Context) {
	userID := middleware.GetUserID(c)
	id := c.Param("id")

	// 先获取规则验证所有权
	existing, err := h.store.GetRule(id)
	if err != nil {
		logger.Printf("[automation] 获取规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
		return
	}
	if existing == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "规则不存在"})
		return
	}
	if existing.UserID != userID {
		c.JSON(http.StatusForbidden, gin.H{"error": "无权修改此规则"})
		return
	}

	var req UpdateRuleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效: " + err.Error()})
		return
	}

	// 只更新提供的字段
	if req.Name != nil {
		existing.Name = *req.Name
	}
	if req.Description != nil {
		existing.Description = *req.Description
	}
	if req.TriggerType != nil {
		existing.TriggerType = *req.TriggerType
	}
	if req.TriggerConfig != nil {
		existing.TriggerConfig = req.TriggerConfig
	}
	if req.Conditions != nil {
		existing.Conditions = req.Conditions
	}
	if req.Actions != nil {
		existing.Actions = req.Actions
	}
	if req.Enabled != nil {
		existing.Enabled = *req.Enabled
	}

	if err := h.store.UpdateRule(existing); err != nil {
		logger.Printf("[automation] 更新规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新规则失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"rule":    existing,
	})
}

// DeleteRule 删除规则
// DELETE /api/v1/automation/rules/:id
func (h *AutomationHandler) DeleteRule(c *gin.Context) {
	userID := middleware.GetUserID(c)
	id := c.Param("id")

	existing, err := h.store.GetRule(id)
	if err != nil {
		logger.Printf("[automation] 获取规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
		return
	}
	if existing == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "规则不存在"})
		return
	}
	if existing.UserID != userID {
		c.JSON(http.StatusForbidden, gin.H{"error": "无权删除此规则"})
		return
	}

	if err := h.store.DeleteRule(id); err != nil {
		logger.Printf("[automation] 删除规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除规则失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"success": true})
}

// TriggerRule 手动触发单条规则
// POST /api/v1/automation/rules/:id/trigger
func (h *AutomationHandler) TriggerRule(c *gin.Context) {
	userID := middleware.GetUserID(c)
	id := c.Param("id")

	rule, err := h.store.GetRule(id)
	if err != nil {
		logger.Printf("[automation] 获取规则失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
		return
	}
	if rule == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "规则不存在"})
		return
	}
	if rule.UserID != userID {
		c.JSON(http.StatusForbidden, gin.H{"error": "无权触发此规则"})
		return
	}

	h.engine.ExecuteRuleActions(rule)
	h.store.MarkRuleTriggered(id)

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "规则已触发",
	})
}

// ========== Scene Handlers ==========

// ListScenes 获取所有场景
// GET /api/v1/automation/scenes
func (h *AutomationHandler) ListScenes(c *gin.Context) {
	userID := middleware.GetUserID(c)
	if userID == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	scenes, err := h.store.GetScenesByUser(userID)
	if err != nil {
		logger.Printf("[automation] 获取场景列表失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景列表失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"scenes": scenes,
		"count":  len(scenes),
	})
}

// CreateScene 创建场景
// POST /api/v1/automation/scenes
func (h *AutomationHandler) CreateScene(c *gin.Context) {
	userID := middleware.GetUserID(c)
	if userID == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	var req CreateSceneRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效: " + err.Error()})
		return
	}

	ruleIDs := ensureRawMessage(req.RuleIDs)

	scene := &store.AutomationScene{
		ID:      randomHexID(),
		UserID:  userID,
		Name:    req.Name,
		Icon:    req.Icon,
		RuleIDs: ruleIDs,
	}

	if err := h.store.CreateScene(scene); err != nil {
		logger.Printf("[automation] 创建场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建场景失败"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"success": true,
		"scene":   scene,
	})
}

// GetScene 获取单个场景
func (h *AutomationHandler) GetScene(c *gin.Context) {
	id := c.Param("id")
	scene, err := h.store.GetScene(id)
	if err != nil {
		logger.Printf("[automation] 获取场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
		return
	}
	if scene == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "场景不存在"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"scene": scene})
}

// UpdateScene 更新场景
// PUT /api/v1/automation/scenes/:id
func (h *AutomationHandler) UpdateScene(c *gin.Context) {
	userID := middleware.GetUserID(c)
	id := c.Param("id")

	existing, err := h.store.GetScene(id)
	if err != nil {
		logger.Printf("[automation] 获取场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
		return
	}
	if existing == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "场景不存在"})
		return
	}
	if existing.UserID != userID {
		c.JSON(http.StatusForbidden, gin.H{"error": "无权修改此场景"})
		return
	}

	var req UpdateSceneRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效: " + err.Error()})
		return
	}

	if req.Name != nil {
		existing.Name = *req.Name
	}
	if req.Icon != nil {
		existing.Icon = *req.Icon
	}
	if req.RuleIDs != nil {
		existing.RuleIDs = req.RuleIDs
	}

	if err := h.store.UpdateScene(existing); err != nil {
		logger.Printf("[automation] 更新场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新场景失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"scene":   existing,
	})
}

// DeleteScene 删除场景
// DELETE /api/v1/automation/scenes/:id
func (h *AutomationHandler) DeleteScene(c *gin.Context) {
	userID := middleware.GetUserID(c)
	id := c.Param("id")

	existing, err := h.store.GetScene(id)
	if err != nil {
		logger.Printf("[automation] 获取场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
		return
	}
	if existing == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "场景不存在"})
		return
	}
	if existing.UserID != userID {
		c.JSON(http.StatusForbidden, gin.H{"error": "无权删除此场景"})
		return
	}

	if err := h.store.DeleteScene(id); err != nil {
		logger.Printf("[automation] 删除场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除场景失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"success": true})
}

// ExecuteScene 手动执行场景
// POST /api/v1/automation/scenes/:id/execute
func (h *AutomationHandler) ExecuteScene(c *gin.Context) {
	id := c.Param("id")

	// 验证场景存在
	scene, err := h.store.GetScene(id)
	if err != nil {
		logger.Printf("[automation] 获取场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
		return
	}
	if scene == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "场景不存在"})
		return
	}

	userID := middleware.GetUserID(c)

	if err := h.engine.ExecuteScene(id, userID); err != nil {
		logger.Printf("[automation] 执行场景失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "执行场景失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "场景已执行",
	})
}

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

// randomHexID 使用 crypto/rand 生成 16 字节 hex ID
func randomHexID() string {
	b := make([]byte, 16)
	rand.Read(b)
	return hex.EncodeToString(b)
}

// ensureRawMessage 确保 json.RawMessage 非空
func ensureRawMessage(raw json.RawMessage) *json.RawMessage {
	if len(raw) == 0 {
		return nil
	}
	result := make(json.RawMessage, len(raw))
	copy(result, raw)
	return &result
}
