package wechat

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/fonchain_enterprise/micro-account/pkg/cache"
	"github.com/fonchain_enterprise/micro-account/pkg/common/redis_key"
	"io/ioutil"
	"net/http"
	"time"
)

type Wechat struct {
	Appid     string
	AppSecret string
}

type OpenIDInfo struct {
	AccessToken    string `json:"access_token"`
	ExpiresIn      int    `json:"expires_in"`
	RefreshToken   string `json:"refresh_token"`
	Openid         string `json:"openid"`
	Scope          string `json:"scope"`
	IsSnapshotuser int    `json:"is_snapshotuser"`
	Unionid        string `json:"unionid"`
	Errmsg         string `json:"errmsg"`
	Errcode        int    `json:"errcode"`
}

type PhoneRes struct {
	PhoneInfo *PhoneInfo `json:"phone_info"`
	Errmsg    string     `json:"errmsg"`
	Errcode   int        `json:"errcode"`
}

type CommonRes struct {
	Errmsg  string `json:"errmsg"`
	Errcode int    `json:"errcode"`
}

type PhoneInfo struct {
	PhoneNumber     string `json:"phoneNumber"`
	PurePhoneNumber string `json:"purePhoneNumber"`
	Errcode         int    `json:"errcode"`
}

type BoxOpenId struct {
	Openid  string `json:"openid"`
	Errmsg  string `json:"errmsg"`
	Errcode int    `json:"errcode"`
}

type BoxAccessToken struct {
	AccessToken  string `json:"access_token"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	Errmsg       string `json:"errmsg"`
	Errcode      int    `json:"errcode"`
}

func GetOpenID(appID, appSecret, code string) (openInfo *OpenIDInfo, err error) {

	var openIDInfo *OpenIDInfo
	str := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
	url := fmt.Sprintf(str, appID, appSecret, code)

	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)

	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		fmt.Printf("请求失败%d\n", resp.StatusCode)
		return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
	}

	fmt.Println("返回数据是", string(body))

	err = json.Unmarshal(body, &openInfo)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	fmt.Println(openIDInfo)

	return

}

func GetBoxPhone(appID, appSecret, code string) (string, error) {
	accessToken, err := GetBoxAccessToken(appID, appSecret)
	if err != nil {
		return "", err
	}

	openInfo, err := getBoxPhone(accessToken, code)
	fmt.Println("提示设呢么", openInfo, err)

	if err != nil {
		return "", err
	}

	fmt.Println("123123--123", openInfo)
	fmt.Println(openInfo.Errmsg)
	fmt.Println(openInfo.Errcode)

	if openInfo.Errcode != 40001 && openInfo.PhoneInfo != nil {
		return openInfo.PhoneInfo.PurePhoneNumber, nil
	}

	fmt.Println("不顶用")
	cache.RedisClient.Del(redis_key.GetBoxAccessToken(appID))

	return getBoxPhoneAgain(appID, appSecret, code)

}

func getBoxPhoneAgain(appID, appSecret, code string) (string, error) {
	accessToken, err := GetBoxAccessToken(appID, appSecret)
	if err != nil {
		return "", err
	}

	openInfo, err := getBoxPhone(accessToken, code)
	fmt.Println("提示设呢么", openInfo, err)

	if err != nil {
		return "", err
	}

	fmt.Println("123123--123", openInfo)
	fmt.Println(openInfo.Errmsg)
	fmt.Println(openInfo.Errcode)
	if openInfo.Errcode != 40001 && openInfo.PhoneInfo != nil {
		return openInfo.PhoneInfo.PurePhoneNumber, nil
	}
	return "", errors.New(openInfo.Errmsg)
}

// GetBoxOpenID 获取小程序的openid
func GetBoxOpenID(appID, appSecret, code string) (string, error) {

	/*
		accessToken, err := GetBoxAccessToken(appID, appSecret)
		if err != nil {
			return "", err
		}

	*/

	openInfo, err := getLoginOpenIdByCode(appID, appSecret, code)
	fmt.Println("提示设呢么", openInfo, err)

	if err != nil {
		return "", err
	}

	return openInfo, nil
	//cache.RedisClient.Del(redis_key.GetBoxAccessToken(appID))

	//return getBoxOpenIDAgain(appID, appSecret, code)
}

func getBoxOpenIDAgain(appID, appSecret, code string) (string, error) {

	accessToken, err := GetBoxAccessToken(appID, appSecret)
	if err != nil {
		return "", err
	}

	openInfo, err := getOpenIdByCode(accessToken, code)

	if err != nil {
		return "", err
	}

	if openInfo.Errcode != 0 {
		return "", errors.New(openInfo.Errmsg)
	}

	return openInfo.Openid, nil
}

func getLoginOpenIdByCode(appId, appSecret, code string) (string, error) {

	str := "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
	url := fmt.Sprintf(str, appId, appSecret, code)

	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	if resp.StatusCode != 200 {
		fmt.Printf("请求失败%d\n", resp.StatusCode)
		return "", errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
	}

	fmt.Println("2--返回数据是", string(body))

	var openInfo OpenIDInfo
	err = json.Unmarshal(body, &openInfo)
	if err != nil {
		fmt.Println(err)
		return "", err
	}
	if openInfo.Errcode != 0 {

		return "", errors.New(openInfo.Errmsg)

	}

	return openInfo.Openid, err
}

func getOpenIdByCode(accessToken, code string) (openInfo *OpenIDInfo, err error) {

	url := "https://api.weixin.qq.com/wxa/getpluginopenpid?access_token=" + accessToken

	// 创建要发送的数据

	data := []byte(fmt.Sprintf(`{"code": "%s"}`, code))
	fmt.Println("1-------------", string(data))
	fmt.Println("1-------------", accessToken)

	// 发送POST请求
	resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
	if err != nil {
		fmt.Println("发送请求失败:", err)
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	if resp.StatusCode != 200 {
		fmt.Printf("请求失败%d\n", resp.StatusCode)
		return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
	}

	fmt.Println("2--返回数据是", string(body))

	err = json.Unmarshal(body, &openInfo)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	return openInfo, err
}

// getBoxPhone 获取手机号
func getBoxPhone(accessToken, code string) (res *PhoneRes, err error) {
	url := "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken

	// 创建要发送的数据
	data := []byte(fmt.Sprintf(`{"code": "%s"}`, code))

	// 发送POST请求
	resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
	if err != nil {
		fmt.Println("发送请求失败:", err)
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	if resp.StatusCode != 200 {
		fmt.Printf("请求失败%d\n", resp.StatusCode)
		return nil, errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
	}

	fmt.Println("2--返回数据是", string(body))

	err = json.Unmarshal(body, &res)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	return res, err
}

func GetBoxAccessToken(appID, appSecret string) (string, error) {

	accessToken := cache.RedisClient.Get(redis_key.GetBoxAccessToken(appID)).Val()

	if accessToken != "" {
		return accessToken, nil
	}

	var openIDInfo *BoxAccessToken

	str := "https://api.weixin.qq.com/cgi-bin/token?appid=%s&secret=%s&grant_type=client_credential"
	url := fmt.Sprintf(str, appID, appSecret)

	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}

	body, err := ioutil.ReadAll(resp.Body)

	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		fmt.Printf("请求失败%d\n", resp.StatusCode)
		return "", errors.New(fmt.Sprintf("请求失败%d", resp.StatusCode))
	}

	fmt.Println("返回数据是", string(body))

	err = json.Unmarshal(body, &openIDInfo)
	if err != nil {
		fmt.Println(err)
		return "", err
	}
	//记录下
	fmt.Println("123123123", redis_key.GetBoxAccessToken(appID), openIDInfo.AccessToken)
	fmt.Println(redis_key.GetBoxAccessToken(appID), openIDInfo.AccessToken)
	cache.RedisClient.Set(redis_key.GetBoxAccessToken(appID), openIDInfo.AccessToken, 6000*time.Second)

	return openIDInfo.AccessToken, nil

}