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"} // 无效密码

	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"}                  // 用户合图失败
)

type Response struct {
	rewriteHandlerFunc http.HandlerFunc
	Code               int         `json:"code"`
	Message            string      `json:"msg"`
	Data               interface{} `json:"data"`
}

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

// Set 设置整个Response
func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response {
	return &Response{
		Code:    Code,
		Message: Message,
		Data:    Data,
	}
}

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

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

	return newResp
}

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

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

	return newResp
}

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

	switch len(data) {
	case 0:
		// 0 直接返回
	case 1:
		newResp.Data = data[0]
	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
}

// RewriteHandler
func (resp *Response) SetRewriteHandler(do http.HandlerFunc) *Response {
	resp = &Response{
		Code: 304,
	}
	resp.rewriteHandlerFunc = do
	return resp
}

// RewriteHandler
func (resp *Response) rewriteHandler(w http.ResponseWriter, r *http.Request) {
	resp.rewriteHandlerFunc(w, r)
}

// Set 设置Response的Code和Message值
func (resp *Response) isRewriteHandler() bool {
	return resp.rewriteHandlerFunc != nil
}