package service

import (
	"bdqr-server/app/main/model"
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"time"

	"github.com/Masterminds/squirrel"
	"github.com/zeromicro/go-zero/core/logx"
)

// TianyuanapiCallLogService 天元API调用记录服务
type TianyuanapiCallLogService struct {
	tianyuanapiCallLogModel model.TianyuanapiCallLogModel
	featureModel            model.FeatureModel
}

// NewTianyuanapiCallLogService 创建天元API调用记录服务
func NewTianyuanapiCallLogService(
	tianyuanapiCallLogModel model.TianyuanapiCallLogModel,
	featureModel model.FeatureModel,
) *TianyuanapiCallLogService {
	return &TianyuanapiCallLogService{
		tianyuanapiCallLogModel: tianyuanapiCallLogModel,
		featureModel:            featureModel,
	}
}

// CallLogOptions 调用记录选项
type CallLogOptions struct {
	FeatureID     string      // 功能ID
	ApiID         string      // API标识（如：YYSYBE08）
	OrderID       string      // 订单ID（可选）
	QueryID       string      // 查询ID（可选）
	CallStatus    int64       // 调用状态：0=失败，1=成功
	ResponseTime  int64       // 响应耗时（毫秒）
	ErrorCode     string      // 错误码（失败时）
	ErrorMessage  string      // 错误信息（失败时）
	RequestParams interface{} // 请求参数（可选）
	ResponseData  interface{} // 响应数据（可选）
	TransactionID string      // 天元API流水号
}

// RecordCall 记录天元API调用
func (s *TianyuanapiCallLogService) RecordCall(ctx context.Context, opts CallLogOptions) error {
	// 1. 获取feature的成本价
	costPrice := 0.00
	if opts.CallStatus == 1 { // 只有成功才计算成本
		if opts.FeatureID == "" {
			logx.Infof("记录API调用时feature_id为空，api_id=%s，无法获取成本价", opts.ApiID)
		} else {
			feature, err := s.featureModel.FindOne(ctx, opts.FeatureID)
			if err == nil {
				costPrice = feature.CostPrice
				logx.Infof("记录API调用 - feature_id=%s, api_id=%s, cost_price=%f", opts.FeatureID, opts.ApiID, costPrice)
			} else {
				logx.Errorf("查询feature成本价失败，feature_id=%s, api_id=%s, err=%v", opts.FeatureID, opts.ApiID, err)
			}
		}
	}

	// 2. 转换参数和响应为JSON字符串
	var requestParamsStr, responseDataStr *string
	if opts.RequestParams != nil {
		if bytes, err := json.Marshal(opts.RequestParams); err == nil {
			jsonStr := string(bytes)
			requestParamsStr = &jsonStr
		}
	}
	if opts.ResponseData != nil {
		// 只记录响应数据的前1000个字符，避免存储过大
		if bytes, err := json.Marshal(opts.ResponseData); err == nil {
			jsonStr := string(bytes)
			if len(jsonStr) > 1000 {
				jsonStr = jsonStr[:1000] + "...[truncated]"
			}
			responseDataStr = &jsonStr
		}
	}

	// 3. 构建调用记录
	callTime := time.Now()
	deleteTime := sql.NullTime{}
	callLog := &model.TianyuanapiCallLog{
		FeatureId:     opts.FeatureID,
		ApiId:         opts.ApiID,
		OrderId:       sql.NullString{},
		QueryId:       sql.NullString{},
		CallStatus:    opts.CallStatus,
		CallTime:      callTime,
		ResponseTime:  sql.NullInt64{},
		CostPrice:     costPrice,
		ErrorCode:     sql.NullString{},
		ErrorMessage:  sql.NullString{},
		RequestParams: sql.NullString{},
		ResponseData:  sql.NullString{},
		TransactionId: sql.NullString{},
		CreateTime:    callTime,
		UpdateTime:    callTime,
		DeleteTime:    deleteTime,
		DelState:      0,
		Version:       0,
	}

	// 4. 填充可选字段
	if opts.OrderID != "" {
		callLog.OrderId = sql.NullString{String: opts.OrderID, Valid: true}
	}
	if opts.QueryID != "" {
		callLog.QueryId = sql.NullString{String: opts.QueryID, Valid: true}
	}
	if opts.ResponseTime > 0 {
		callLog.ResponseTime = sql.NullInt64{Int64: opts.ResponseTime, Valid: true}
	}
	if opts.ErrorCode != "" {
		callLog.ErrorCode = sql.NullString{String: opts.ErrorCode, Valid: true}
	}
	if opts.ErrorMessage != "" {
		callLog.ErrorMessage = sql.NullString{String: opts.ErrorMessage, Valid: true}
	}
	if requestParamsStr != nil {
		callLog.RequestParams = sql.NullString{String: *requestParamsStr, Valid: true}
	}
	if responseDataStr != nil {
		callLog.ResponseData = sql.NullString{String: *responseDataStr, Valid: true}
	}
	if opts.TransactionID != "" {
		callLog.TransactionId = sql.NullString{String: opts.TransactionID, Valid: true}
	}

	// 5. 插入记录
	_, err := s.tianyuanapiCallLogModel.Insert(ctx, nil, callLog)
	if err != nil {
		logx.Errorf("插入天元API调用记录失败，feature_id=%s, api_id=%s, err=%v", opts.FeatureID, opts.ApiID, err)
		return fmt.Errorf("插入调用记录失败: %w", err)
	}

	return nil
}

// GetStatistics 获取统计信息
type StatisticsFilter struct {
	FeatureID string    // 功能ID
	ApiID     string    // API标识
	StartDate time.Time // 开始日期
	EndDate   time.Time // 结束日期
}

// Statistics 统计信息
type Statistics struct {
	TotalCalls   int64   // 总调用次数
	SuccessCalls int64   // 成功次数
	FailedCalls  int64   // 失败次数
	TotalCost    float64 // 总成本（成功调用的成本之和）
}

// GetStatistics 获取统计信息
func (s *TianyuanapiCallLogService) GetStatistics(ctx context.Context, filter StatisticsFilter) (*Statistics, error) {
	builder := s.tianyuanapiCallLogModel.SelectBuilder()

	// 添加过滤条件
	if filter.FeatureID != "" {
		builder = builder.Where(squirrel.Eq{"feature_id": filter.FeatureID})
	}
	if filter.ApiID != "" {
		builder = builder.Where(squirrel.Eq{"api_id": filter.ApiID})
	}
	if !filter.StartDate.IsZero() {
		builder = builder.Where(squirrel.GtOrEq{"call_time": filter.StartDate})
		logx.Infof("API成本统计 - 开始时间: %v", filter.StartDate)
	}
	if !filter.EndDate.IsZero() {
		builder = builder.Where(squirrel.Lt{"call_time": filter.EndDate})
		logx.Infof("API成本统计 - 结束时间: %v", filter.EndDate)
	}

	// 统计总调用次数
	totalCalls, err := s.tianyuanapiCallLogModel.FindCount(ctx, builder, "id")
	if err != nil {
		return nil, fmt.Errorf("统计总调用次数失败: %w", err)
	}
	logx.Infof("API成本统计 - 总调用次数: %d", totalCalls)

	// 统计成功次数
	successBuilder := builder.Where(squirrel.Eq{"call_status": 1})
	successCalls, err := s.tianyuanapiCallLogModel.FindCount(ctx, successBuilder, "id")
	if err != nil {
		return nil, fmt.Errorf("统计成功次数失败: %w", err)
	}
	logx.Infof("API成本统计 - 成功调用次数: %d", successCalls)

	// 统计失败次数
	failedCalls := totalCalls - successCalls

	// 统计总成本（仅成功调用）
	// 先打印SQL以便调试（复制builder避免影响后续查询）
	debugBuilder := successBuilder
	query, values, _ := debugBuilder.Columns("IFNULL(SUM(cost_price),0)").Where("del_state = ?", 0).ToSql()
	logx.Infof("API成本统计 - SQL: %s, 参数: %v", query, values)

	totalCost, err := s.tianyuanapiCallLogModel.FindSum(ctx, successBuilder, "cost_price")
	if err != nil {
		return nil, fmt.Errorf("统计总成本失败: %w", err)
	}
	logx.Infof("API成本统计 - 总成本: %f", totalCost)

	return &Statistics{
		TotalCalls:   totalCalls,
		SuccessCalls: successCalls,
		FailedCalls:  failedCalls,
		TotalCost:    totalCost,
	}, nil
}
