package financewithdrawal

import "hyapp-admin-server/internal/model"

type withdrawalApplicationDTO struct {
	ID                           uint    `json:"id"`
	AppCode                      string  `json:"appCode"`
	AppName                      string  `json:"appName"`
	SourceSystem                 string  `json:"sourceSystem"`
	SourceApplicationID          string  `json:"sourceApplicationId"`
	UserID                       string  `json:"userId"`
	SalaryAssetType              string  `json:"salaryAssetType"`
	WithdrawAmount               string  `json:"withdrawAmount"`
	WithdrawAmountMinor          int64   `json:"withdrawAmountMinor"`
	BalanceBefore                *string `json:"balanceBefore"`
	ServiceChargeRatio           *string `json:"serviceChargeRatio"`
	ServiceCharge                *string `json:"serviceCharge"`
	ActualAmount                 *string `json:"actualAmount"`
	ActualAmountMinor            *int64  `json:"actualAmountMinor"`
	ExternalFinanceClaimDecision *string `json:"externalFinanceClaimDecision"`
	ExternalFinanceClaimStatus   *string `json:"externalFinanceClaimStatus"`
	PointGrossAmount             int64   `json:"pointGrossAmount,omitempty"`
	PointFeeAmount               int64   `json:"pointFeeAmount,omitempty"`
	PointNetAmount               int64   `json:"pointNetAmount,omitempty"`
	PointsPerUSD                 int64   `json:"pointsPerUsd,omitempty"`
	PointFeeBPS                  int32   `json:"pointFeeBps,omitempty"`
	PointPolicyInstance          string  `json:"pointPolicyInstanceCode,omitempty"`
	WithdrawMethod               string  `json:"withdrawMethod"`
	WithdrawAddress              string  `json:"withdrawAddress"`
	FreezeTransactionID          string  `json:"freezeTransactionId"`
	AuditTransactionID           string  `json:"auditTransactionId"`
	Status                       string  `json:"status"`
	ApproverUserID               *uint   `json:"approverUserId"`
	ApproverName                 string  `json:"approverName"`
	AuditRemark                  string  `json:"auditRemark"`
	AuditImageURL                string  `json:"auditImageUrl"`
	ApprovedAtMS                 *int64  `json:"approvedAtMs"`
	OperationsStatus             string  `json:"operationsStatus"`
	OperationsReviewerUserID     *uint   `json:"operationsReviewerUserId"`
	OperationsReviewerName       string  `json:"operationsReviewerName"`
	OperationsAuditRemark        string  `json:"operationsAuditRemark"`
	OperationsAuditTransactionID string  `json:"operationsAuditTransactionId"`
	OperationsReviewedAtMS       *int64  `json:"operationsReviewedAtMs"`
	CreatedAtMS                  int64   `json:"createdAtMs"`
	UpdatedAtMS                  int64   `json:"updatedAtMs"`
}

func withdrawalApplicationDTOFromModel(item model.UserWithdrawalApplication) withdrawalApplicationDTO {
	dto := withdrawalApplicationDTO{
		ID:                           item.ID,
		AppCode:                      item.AppCode,
		AppName:                      item.AppCode,
		SourceSystem:                 item.SourceSystem,
		SourceApplicationID:          item.SourceApplicationID,
		UserID:                       item.UserID,
		SalaryAssetType:              item.SalaryAssetType,
		WithdrawAmount:               item.WithdrawAmount,
		WithdrawAmountMinor:          item.WithdrawAmountMinor,
		BalanceBefore:                item.BalanceBefore,
		ServiceChargeRatio:           item.ServiceChargeRatio,
		ServiceCharge:                item.ServiceCharge,
		ActualAmount:                 item.ActualAmount,
		ActualAmountMinor:            item.ActualAmountMinor,
		ExternalFinanceClaimDecision: item.ExternalFinanceClaimDecision,
		ExternalFinanceClaimStatus:   item.ExternalFinanceClaimStatus,
		WithdrawMethod:               item.WithdrawMethod,
		WithdrawAddress:              item.WithdrawAddress,
		FreezeTransactionID:          item.FreezeTransactionID,
		AuditTransactionID:           item.AuditTransactionID,
		Status:                       item.Status,
		ApproverUserID:               item.ApproverUserID,
		ApproverName:                 item.ApproverName,
		AuditRemark:                  item.AuditRemark,
		AuditImageURL:                item.AuditImageURL,
		ApprovedAtMS:                 item.ApprovedAtMS,
		OperationsStatus:             item.OperationsStatus,
		OperationsReviewerUserID:     item.OperationsReviewerUserID,
		OperationsReviewerName:       item.OperationsReviewerName,
		OperationsAuditRemark:        item.OperationsAuditRemark,
		OperationsAuditTransactionID: item.OperationsAuditTransactionID,
		OperationsReviewedAtMS:       item.OperationsReviewedAtMS,
		CreatedAtMS:                  item.CreatedAtMS,
		UpdatedAtMS:                  item.UpdatedAtMS,
	}
	if isPointWithdrawalAssetType(item.SalaryAssetType) {
		feePoints, netPoints, pointsPerUSD, feeBPS := pointWithdrawalSnapshot(item)
		dto.PointGrossAmount = item.WithdrawAmountMinor
		dto.PointFeeAmount = feePoints
		dto.PointNetAmount = netPoints
		dto.PointsPerUSD = pointsPerUSD
		dto.PointFeeBPS = feeBPS
		dto.PointPolicyInstance = item.PointPolicyInstance
	}
	return dto
}

func pointWithdrawalSnapshot(item model.UserWithdrawalApplication) (feePoints int64, netPoints int64, pointsPerUSD int64, feeBPS int32) {
	pointsPerUSD = item.PointsPerUSD
	if pointsPerUSD <= 0 {
		pointsPerUSD = pointWithdrawalDefaultPointsPerUSD
	}
	feeBPS = item.PointFeeBPS
	if feeBPS < 0 || feeBPS > 10000 {
		feeBPS = pointWithdrawalDefaultFeeBPS
	}
	feePoints, netPoints = item.PointFeeAmount, item.PointNetAmount
	if feePoints < 0 || netPoints < 0 || feePoints+netPoints != item.WithdrawAmountMinor {
		// 090 之前的存量 POINT 申请没有快照；只对这些不一致旧行按历史 5% 默认回填。
		feePoints = item.WithdrawAmountMinor * int64(feeBPS) / 10000
		netPoints = item.WithdrawAmountMinor - feePoints
	}
	return
}

func withdrawalApplicationDTOsFromModel(items []model.UserWithdrawalApplication) []withdrawalApplicationDTO {
	out := make([]withdrawalApplicationDTO, 0, len(items))
	for _, item := range items {
		out = append(out, withdrawalApplicationDTOFromModel(item))
	}
	return out
}
