package maycur

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"hongze/hz_crm_api/services/alarm_msg"
	"hongze/hz_crm_api/utils"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

const (
	AppKey                       = "AP3MLZIOZR9AIH"
	AppSecret                    = "vuarTISZiRM4U3CcSkQLlKLQSDhZZkxG"
	ApiSuccessCode               = "ACK"                                      // 接口请求成功标识
	CompanyProfileCode           = "RD2203231L27R3B4"                         // 客户档案编码
	OpenApiTokenCacheKey         = "admin_maycur_token"                       // Token缓存Key
	OpenApiAuthLoginUrl          = "/api/openapi/auth/login"                  // 鉴权接口
	ApiEmployeeDetailUrl         = "/api/openapi/employee/details"            // 员工详情接口
	ApiCompanyProfilePageListUrl = "/api/openapi/reference/data/detail/query" // 客户档案列表接口-分页
	ApiImportCompanyProfileUrl   = "/api/openapi/reference/data/detail"       // 批量导入客户档案接口
	AuthGroupCode                = "UG21277004535961787"                      // 所有客户档案可见的用户组编码
)

// OpenApiTokenReq 获取OpenApiToken请求体
type OpenApiTokenReq struct {
	Secret    string `json:"secret" description:"secret, 非AppSecret"`
	AppCode   string `json:"appCode" description:"MayCurAppKey"`
	Timestamp int64  `json:"timestamp" description:"毫秒级时间戳"`
}

// OpenApiTokenResp 获取OpenApiToken响应体
type OpenApiTokenResp struct {
	Code    string `json:"code" description:"状态码"`
	Message string `json:"message" description:"返回信息"`
	Data    OpenApiToken
}

// OpenApiToken OpenApiToken
type OpenApiToken struct {
	EntCode string `json:"entCode" description:"企业编码"`
	TokenId string `json:"tokenId" description:"Token"`
}

// CurlOpenApiToken 请求OpenApiToken接口
func CurlOpenApiToken() (result *OpenApiTokenResp, err error) {
	// 生成secret
	millTime := time.Now().UnixNano() / 1e6
	hexBase := fmt.Sprintf("%s:%s:%d", AppSecret, AppKey, millTime)
	m := sha256.New()
	m.Write([]byte(hexBase))
	secret := hex.EncodeToString(m.Sum(nil))

	// 请求参数
	params := new(OpenApiTokenReq)
	params.Secret = secret
	params.AppCode = AppKey
	params.Timestamp = millTime

	// 请求体
	url := fmt.Sprintf("%s%s", utils.MayCurBaseUrl, OpenApiAuthLoginUrl)
	paramsByte, e := json.Marshal(params)
	if e != nil {
		err = fmt.Errorf("params to json err: %s", e.Error())
		return
	}
	postParam := string(paramsByte)

	// 响应结果
	body, e := buildHttpRequest(url, "POST", postParam, false)
	result = new(OpenApiTokenResp)
	if e = json.Unmarshal(body, &result); e != nil {
		err = fmt.Errorf("resp unmarshal err: %s", e.Error())
		return
	}
	return
}

// GetOpenApiToken 获取OpenApiToken
func GetOpenApiToken() (apiToken *OpenApiToken, err error) {
	defer func() {
		if err != nil {
			utils.FileLog.Error("GetOpenApiToken Err: %s", err.Error())
			alarm_msg.SendAlarmMsg(fmt.Sprintf("获取OpenApiToken失败, ErrMsg: %s", err.Error()), 3)
		}
	}()
	apiToken = new(OpenApiToken)

	// 缓存读取token
	t, _ := utils.Rc.RedisString(OpenApiTokenCacheKey)
	if t != "" {
		lastToken := new(OpenApiToken)
		if e := json.Unmarshal([]byte(t), &lastToken); e != nil {
			err = fmt.Errorf("OpenApiToken缓存解析失败, Err: %s", e.Error())
			return
		}
		if lastToken != nil && lastToken.EntCode != "" && lastToken.TokenId != "" {
			apiToken = lastToken
			return
		}
	}

	// 获取新的token
	result, e := CurlOpenApiToken()
	if e != nil {
		err = fmt.Errorf("请求OpenApiToken接口失败, Err: %s", e.Error())
		return
	}
	if result == nil {
		err = fmt.Errorf("请求OpenApiToken接口结果为nil")
		return
	}
	if result.Code != ApiSuccessCode {
		err = fmt.Errorf("请求OpenApiToken接口Code异常: %s, ErrMsg: %s", result.Code, result.Message)
		return
	}
	apiToken.TokenId = result.Data.TokenId
	apiToken.EntCode = result.Data.EntCode

	// 写入缓存
	cacheByte, e := json.Marshal(apiToken)
	if e != nil {
		err = fmt.Errorf("OpenApiToken转Json失败, Err: %s", e.Error())
		return
	}
	if e = utils.Rc.Put(OpenApiTokenCacheKey, cacheByte, 28*time.Minute); e != nil {
		err = fmt.Errorf("OpenApiToken写入缓存失败, Err: %s", e.Error())
		return
	}
	return
}

// buildHttpRequest 创建请求
func buildHttpRequest(url, method, payload string, hasAuth bool) (result []byte, err error) {
	client := http.Client{}
	req, e := http.NewRequest(method, url, strings.NewReader(payload))
	if e != nil {
		err = fmt.Errorf("http new request err: %s", e.Error())
		return
	}
	req.Header.Set("Content-Type", "application/json")
	// 鉴权信息
	if hasAuth {
		token, e := GetOpenApiToken()
		if e != nil {
			err = fmt.Errorf("获取Token失败, Err: %s", e.Error())
			return
		}
		if token == nil {
			err = fmt.Errorf("获取Token失败, nil")
			return
		}
		if token.EntCode == "" || token.TokenId == "" {
			err = fmt.Errorf("获取Token异常, EntCode: %s, TokenId: %s", token.EntCode, token.TokenId)
			return
		}
		req.Header.Set("entCode", token.EntCode)
		req.Header.Set("tokenId", token.TokenId)
		//utils.FileLog.Info("EntCode: %s, TokenId: %s", token.EntCode, token.TokenId)
	}

	resp, e := client.Do(req)
	if e != nil {
		err = fmt.Errorf("client request err: %s", e.Error())
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()

	body, e := ioutil.ReadAll(resp.Body)
	if e != nil {
		err = fmt.Errorf("ioutil read err: %s", e.Error())
		return
	}
	utils.FileLog.Info("maycur http resp: %s", string(body))
	return body, nil
}

// SyncCompanyProfile 同步客户档案及可见性
func SyncCompanyProfile() (err error) {
	defer func() {
		if err != nil {
			utils.FileLog.Error("SyncCompanyProfile ErrMsg: %s", err.Error())
			alarm_msg.SendAlarmMsg(fmt.Sprintf("每刻-同步客户档案及可见性失败, ErrMsg: %s", err.Error()), 3)
			return
		}
		//alarm_msg.SendAlarmMsg(fmt.Sprintf("每刻-同步客户档案成功"), 1)
	}()

	// 同步每刻客户档案到本地
	utils.FileLog.Info("下载客户档案至本地")
	if e := DownloadCompanyProfile(); e != nil {
		err = fmt.Errorf("同步客户档案至本地失败, Err: %s", e.Error())
		return
	}
	// 更新公募销售、公募客户信息
	utils.FileLog.Info("更新公募客户及销售")
	if e := SyncPublicOfferingSale(); e != nil {
		err = fmt.Errorf("同步公募销售信息失败, Err: %s", e.Error())
		return
	}
	if e := SyncPublicOfferingCompany(); e != nil {
		err = fmt.Errorf("同步公募客户信息失败, Err: %s", e.Error())
		return
	}

	// 生成导入数据
	utils.FileLog.Info("生成导入数据")
	importsData, e := GetImportCompanyData()
	if e != nil {
		err = fmt.Errorf("生成导入数据失败, Err: %s", e.Error())
		return
	}
	// Test
	//for _, v := range importsData {
	//	b, e := json.Marshal(v)
	//	if e != nil {
	//		err = fmt.Errorf("request json marshal err: %s", e.Error())
	//		return
	//	}
	//	utils.FileLog.Info("%s", string(b))
	//}

	// 导入
	utils.FileLog.Info("导入数据长度: %d", len(importsData))
	if e := ImportCompanyProfile(importsData); e != nil {
		err = fmt.Errorf("导入失败, Err: %s", e.Error())
		return
	}
	return
}

//func ApiTest() (err error) {
//	defer func() {
//		if err != nil {
//			fmt.Println(err.Error())
//		}
//	}()
//
//	time.Sleep(2 * time.Second)
//
//	var req ImportCompanyProfileReq
//	req.BizCode = CompanyProfileCode
//
//	var dataDetails []ImportCompanyProfileReferenceData
//	authArr := make([]*ReferenceDataAuth, 0)
//	authArr = append(authArr, &ReferenceDataAuth{
//		BizCode: "0155",
//		Type:    "STAFF",
//	})
//	//HZCP0155
//	dataDetails = append(dataDetails, ImportCompanyProfileReferenceData{
//		Name:               "测试导入",
//		BizCode:            "HZCP0155",
//		Enabled:            true,
//		ReferenceDataAuthz: authArr,
//	})
//	req.ReferenceDataDetails = dataDetails
//
//	_, _ = CurlImportCompanyProfile(req)
//	fmt.Println("操作成功")
//	return
//}

//func ApiTest2() (err error) {
//	defer func() {
//		if err != nil {
//			fmt.Println(err.Error())
//		}
//	}()
//
//	url := fmt.Sprintf("%s%s", utils.MayCurBaseUrl, `/api/openapi/reference/data/detail/RD2203231L27R3B4/HZCP1680171ELGFQ3`)
//	_, e := buildHttpRequest(url, "GET", ``, true)
//	if e != nil {
//		err = fmt.Errorf("操作失败, Err: %s", e.Error())
//		return
//	}
//	fmt.Println("操作成功")
//	return
//}
