package exporter

import (
	"context"
	"time"

	"gorm.io/gorm"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
)

// AgentRechargeDataSource 代理充值导出数据源。
type AgentRechargeDataSource struct {
	db *gorm.DB
}

// NewAgentRechargeDataSource 创建代理充值导出数据源。
func NewAgentRechargeDataSource(db *gorm.DB) *AgentRechargeDataSource {
	return &AgentRechargeDataSource{db: db}
}

// Scene 返回导出场景编码。
func (s *AgentRechargeDataSource) Scene() string {
	return constants.ExportTaskSceneAgentRecharge
}

// Count 统计代理充值导出行数。
func (s *AgentRechargeDataSource) Count(ctx context.Context, params ExportParams) (int, error) {
	var total int64
	query := s.applyFilters(s.baseQuery(ctx), params)
	if err := query.Count(&total).Error; err != nil {
		return 0, err
	}
	return int(total), nil
}

// Headers 返回代理充值导出表头。
func (s *AgentRechargeDataSource) Headers(context.Context, ExportParams) ([]string, error) {
	return []string{
		"充值单号", "店铺名称", "充值类型", "充值金额(元)", "实付金额(元)", "充值前余额(元)", "充值后余额(元)",
		"状态", "支付方式", "运营备注", "驳回原因", "创建时间", "支付时间", "完成时间", "提交人", "审批来源", "审批状态", "支付凭证",
	}, nil
}

// Fetch 按 offset/limit 查询代理充值导出数据。
func (s *AgentRechargeDataSource) Fetch(ctx context.Context, params ExportParams, offset, limit int) ([][]string, error) {
	if limit <= 0 {
		return [][]string{}, nil
	}

	var items []agentRechargeExportRow
	query := s.applyFilters(s.baseQuery(ctx), params).
		Select(`
			r.recharge_no,
			r.amount,
			r.payment_method,
			r.status,
			r.remark,
			COALESCE(r.rejection_reason, '') AS rejection_reason,
			r.created_at,
			r.paid_at,
			r.completed_at,
			COALESCE(sh.shop_name, '') AS shop_name,
			COALESCE(ac.username, '') AS submitter_name,
			ai.provider AS approval_provider,
			ai.status AS approval_status,
			wt.amount AS actual_amount,
			wt.balance_before,
			wt.balance_after,
			COALESCE((SELECT string_agg(voucher.value, ',' ORDER BY voucher.ordinality)
				FROM jsonb_array_elements_text(COALESCE(r.payment_voucher_key, '[]'::jsonb)) WITH ORDINALITY AS voucher(value, ordinality)), '') AS voucher_keys
		`).
		Joins("LEFT JOIN tb_shop AS sh ON sh.id = r.shop_id").
		Joins("LEFT JOIN tb_account AS ac ON ac.id = r.user_id").
		Joins("LEFT JOIN tb_approval_instance AS ai ON ai.id = r.approval_instance_id").
		Joins(`LEFT JOIN LATERAL (
			SELECT t.amount, t.balance_before, t.balance_after
			FROM tb_agent_wallet_transaction AS t
			WHERE t.reference_type = ?
				AND t.reference_id = r.id
				AND t.transaction_type = ?
				AND t.status = ?
				AND t.deleted_at IS NULL
			ORDER BY t.id ASC
			LIMIT 1
		) AS wt ON TRUE`, constants.ReferenceTypeTopup, constants.AgentTransactionTypeRecharge, constants.TransactionStatusSuccess).
		Order("r.id ASC").
		Limit(limit).
		Offset(offset)
	if err := query.Scan(&items).Error; err != nil {
		return nil, err
	}

	rows := make([][]string, 0, len(items))
	for _, item := range items {
		rows = append(rows, []string{
			item.RechargeNo,
			item.ShopName,
			formatRechargeType(item.PaymentMethod),
			formatMoneyYuan(item.Amount),
			formatOptionalMoneyYuan(item.ActualAmount),
			formatOptionalMoneyYuan(item.BalanceBefore),
			formatOptionalMoneyYuan(item.BalanceAfter),
			constants.GetRechargeStatusName(item.Status),
			constants.GetBusinessPaymentMethodName(item.PaymentMethod),
			item.Remark,
			item.RejectionReason,
			item.CreatedAt.Format(exportTimeLayout),
			formatOptionalTime(item.PaidAt),
			formatOptionalTime(item.CompletedAt),
			item.SubmitterName,
			formatApprovalProvider(item.ApprovalProvider),
			formatOptionalApprovalStatus(item.ApprovalStatus),
			item.VoucherKeys,
		})
	}
	return rows, nil
}

func (s *AgentRechargeDataSource) baseQuery(ctx context.Context) *gorm.DB {
	return s.db.WithContext(ctx).Table("tb_agent_recharge_record AS r").Where("r.deleted_at IS NULL")
}

func (s *AgentRechargeDataSource) applyFilters(query *gorm.DB, params ExportParams) *gorm.DB {
	query = applyExportShopScope(query, params, "r.shop_id")
	if shopID, ok := filterUint(params.Filters, "shop_id"); ok {
		query = query.Where("r.shop_id = ?", shopID)
	}
	if status, ok := filterInt(params.Filters, "status"); ok {
		query = query.Where("r.status = ?", status)
	}
	if start, ok := filterTime(params.Filters, "start_date"); ok {
		query = query.Where("r.created_at >= ?", start)
	}
	if end, ok := filterEndDate(params.Filters, "end_date"); ok {
		query = query.Where("r.created_at <= ?", end)
	}
	return query
}

type agentRechargeExportRow struct {
	RechargeNo       string     `gorm:"column:recharge_no"`
	ShopName         string     `gorm:"column:shop_name"`
	Amount           int64      `gorm:"column:amount"`
	ActualAmount     *int64     `gorm:"column:actual_amount"`
	BalanceBefore    *int64     `gorm:"column:balance_before"`
	BalanceAfter     *int64     `gorm:"column:balance_after"`
	PaymentMethod    string     `gorm:"column:payment_method"`
	Status           int        `gorm:"column:status"`
	Remark           string     `gorm:"column:remark"`
	RejectionReason  string     `gorm:"column:rejection_reason"`
	CreatedAt        time.Time  `gorm:"column:created_at"`
	PaidAt           *time.Time `gorm:"column:paid_at"`
	CompletedAt      *time.Time `gorm:"column:completed_at"`
	SubmitterName    string     `gorm:"column:submitter_name"`
	ApprovalProvider *string    `gorm:"column:approval_provider"`
	ApprovalStatus   *int       `gorm:"column:approval_status"`
	VoucherKeys      string     `gorm:"column:voucher_keys"`
}

func formatRechargeType(paymentMethod string) string {
	if paymentMethod == constants.RechargeMethodOffline {
		return "员工线下代充值"
	}
	return "在线充值"
}

func formatOptionalMoneyYuan(value *int64) string {
	if value == nil {
		return ""
	}
	return formatMoneyYuan(*value)
}

func formatApprovalProvider(provider *string) string {
	if provider == nil || *provider == "" {
		return ""
	}
	if *provider == constants.IntegrationProviderWeCom {
		return "企业微信"
	}
	return *provider
}

func formatOptionalApprovalStatus(status *int) string {
	if status == nil {
		return ""
	}
	return constants.GetApprovalStatusName(*status)
}
