package dailytask

import (
	"strings"
	"time"

	"hyapp-admin-server/internal/appctx"
	"hyapp-admin-server/internal/integration/activityclient"
	"hyapp-admin-server/internal/middleware"
	"hyapp-admin-server/internal/modules/shared"
	"hyapp-admin-server/internal/response"
	activityv1 "hyapp.local/api/proto/activity/v1"

	"github.com/gin-gonic/gin"
)

type Handler struct {
	activity activityclient.Client
	audit    shared.OperationLogger
}

func New(activity activityclient.Client, audit shared.OperationLogger) *Handler {
	return &Handler{activity: activity, audit: audit}
}

type taskRequest struct {
	TaskType              string `json:"task_type"`
	Category              string `json:"category"`
	MetricType            string `json:"metric_type"`
	Title                 string `json:"title"`
	Description           string `json:"description"`
	AudienceType          string `json:"audience_type"`
	IconKey               string `json:"icon_key"`
	IconURL               string `json:"icon_url"`
	ActionType            string `json:"action_type"`
	ActionParam           string `json:"action_param"`
	ActionPayloadJSON     string `json:"action_payload_json"`
	DimensionFilterJSON   string `json:"dimension_filter_json"`
	TargetValue           int64  `json:"target_value"`
	TargetUnit            string `json:"target_unit"`
	RewardType            string `json:"reward_type"`
	RewardCoinAmount      int64  `json:"reward_coin_amount"`
	RewardAssetType       string `json:"reward_asset_type"`
	RewardResourceID      int64  `json:"reward_resource_id"`
	RewardResourceGroupID int64  `json:"reward_resource_group_id"`
	RewardQuantity        int64  `json:"reward_quantity"`
	RewardDurationMS      int64  `json:"reward_duration_ms"`
	Status                string `json:"status"`
	SortOrder             int32  `json:"sort_order"`
	EffectiveFromMS       int64  `json:"effective_from_ms"`
	EffectiveToMS         int64  `json:"effective_to_ms"`
}

type statusRequest struct {
	Status string `json:"status"`
}

type taskDTO struct {
	TaskID                string              `json:"task_id"`
	TaskType              string              `json:"task_type"`
	Category              string              `json:"category"`
	MetricType            string              `json:"metric_type"`
	Title                 string              `json:"title"`
	Description           string              `json:"description"`
	AudienceType          string              `json:"audience_type"`
	IconKey               string              `json:"icon_key"`
	IconURL               string              `json:"icon_url"`
	ActionType            string              `json:"action_type"`
	ActionParam           string              `json:"action_param"`
	ActionPayloadJSON     string              `json:"action_payload_json"`
	DimensionFilterJSON   string              `json:"dimension_filter_json"`
	TargetValue           int64               `json:"target_value"`
	TargetUnit            string              `json:"target_unit"`
	RewardType            string              `json:"reward_type"`
	RewardCoinAmount      int64               `json:"reward_coin_amount"`
	RewardAssetType       string              `json:"reward_asset_type"`
	RewardResourceID      int64               `json:"reward_resource_id"`
	RewardResourceGroupID int64               `json:"reward_resource_group_id"`
	RewardQuantity        int64               `json:"reward_quantity"`
	RewardDurationMS      int64               `json:"reward_duration_ms"`
	RewardItems           []taskRewardItemDTO `json:"reward_items"`
	Status                string              `json:"status"`
	SortOrder             int32               `json:"sort_order"`
	Version               int64               `json:"version"`
	EffectiveFromMS       int64               `json:"effective_from_ms"`
	EffectiveToMS         int64               `json:"effective_to_ms"`
	CreatedByAdminID      int64               `json:"created_by_admin_id"`
	UpdatedByAdminID      int64               `json:"updated_by_admin_id"`
	CreatedAtMS           int64               `json:"created_at_ms"`
	UpdatedAtMS           int64               `json:"updated_at_ms"`
}

type taskRewardItemDTO struct {
	ItemType          string `json:"item_type"`
	ResourceID        int64  `json:"resource_id"`
	ResourceType      string `json:"resource_type"`
	CoverURL          string `json:"cover_url"`
	Quantity          int64  `json:"quantity"`
	DurationMS        int64  `json:"duration_ms"`
	WalletAssetType   string `json:"wallet_asset_type"`
	WalletAssetAmount int64  `json:"wallet_asset_amount"`
}

// ListTaskDefinitions 返回活动管理 > 每日任务页的 daily/exclusive 配置列表。
func (h *Handler) ListTaskDefinitions(c *gin.Context) {
	options := shared.ListOptions(c)
	resp, err := h.activity.ListTaskDefinitions(c.Request.Context(), &activityv1.ListTaskDefinitionsRequest{
		Meta:     h.meta(c),
		TaskType: strings.TrimSpace(firstQuery(c, "task_type", "taskType")),
		Category: strings.TrimSpace(c.Query("category")),
		Status:   options.Status,
		Keyword:  options.Keyword,
		Page:     int32(options.Page),
		PageSize: int32(options.PageSize),
	})
	if err != nil {
		response.ServerError(c, "获取任务列表失败")
		return
	}
	items := make([]taskDTO, 0, len(resp.GetTasks()))
	for _, item := range resp.GetTasks() {
		items = append(items, taskFromProto(item))
	}
	response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
}

// CreateTaskDefinition 创建任务配置；active 任务会立即被 App 查询看到。
func (h *Handler) CreateTaskDefinition(c *gin.Context) {
	var req taskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "任务参数不正确")
		return
	}
	resp, err := h.activity.UpsertTaskDefinition(c.Request.Context(), req.toProto(c, "", h.meta(c)))
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	item := taskFromProto(resp.GetTask())
	h.auditLog(c, "create-daily-task", item.TaskID, item.Title)
	response.Created(c, item)
}

// UpdateTaskDefinition 编辑任务配置；关键字段变更由 activity-service 生成新版本。
func (h *Handler) UpdateTaskDefinition(c *gin.Context) {
	taskID := strings.TrimSpace(c.Param("task_id"))
	if taskID == "" {
		response.BadRequest(c, "ID 参数不正确")
		return
	}
	var req taskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "任务参数不正确")
		return
	}
	resp, err := h.activity.UpsertTaskDefinition(c.Request.Context(), req.toProto(c, taskID, h.meta(c)))
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	item := taskFromProto(resp.GetTask())
	h.auditLog(c, "update-daily-task", item.TaskID, item.Title)
	response.OK(c, item)
}

// SetTaskDefinitionStatus 只做 draft/active/paused/archived 状态流转，不物理删除任务。
func (h *Handler) SetTaskDefinitionStatus(c *gin.Context) {
	taskID := strings.TrimSpace(c.Param("task_id"))
	if taskID == "" {
		response.BadRequest(c, "ID 参数不正确")
		return
	}
	var req statusRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "状态参数不正确")
		return
	}
	resp, err := h.activity.SetTaskDefinitionStatus(c.Request.Context(), &activityv1.SetTaskDefinitionStatusRequest{
		Meta:            h.meta(c),
		TaskId:          taskID,
		Status:          strings.TrimSpace(req.Status),
		OperatorAdminId: int64(middleware.CurrentUserID(c)),
	})
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	item := taskFromProto(resp.GetTask())
	h.auditLog(c, "set-daily-task-status", item.TaskID, item.Status)
	response.OK(c, item)
}

func (r taskRequest) toProto(c *gin.Context, taskID string, meta *activityv1.RequestMeta) *activityv1.UpsertTaskDefinitionRequest {
	// admin-server 只做字段裁剪和身份注入，任务口径校验、JSON 对象校验和版本生成统一放在 activity-service。
	// 图标和跳转属于展示字段，直接透传给任务定义，App 任务页会按 icon_key/icon_url/action_* 渲染。
	return &activityv1.UpsertTaskDefinitionRequest{
		Meta:                  meta,
		TaskId:                taskID,
		TaskType:              strings.TrimSpace(r.TaskType),
		Category:              strings.TrimSpace(r.Category),
		MetricType:            strings.TrimSpace(r.MetricType),
		Title:                 strings.TrimSpace(r.Title),
		Description:           strings.TrimSpace(r.Description),
		AudienceType:          strings.TrimSpace(r.AudienceType),
		IconKey:               strings.TrimSpace(r.IconKey),
		IconUrl:               strings.TrimSpace(r.IconURL),
		ActionType:            strings.TrimSpace(r.ActionType),
		ActionParam:           strings.TrimSpace(r.ActionParam),
		ActionPayloadJson:     strings.TrimSpace(r.ActionPayloadJSON),
		DimensionFilterJson:   strings.TrimSpace(r.DimensionFilterJSON),
		TargetValue:           r.TargetValue,
		TargetUnit:            strings.TrimSpace(r.TargetUnit),
		RewardCoinAmount:      r.RewardCoinAmount,
		RewardAssetType:       strings.TrimSpace(r.RewardAssetType),
		RewardType:            strings.TrimSpace(r.RewardType),
		RewardResourceId:      r.RewardResourceID,
		RewardResourceGroupId: r.RewardResourceGroupID,
		RewardQuantity:        r.RewardQuantity,
		RewardDurationMs:      r.RewardDurationMS,
		Status:                strings.TrimSpace(r.Status),
		SortOrder:             r.SortOrder,
		EffectiveFromMs:       r.EffectiveFromMS,
		EffectiveToMs:         r.EffectiveToMS,
		OperatorAdminId:       int64(middleware.CurrentUserID(c)),
	}
}

func (h *Handler) meta(c *gin.Context) *activityv1.RequestMeta {
	return &activityv1.RequestMeta{
		RequestId: middleware.CurrentRequestID(c),
		Caller:    "admin-server",
		AppCode:   appctx.FromContext(c.Request.Context()),
		SentAtMs:  time.Now().UnixMilli(),
	}
}

func (h *Handler) auditLog(c *gin.Context, action string, taskID string, detail string) {
	if h.audit == nil {
		return
	}
	shared.OperationLogWithResourceID(c, h.audit, action, "task_definitions", taskID, "success", detail)
}

func taskFromProto(item *activityv1.TaskDefinition) taskDTO {
	if item == nil {
		return taskDTO{}
	}
	// 后台列表返回 activity-service 的完整任务定义，保证编辑弹窗能原样带回维度过滤、图标和跳转配置。
	return taskDTO{
		TaskID:                item.GetTaskId(),
		TaskType:              item.GetTaskType(),
		Category:              item.GetCategory(),
		MetricType:            item.GetMetricType(),
		Title:                 item.GetTitle(),
		Description:           item.GetDescription(),
		AudienceType:          item.GetAudienceType(),
		IconKey:               item.GetIconKey(),
		IconURL:               item.GetIconUrl(),
		ActionType:            item.GetActionType(),
		ActionParam:           item.GetActionParam(),
		ActionPayloadJSON:     item.GetActionPayloadJson(),
		DimensionFilterJSON:   item.GetDimensionFilterJson(),
		TargetValue:           item.GetTargetValue(),
		TargetUnit:            item.GetTargetUnit(),
		RewardCoinAmount:      item.GetRewardCoinAmount(),
		RewardAssetType:       item.GetRewardAssetType(),
		RewardType:            item.GetRewardType(),
		RewardResourceID:      item.GetRewardResourceId(),
		RewardResourceGroupID: item.GetRewardResourceGroupId(),
		RewardQuantity:        item.GetRewardQuantity(),
		RewardDurationMS:      item.GetRewardDurationMs(),
		RewardItems:           taskRewardItemsFromProto(item.GetRewardItems()),
		Status:                item.GetStatus(),
		SortOrder:             item.GetSortOrder(),
		Version:               item.GetVersion(),
		EffectiveFromMS:       item.GetEffectiveFromMs(),
		EffectiveToMS:         item.GetEffectiveToMs(),
		CreatedByAdminID:      item.GetCreatedByAdminId(),
		UpdatedByAdminID:      item.GetUpdatedByAdminId(),
		CreatedAtMS:           item.GetCreatedAtMs(),
		UpdatedAtMS:           item.GetUpdatedAtMs(),
	}
}

func taskRewardItemsFromProto(items []*activityv1.TaskRewardItem) []taskRewardItemDTO {
	result := make([]taskRewardItemDTO, 0, len(items))
	for _, item := range items {
		if item == nil {
			continue
		}
		result = append(result, taskRewardItemDTO{
			ItemType:          item.GetItemType(),
			ResourceID:        item.GetResourceId(),
			ResourceType:      item.GetResourceType(),
			CoverURL:          item.GetCoverUrl(),
			Quantity:          item.GetQuantity(),
			DurationMS:        item.GetDurationMs(),
			WalletAssetType:   item.GetWalletAssetType(),
			WalletAssetAmount: item.GetWalletAssetAmount(),
		})
	}
	return result
}

func firstQuery(c *gin.Context, keys ...string) string {
	for _, key := range keys {
		if value := c.Query(key); value != "" {
			return value
		}
	}
	return ""
}
