package util

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/fonchain/fonchain-artistinfo/pkg/m"
	"github.com/fonchain/utils/objstorage"
)

// IdCardTurnAge 身份证号读取年龄
func IdCardTurnAge(idCard string) int {
	var mapmou = map[string]int{"January": 1, "february": 2, "March": 3, "April": 4, "May": 5, "June": 6, "July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12}
	// idCard := "34052419800101001X" //身份证
	now := time.Now()
	now_year := now.Year()                 // 年
	now_mo := mapmou[now.Month().String()] // 月
	now_day := now.Day()                   // 日
	fmt.Println(now_year, now_mo, now_day)
	idcard_year, _ := strconv.Atoi(Substr(idCard, 6, 4)) // 年
	idcard_mo, _ := strconv.Atoi(Substr(idCard, 10, 2))  // 月
	idcard_day, _ := strconv.Atoi(Substr(idCard, 12, 2)) // 日
	fmt.Println(idcard_year, idcard_mo, idcard_day)
	fmt.Println("idCard:" + idCard)
	age := now_year - idcard_year // 如果计算虚岁需这样:age := now_year - idcard_year+1
	if now_year < idcard_year {
		age = 0
	} else {
		if now_mo < idcard_mo {
			age = age - 1
		} else {
			if now_day < idcard_day {
				age = age - 1
			}
		}
	}
	fmt.Println("age:", age)
	return age
}

func Substr(str string, start, length int) string {

	rs := []rune(str)
	rl := len(rs)
	end := 0
	if start < 0 {
		start = rl - 1 + start
	}
	end = start + length
	if start > end {
		start, end = end, start
	}
	if start < 0 {
		start = 0
	}
	if start > rl {
		start = rl
	}
	if end < 0 {
		end = 0
	}
	if end > rl {
		end = rl
	}
	return string(rs[start:end])
}

// 封装上传图片到bos然后返回状态和图片的url,单张
func UploadToBos(file multipart.File, objName string) (string, error) {
	BOSClient, err := objstorage.NewBOS(m.AK, m.SK, objstorage.BOS_BJ)
	if err != nil {
		fmt.Println(err)
	}
	b := new(strings.Builder)
	io.Copy(b, file)
	_, err = BOSClient.PutObjectFromBytes(m.Bucket, objName, []byte(b.String()))
	if err != nil {
		return "", err
	}
	url := m.URL + "/" + objName

	return url, nil
}

type CopyOption struct {
	Src         interface{}
	Dst         interface{}
	WhiteFields string
	BlackFields string
}

// 反射
func CopyStructSuper(copyOpt CopyOption) {
	st := reflect.TypeOf(copyOpt.Src)
	sv := reflect.ValueOf(copyOpt.Src)
	dt := reflect.TypeOf(copyOpt.Dst)
	dv := reflect.ValueOf(copyOpt.Dst)
	if st.Kind() == reflect.Ptr { //处理指针
		st = st.Elem()
		sv = sv.Elem()
	}
	if dt.Kind() == reflect.Ptr { //处理指针
		dt = dt.Elem()
	}
	if st.Kind() != reflect.Struct || dt.Kind() != reflect.Struct { //如果不是struct类型,直接返回dst
		return
	}

	dv = reflect.ValueOf(dv.Interface())

	// 遍历TypeOf 类型
	for i := 0; i < dt.NumField(); i++ { //通过索引来取得它的所有字段,同时来决定循环的次数
		f := dt.Field(i) //通过这个i作为它的索引,从0开始来取得它的字段
		dVal := dv.Elem().Field(i)
		sVal := sv.FieldByName(f.Name)
		if copyOpt.WhiteFields != "" {
			if !strings.Contains(copyOpt.WhiteFields, fmt.Sprintf(",%s,", f.Name)) {
				continue
			}
		}

		if copyOpt.BlackFields != "" {
			if strings.Contains(copyOpt.BlackFields, fmt.Sprintf(",%s,", f.Name)) {
				continue
			}
		}
		//src数据有效,且dst字段能赋值,类型一致
		if sVal.IsValid() && dVal.CanSet() && f.Type.Kind() == sVal.Type().Kind() {
			dVal.Set(sVal)
		}
	}
}

func Post(url, data string) (string, error) {
	reader := bytes.NewReader([]byte(data))

	request, err := http.NewRequest("POST", url, reader)
	if err != nil {
		return "", err
	}
	defer request.Body.Close() //程序在使用完回复后必须关闭回复的主体
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	//必须设定该参数,POST参数才能正常提交,意思是以json串提交数据

	client := http.Client{}
	resp, err := client.Do(request) //Do 方法发送请求,返回 HTTP 回复
	if err != nil {
		return "", err
	}

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	//byte数组直接转成string,优化内存
	// str := (*string)(unsafe.Pointer(&respBytes))
	return string(respBytes), nil
}