package basic

import (
	"fmt"
	"io"
	"net/http"
	"reflect"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/zeromicro/go-zero/core/logx"
)

// 全局的BucketName
var StorageBucketName = aws.String("storage.fusenpack.com")

// 全局的BucketName 缓存使用
var TempfileBucketName = aws.String("tempfile.fusenpack.com")

const UploadFileLimitSize = 200 << 20

// File uploadfile 文件(multipart...)
type File struct {
	Filename string
	Header   map[string][]string
	Size     int64
	Data     []byte
}

// StatusResponse 公司自定义状态码
type StatusResponse struct {
	Code    int    // 状态码
	Message string // 状态码相关解析
}

var (
	CodeOK         = &StatusResponse{200, "success"}            // 成功
	CodeApiErr     = &StatusResponse{500, "api error"}          // API错误
	CodeSaveErr    = &StatusResponse{501, "failed to save"}     // 保存失败
	CodeServiceErr = &StatusResponse{510, "server logic error"} // 服务逻辑错误
	CodeUnAuth     = &StatusResponse{401, "unauthorized"}       // 未授权

	CodeOAuthGoogleApiErr           = &StatusResponse{5070, "oauth2 google api error"}
	CodeOAuthRegisterTokenErr       = &StatusResponse{5071, "oauth2 register create token error"}
	CodeOAuthEmailErr               = &StatusResponse{5072, "Invalid email format"}
	CodeOAuthRandReaderErr          = &StatusResponse{5073, "rand reader error"}
	CodeOAuthConfirmationTimeoutErr = &StatusResponse{5074, "confirmation timeout error"}
	CodeOAuthResetTokenEncryptErr   = &StatusResponse{5075, "oauth2 reset  token encrypt error"}
	CodeOAuthResetTokenDecryptErr   = &StatusResponse{5076, "oauth2 reset  token decrypt error"}
	CodeOAuthTypeErr                = &StatusResponse{5077, "oauth2 token operator error"}

	CodeS3PutObjectRequestErr = &StatusResponse{5060, "s3 PutObjectRequest error"}    // s3 PutObjectRequest 错误
	CodeS3PutSizeLimitErr     = &StatusResponse{5061, "s3 over limit size error"}     // s3 超过文件大小限制 错误
	CodeS3CategoryErr         = &StatusResponse{5062, "s3 category not exists error"} // s3 类别不存在  错误

	CodeEmailNotFoundErr  = &StatusResponse{5050, "email not found"}                            // 未找到email
	CodeUserIdNotFoundErr = &StatusResponse{5051, "user not found"}                             // 未找到用户
	CodePasswordErr       = &StatusResponse{5052, "invalid password"}                           // 无效密码
	CodeEmailExistsErr    = &StatusResponse{5053, "email exists"}                               // email存在
	CodeEmailTimeShortErr = &StatusResponse{5053, "email with the time of resend is too short"} // email重发的时间太短
	CodeResetPasswordErr  = &StatusResponse{5054, "reset password error"}                       // 无效密码
	CodeEmailErr          = &StatusResponse{5054, "email error"}

	CodeSafeValueRangeErr = &StatusResponse{5040, "value not in range"}    // 值不在范围内
	CodeTemplateErr       = &StatusResponse{5040, "template parsed error"} // 模板解析错误

	CodeOrderNotFoundErr      = &StatusResponse{5030, "order not found"}                    //未找到订单
	CodeCloudOrderNotFoundErr = &StatusResponse{5031, "cloud order not found"}              //未找到云仓订单
	CodeOrderNotCancelledErr  = &StatusResponse{5032, "current order cannot be cancelled"}  // 当前订单无法取消
	CodeOrderCancelledNotOk   = &StatusResponse{5033, "current order cancelled failed"}     // 当前订单取消失败
	CodeOrderCancelledOk      = &StatusResponse{5034, "current order cancelled successful"} // 当前订单取消成功

	CodePayNotFoundErr = &StatusResponse{5020, "pay info not found"}      // 支付信息无法查询
	CodePayCancelOk    = &StatusResponse{5021, "cancellation successful"} // 支付取消成功
	CodePayCancelNotOk = &StatusResponse{5022, "cancellation failed"}     // 支付取消失败

	CodePaybackNotOk = &StatusResponse{5023, "pay back failed"} // 支付回调处理失败

	CodeGuestDupErr = &StatusResponse{5010, "user is already guest and does not need to reapply"} // 用户已经是访客用户,无需重复申请
	CodeGuestGenErr = &StatusResponse{5011, "serialization failed for guest ID"}                  // 访客ID序列化失败

	CodeDbUpdateErr         = &StatusResponse{5000, "database update error"}               // 数据库更新错误
	CodeRequestParamsErr    = &StatusResponse{5002, "invalid request parameters"}          // 请求参数无效
	CodeDbRecordNotFoundErr = &StatusResponse{5003, "database record not found"}           //数据库中未找到记录
	CodeDbCreateErr         = &StatusResponse{5004, "failed to create record in database"} // 数据库中创建记录失败
	CodeDbSqlErr            = &StatusResponse{5005, "database error"}                      // 数据库错误
	CodeJsonErr             = &StatusResponse{5006, "JSON error"}                          // JSON解析错误

	CodeAesCbcEncryptionErr = &StatusResponse{5106, "encryption data err"} // 加密数据失败
	CodeAesCbcDecryptionErr = &StatusResponse{5107, "decryption data err"} // 解密数据失败

	CodeSharedStateErr       = &StatusResponse{5201, "shared state server  err"} // 状态机错误
	CodeEmailConfirmationErr = &StatusResponse{5202, "email confirmation   err"} // email 验证错误

	CodeFileUploadErr         = &StatusResponse{5110, "file upload  err"}                  // 文件上传失败
	CodeFileUploadLogoErr     = &StatusResponse{5111, "logo upload  err"}                  // 用户上传LOGO失败
	CodeFileUploadLogoErrType = &StatusResponse{5111, "logo upload err file is not image"} // 用户上位LOGO失败"}
	CodeFileLogoCombineErr    = &StatusResponse{5112, "logo upload  err"}                  // 用户合图失败
	CodeFileNoFoundErr        = &StatusResponse{5113, "file not found  err"}               // 文件不存在
	CodeLogoSetCategory       = &StatusResponse{5114, "logo set category fail"}            // 文件不存在

	CodeLogoCombineErr        = &StatusResponse{5115, "logo combine fail"}         // 合图失败
	CodeLogoCombineNoFoundErr = &StatusResponse{5116, "template record not found"} // 模版不存在

	CodeErrOrder                            = &StatusResponse{5300, "create order failed"}                                    // 订单错误
	CodeErrOrderCreatShoppingCartEmpty      = &StatusResponse{5301, "create order failed, shopping cart is empty"}            // 订单创建失败,购物车为空
	CodeErrOrderCreatShoppingCartNotMatched = &StatusResponse{5302, "create order failed, shopping cart not matched"}         // 订单创建失败,购物车不相符
	CodeErrOrderCreatProductAbsent          = &StatusResponse{5303, "create order failed, product is absent"}                 // 订单创建失败,商品不存在
	CodeErrOrderCreatProductPriceAbsent     = &StatusResponse{5304, "create order failed, price of product is absent"}        // 订单创建失败,商品价格不存在
	CodeErrOrderCreatProductAccessoryAbsent = &StatusResponse{5305, "create order failed, accessory of product is absent"}    // 订单创建失败,商品配件不存在
	CodeErrOrderCreatePrePaymentParam       = &StatusResponse{5306, "create payment failed, the shipping address is illegal"} // 订单创建失败,商品配件不存在
	CodeErrOrderCreatePrePaymentInfoNoFound = &StatusResponse{5307, "order info not found"}
	CodeErrOrderCreatePrePaymentNoUnPaid    = &StatusResponse{5308, "create payment failed, order is not unpaid"}
	CodeErrOrderCreatePrePaymentPaid        = &StatusResponse{5309, "create payment failed, order is paid"}
	CodeErrOrderCreatePrePaymentTimeout     = &StatusResponse{5310, "create payment failed, timeout"}
	CodeErrOrderDeleteStatusIllegality      = &StatusResponse{5311, "delete order failed, status is illegality"}
	CodeErrOrderInvoiceStatusIllegality     = &StatusResponse{5312, "get order invoice failed, pay status is illegality"}
)

type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"msg"`
	Data    interface{} `json:"data"`
	Debug   interface{} `json:"debug"` // debug的相关数据
}

// Set 设置Response的Code和Message值
func (resp *Response) Set(Code int, Message string) *Response {
	return &Response{
		Code:    Code,
		Message: Message,
	}
}

// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数, 第二个data就是debug参数
func (resp *Response) SetStatus(sr *StatusResponse, dataAndDebug ...interface{}) *Response {

	newResp := &Response{
		Code:    sr.Code,
		Message: sr.Message,
	}

	switch len(dataAndDebug) {
	case 0:
		// 0 直接返回
	case 1:
		if err, ok := dataAndDebug[0].(error); ok {
			newResp.Message = err.Error()
		} else {
			newResp.Data = dataAndDebug[0]
		}
	case 2:
		newResp.Data = dataAndDebug[0]
		newResp.Debug = dataAndDebug[1]
	default:
		panic("data只接收1或2个 data, error.Error() 和 data ")
	}

	return newResp
}

// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数, 第二个data就是debug参数
func (resp *Response) SetWithDebug(sr *StatusResponse, debug interface{}) *Response {

	resp = &Response{
		Code:    sr.Code,
		Message: sr.Message,
		Debug:   debug,
	}

	return resp
}

// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数
func (resp *Response) SetStatusWithMessage(sr *StatusResponse, msg string, dataAndDebug ...interface{}) *Response {
	newResp := &Response{
		Code:    sr.Code,
		Message: msg,
	}

	switch len(dataAndDebug) {
	case 0:
		// 0 直接返回
	case 1:
		newResp.Data = dataAndDebug[0]
	case 2:
		newResp.Debug = dataAndDebug[1]
	default:
		panic("data只接收一个 data")
	}

	return newResp
}

func (resp *Response) SetStatusAddMessage(sr *StatusResponse, msg string, dataAndDebug ...interface{}) *Response {
	newResp := &Response{
		Code:    sr.Code,
		Message: sr.Message + ":" + msg,
	}

	switch len(dataAndDebug) {
	case 0:
		// 0 直接返回
	case 1:
		newResp.Data = dataAndDebug[0]
	case 2:
		newResp.Data = dataAndDebug[0]
		newResp.Debug = dataAndDebug[1]
	default:
		panic("data只接收一个 data")
	}
	return newResp
}

var fileType = reflect.TypeOf(File{})

func RequestFileParse(r *http.Request, req any) error {
	vreq := reflect.ValueOf(req)
	if vreq.Kind() != reflect.Ptr {
		panic("req must &req pass")
	}

	reqValue := vreq.Elem()
	reqType := reqValue.Type()
	for i := 0; i < reqType.NumField(); i++ {
		if tname, ok := reqType.Field(i).Tag.Lookup("file"); ok {
			file, fheader, err := r.FormFile(tname)
			if err != nil {
				logx.Info("upload file error")
				return err
			}

			if fheader.Size > UploadFileLimitSize {
				err = fmt.Errorf("upload file size over limit %d", UploadFileLimitSize)
				logx.Info(err)
				return err
			}

			data, err := io.ReadAll(file)
			if err != nil {
				logx.Info("upload file data error")
				return err
			}
			err = file.Close()
			if err != nil {
				logx.Info("file  close error")
				return err
			}

			field := reqValue.Field(i)

			if field.Kind() == reflect.Ptr {
				if field.IsNil() {
					fsfile := reflect.New(field.Type().Elem())
					fsfile = fsfile.Elem()
					fsfile.Field(0).Set(reflect.ValueOf(fheader.Filename))
					fsfile.Field(1).Set(reflect.ValueOf(fheader.Header))
					fsfile.Field(2).Set(reflect.ValueOf(fheader.Size))
					fsfile.Field(3).Set(reflect.ValueOf(data))
					field.Set(fsfile.Addr())
				} else {
					field = field.Elem()
					field.Field(0).Set(reflect.ValueOf(fheader.Filename))
					field.Field(1).Set(reflect.ValueOf(fheader.Header))
					field.Field(2).Set(reflect.ValueOf(fheader.Size))
					field.Field(3).Set(reflect.ValueOf(data))
				}
			} else {
				field.Field(0).Set(reflect.ValueOf(fheader.Filename))
				field.Field(1).Set(reflect.ValueOf(fheader.Header))
				field.Field(2).Set(reflect.ValueOf(fheader.Size))
				field.Field(3).Set(reflect.ValueOf(data))
			}

		}
	}

	return nil
}