package wallet

import (
	"context"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
	"strings"
	"time"
)

// ProcessHostSalarySettlementBatch 执行主播/代理工资结算批处理；日结和半月结不清空周期钻石，月底只做逻辑清算标记。
func (s *Service) ProcessHostSalarySettlementBatch(ctx context.Context, command ledger.HostSalarySettlementBatchCommand) (ledger.HostSalarySettlementBatchResult, error) {
	if s.repository == nil {
		return ledger.HostSalarySettlementBatchResult{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	switch strings.TrimSpace(command.SettlementType) {
	case ledger.HostSalarySettlementModeDaily, ledger.HostSalarySettlementModeHalfMonth, ledger.HostSalarySettlementTypeMonthEnd:
	default:
		return ledger.HostSalarySettlementBatchResult{}, xerr.New(xerr.InvalidArgument, "settlement_type is invalid")
	}
	if command.BatchSize <= 0 {
		command.BatchSize = 100
	}
	if command.BatchSize > 500 {
		command.BatchSize = 500
	}
	if strings.TrimSpace(command.RunID) == "" || strings.TrimSpace(command.WorkerID) == "" {
		return ledger.HostSalarySettlementBatchResult{}, xerr.New(xerr.InvalidArgument, "run_id and worker_id are required")
	}
	command.AppCode = appcode.Normalize(command.AppCode)
	if command.NowMs <= 0 {
		command.NowMs = s.now().UTC().UnixMilli()
	}
	if strings.TrimSpace(command.CycleKey) == "" {
		command.CycleKey = hostSalaryCycleKey(command.NowMs)
	}
	if !validHostSalaryCycleKey(command.CycleKey) {
		return ledger.HostSalarySettlementBatchResult{}, xerr.New(xerr.InvalidArgument, "cycle_key must use YYYY-MM")
	}
	ctx = appcode.WithContext(ctx, command.AppCode)
	return s.repository.ProcessHostSalarySettlementBatch(ctx, command)
}

func hostSalaryCycleKey(nowMs int64) string {
	// 结算周期按 UTC 月锚定，和送礼入账的 host_period_diamond_accounts.cycle_key 保持同一口径。
	return time.UnixMilli(nowMs).UTC().Format("2006-01")
}

func validHostSalaryCycleKey(cycleKey string) bool {
	cycleKey = strings.TrimSpace(cycleKey)
	if len(cycleKey) != len("2006-01") {
		return false
	}
	parsed, err := time.Parse("2006-01", cycleKey)
	return err == nil && parsed.UTC().Format("2006-01") == cycleKey
}

// GetActiveHostSalaryPolicy 按工资周期读取主播所在区域已绑定的不可变政策版本。
func (s *Service) GetActiveHostSalaryPolicy(ctx context.Context, appCode string, regionID int64, settlementMode string, triggerMode string, cycleKey string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) {
	if regionID <= 0 {
		return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "region_id is required")
	}
	if s.repository == nil {
		return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	settlementMode = strings.TrimSpace(settlementMode)
	if settlementMode != "" && settlementMode != ledger.HostSalarySettlementModeDaily && settlementMode != ledger.HostSalarySettlementModeHalfMonth {
		return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "settlement_mode is invalid")
	}
	triggerMode = strings.TrimSpace(triggerMode)
	if triggerMode != "" && triggerMode != ledger.HostSalarySettlementTriggerAutomatic && triggerMode != ledger.HostSalarySettlementTriggerManual {
		return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "settlement_trigger_mode is invalid")
	}
	if nowMs <= 0 {
		nowMs = s.now().UTC().UnixMilli()
	}
	cycleKey = strings.TrimSpace(cycleKey)
	if cycleKey == "" {
		// 旧 H5 未传周期时只允许展示层回退当前 UTC 月；结算批次始终显式携带自己的 cycle_key。
		cycleKey = hostSalaryCycleKey(nowMs)
	}
	if !validHostSalaryCycleKey(cycleKey) {
		return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "cycle_key must use YYYY-MM")
	}
	appCode = appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, appCode)
	// H5 展示可以不传 trigger mode，此时 automatic/manual 政策都可展示；结算任务仍会传具体 trigger 精确匹配。
	return s.repository.GetActiveHostSalaryPolicy(ctx, regionID, settlementMode, triggerMode, cycleKey)
}

// GetTeamHostSalaryStats 聚合一组 Agency 收款人名下主播的预收入工资，经理中心团队工资卡片使用。
// 收款人集合为空时按空团队返回零值统计，不视为错误；周期数和收款人数设防御上限避免误用打出超大 IN 查询。
func (s *Service) GetTeamHostSalaryStats(ctx context.Context, appCode string, query ledger.TeamHostSalaryStatsQuery) ([]ledger.TeamHostSalaryCycleStat, error) {
	if s.repository == nil {
		return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	if len(query.CycleKeys) == 0 || len(query.CycleKeys) > 12 {
		return nil, xerr.New(xerr.InvalidArgument, "cycle_keys must contain 1 to 12 entries")
	}
	if len(query.AgencyOwnerUserIDs) > 10000 {
		return nil, xerr.New(xerr.InvalidArgument, "agency_owner_user_ids is too large")
	}
	if query.NowMs <= 0 {
		query.NowMs = s.now().UTC().UnixMilli()
	}
	appCode = appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, appCode)
	return s.repository.GetTeamHostSalaryStats(ctx, query)
}

// GetHostSalaryProgress 返回主播当前工资周期的钻石累计；没有收礼账户时返回 0，避免 H5 用其他等级系统兜底导致进度口径错误。
func (s *Service) GetHostSalaryProgress(ctx context.Context, appCode string, userID int64, cycleKey string, nowMs int64) (ledger.HostSalaryProgress, error) {
	if userID <= 0 {
		return ledger.HostSalaryProgress{}, xerr.New(xerr.InvalidArgument, "host_user_id is required")
	}
	if s.repository == nil {
		return ledger.HostSalaryProgress{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	if nowMs <= 0 {
		nowMs = s.now().UTC().UnixMilli()
	}
	cycleKey = strings.TrimSpace(cycleKey)
	if cycleKey == "" {
		cycleKey = hostSalaryCycleKey(nowMs)
	}
	appCode = appcode.Normalize(appCode)
	ctx = appcode.WithContext(ctx, appCode)
	return s.repository.GetHostSalaryProgress(ctx, userID, cycleKey)
}
