package yc

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
	"tmr-watch/conf/setting"
	"tmr-watch/http/handle/restful"
	"tmr-watch/pkg/logging"

	"github.com/astaxie/beego/logs"
	"github.com/robfig/cron"
	"github.com/xormplus/xorm"
)

type udPastureInfo struct {
	Token     string `xorm:"token"`
	Pastureid string `xorm:"pastureid"`
	Werks     string `xorm:"werks"`
}

func YqCron() {
	tx := restful.Engine.NewSession()
	defer tx.Close()

	pastureinfo := new(udPastureInfo)
	err := tx.SQL(`select column_default  as pastureid,(select werks from pasture where pastureid = column_default)  werks  from    information_schema.COLUMNS
	WHERE table_name = 'recweight' AND table_schema = ? AND column_name = 'pastureid'`, setting.DatabaseSetting.Name).GetFirst(pastureinfo).Error
	if err != nil {
		logs.Error(err)
		return
	}

	token := getToken()
	syncBar(token, pastureinfo.Pastureid)

	c := cron.New()
	c.AddFunc("0 0 1 * * *", func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcFeedtempletPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcFeedPush(pastureinfo.Pastureid, pastureinfo.Werks, token)
		YcPlanPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcBarFeedRemainPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	c.AddFunc("0 0 6 * * *", func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcPlanPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	c.AddFunc("0 0 7 * * *", func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcFeedtempletPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcBarFeedRemainPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	c.AddFunc("0 0 12 * * *", func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcPlanPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	c.AddFunc("0 0 18 * * *", func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcPlanPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	c.AddFunc("0 0 23 * * *", func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcFeedtempletPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcFeedPush(pastureinfo.Pastureid, pastureinfo.Werks, token)
		YcPlanPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcBarFeedRemainPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	duetimecst2, _ := time.ParseInLocation("15:04:05", "00:05:00", time.Local)
	duetimecst3, _ := time.ParseInLocation("15:04:05", "00:00:00", time.Local)
	spec := fmt.Sprintf("@every %v", duetimecst2.Sub(duetimecst3))
	c.AddFunc(spec, func() {
		token := getToken()
		now := time.Now().Format("2006-01-02")
		YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
		YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, now, token)
	})

	c.Start()

	// YcFeedtempletPush(pastureinfo.Pastureid, pastureinfo.Werks, "", token)
	// fmt.Println(getToken())

	// YcFeedPush(pastureinfo.Pastureid, pastureinfo.Werks, token)
	// YcPlanPush(pastureinfo.Pastureid, pastureinfo.Werks, "", token)
	// YcUtirPush(pastureinfo.Pastureid, pastureinfo.Werks, "", token)
	// YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, "", token)
	// YcBarFeedRemainPush(pastureinfo.Pastureid, pastureinfo.Werks, "", token)
	// YcMaterialIssuePush(pastureinfo.Pastureid, pastureinfo.Werks, "", token)
}

func createApiSign(appId, timeStamp, apiKey, secretKey string) string {
	return getMD5Encode(fmt.Sprintf("%s#%s#%s#%s", appId, timeStamp, apiKey, secretKey))
}

func getMD5Encode(data string) string {
	fmt.Println(data)
	hasher := md5.New()
	hasher.Write([]byte(data))
	digest := hasher.Sum(nil)
	md5HashString := hex.EncodeToString(digest)
	return md5HashString
}

func getToken() string {
	appId := "6Zub5bed5Yqo55uS"
	apiKey := "3c6bbff8cf1e496eb8eb9025cd8537fh"
	secretKey := "26b5d9f63b6142de8f102afb1aa2eb7g"

	req, err := http.NewRequest("POST", "https://test.vmuyun.com/base-server/outSide/token", nil)
	if err != nil {
		logs.Error(err)
	}

	now := time.Now()
	nanos := now.UnixNano()
	timeStamp := fmt.Sprintf("%d", nanos/int64(time.Millisecond))
	apiSign := createApiSign(appId, timeStamp, apiKey, secretKey)
	req.Header.Set("appId", appId)
	req.Header.Set("apiKey", apiKey)
	req.Header.Set("secretKey", secretKey)
	req.Header.Set("timeStamp", timeStamp)
	req.Header.Set("apiSign", apiSign)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logs.Error(err)
		return ""
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	data := make(map[string]string, 0)
	json.Unmarshal(body, &data)
	fmt.Println(string(body))

	if _, ok := data["data"]; ok {
		return data["data"]
	}
	return ""
}

func postPush(data string, msgtype int, tx *xorm.Session, pastureId, token string) {

	// jsonStr, _ := json.Marshal(data)
	url := "https://test.vmuyun.com/project-server/openApi/feeding/pushData"
	req, err := http.NewRequest("POST", url, strings.NewReader((data)))
	if err != nil {
		logs.Error(err)
		// return nil
	}

	// req.Header.Set("Content-Type", "application/json")
	// req.Header.Set("Content-Length", "13444")
	req.Header.Add("Authorization", token)
	// req.Header.Set("Host", "test.vmuyun.com")
	// req.Header.Set("Accept", "*/*")
	// req.Header.Set("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
	// req.Header.Add("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
	req.Header.Add("Content-Type", "application/json")
	// req.Header.Add("Accept", "*/*")
	// req.Header.Add("Host", "test.vmuyun.com")
	// req.Header.Add("Connection", "keep-alive")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logs.Error(err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))

	if strings.Index(resp.Status, "200") > -1 {
		bodyData := make(map[string]string)
		json.Unmarshal(body, &bodyData)
		if _, ok := bodyData["data"]; ok {
			tx.Exec(` insert into saplog(pastureId,request,response,status,msgtext,createTime,msgtype,dataDate,url)
			values(?,?,?,?,?,now(),?,now(),?)`, pastureId, data, bodyData["data"], "", "", msgtype, url)
		} else {
			tx.Exec(` insert into saplog(pastureId,request,response,status,msgtext,createTime,msgtype,dataDate,url)
			values(?,?,?,?,?,now(),?,now(),?)`, pastureId, data, string(body), "", "", msgtype, url)
		}
	} else {
		tx.Exec(` insert into saplog(pastureId,request,response,status,msgtext,createTime,msgtype,dataDate,url)
		values(?,?,?,?,?,now(),?,now(),?)`, pastureId, data, string(body), "", "", msgtype, url)
	}

}

func YcFeedtempletPush(pastureId, farmId, date, token string) error {
	tx := restful.Engine.NewSession()
	defer tx.Close()

	var now string
	if date != "" {
		now = date
	} else {
		now = time.Now().AddDate(0, 0, -1).Format("2006-01-02")
	}

	dataList, err := tx.SQL(`SELECT
	ft.tcode AS recipeId,
	ft.TNAME AS recipeName,
	f.feedcode   AS ingId,
	ifnull(f.udname,f.fname) AS ingName,
	round( f.dry * ftd.FWEIGHT, 2 ) AS dmQty,
	ftd.FWEIGHT AS afQty,
	ftd.SORT AS mixNo,
	round( f.Uprice * ftd.FWEIGHT, 2 ) AS recipeCost,
	fc.fcname AS ingType,
	f.AllowRatio AS allowableError ,fc.fcname ingType
FROM
	feedtempletdate ft 
	 JOIN ftdetaildate ftd ON ft.id = ftd.FTID  and ft.date = ftd.date
	 JOIN feed f ON ftd.FID = f.id
	 JOIN feedclass fc ON f.fclassid = fc.id 
WHERE
	ft.ENABLE = 1 
	AND ft.isDelete != 1  and ft.date = ?  `, now).Query().List()
	if err != nil {
		logging.Error(err)
		return err
	}

	dataByte, _ := json.Marshal(&dataList)

	reqJson := `{
    "reqMethod": "PARTY",
    "param": {
        "code": "1",
        "method": "getfeedtempletinfo",
        "resultData": %s,
        "farmId": "%s",
        "rowCount": %d,
        "errMessage": ""
    },
    "regCode": "cpt180511",
    "command": "3d6e4752",
    "apiId": "getCptData"
}`
	reqJson = fmt.Sprintf(reqJson, string(dataByte), farmId, len(dataList))
	fmt.Println(reqJson)
	postPush(reqJson, 4, tx, pastureId, token)
	return nil
}

func YcFeedPush(pastureId, farmId, token string) error {
	tx := restful.Engine.NewSession()
	defer tx.Close()

	dataList, err := tx.SQL(`SELECT
	dry dmQty,
	sort,
	feedcode ingId,
	fname ingName,
	fclass ingType,
	allowratio allowableError 
FROM
	feed 
WHERE
	pastureId = ?  `, pastureId).Query().List()
	if err != nil {
		logging.Error(err)
		return err
	}

	dataByte, _ := json.Marshal(&dataList)
	reqJson := `{
		"apiId": "getKPTData ", 
		"param": {
			"farmId": "%s",
				"method":"getfeedinfo",
				"rowCount": %d,
				"resultData":%s
		}
	}`

	reqJson = fmt.Sprintf(reqJson, farmId, len(dataList), string(dataByte))
	fmt.Println(reqJson)
	postPush(reqJson, 2, tx, pastureId, token)
	return nil
}

func YcPlanPush(pastureId, farmId, date, token string) error {
	tx := restful.Engine.NewSession()
	defer tx.Close()

	dataList, err := tx.SQL(`SELECT
	projname planName,
	datacaptureno tmrNo,
	times loadShift,
	tempid recipeId,
	templetname recipeName,
	lweight expWeight,
	tmrtname tmrName,
	'是' STATUS,
	feedpcount cowCount,
	id planId,
	DATE_FORMAT( mydate, '%H:%i:%s' ) planTime,
	DATE_FORMAT( mydate, '%Y-%m-%d' ) planDate,
IF( iscompleted = 1, '是', '否' ) isCompleted,
IF(dlp.driverId != 0,(
		SELECT
			drivername 
		FROM
			driver 
		WHERE
			id = dlp.driverId 
			),(
		SELECT
			dr.driver 
		FROM
			dutyrecord dr 
		WHERE
			dr.pastureid = dlp.pastureid 
			AND dr.eqid = dlp.tmrid 
			AND dr.times = dlp.times 
			AND dr.operatetime <= dlp.mydate 
		ORDER BY
			dr.operatetime DESC 
			LIMIT 1 
		)) driverName 
FROM
	downloadedplan dlp 
WHERE
	havebutton = 1 
	AND mydate = ?  `, date).Query().List()
	if err != nil {
		logging.Error(err)
		return err
	}

	dataByte, _ := json.Marshal(&dataList)
	reqJson := `{
		"apiId": "getKPTData ", 
		"param": {
			"farmId": "%s",
				"method":"getplaninfo",
				"rowCount": %d,
				"resultData":%s
		}
	}`

	reqJson = fmt.Sprintf(reqJson, farmId, len(dataList), string(dataByte))
	fmt.Println(reqJson)
	postPush(reqJson, 2, tx, pastureId, token)
	return nil
}

//搅拌
func YcUtirPush(pastureId, farmId, date, token string) error {
	tx := restful.Engine.NewSession()
	defer tx.Close()
	var now string
	if date != "" {
		now = date
	} else {
		now = time.Now().AddDate(0, 0, -1).Format("2006-01-02")
	}

	dataList, err := tx.SQL(`select date_format(d1.date,'%Y-%m-%d')  dropDate,d.times loadShift,d.datacaptureno  tmrNo,ft.tcode recipeId,ft.ccname recipeName,if(d1.feedcode = -1 ,d1.fid,f.feedcode) ingId,ifnull(f.fname,ftd.fname)  ingName,
	ifnull(ifnull(fc.fcname,(select fcname from feedclass fc1 join feed f1 on f1.fclassid = fc1.id where f1.id =ftd.fid )),'饲料') ingType,
	ifnull(f.dry * d1.actualweightminus,0)  dmPct,d1.sort mixNo,ifnull(d1.feedallowratio,0) allowableError , if(f.fname is not null, ifnull(d1.lweight,''),	ifnull(ftd.fweight / (select sum(fweight)  from ftdetaildate  where  date =  d1.date and ftid = d1.fid ) *  d1.lweight,"") )  expWeight,
	
	if(f.fname is not null, ifnull(d1.actualweightminus,''),	ifnull(ftd.fweight / (select sum(fweight)  from ftdetaildate  where  date =  d1.date and ftid = d1.fid ) *  d1.actualweightminus,"") ) actualWeight,
	DATE_FORMAT(IFNULL((SELECT MAX(intime) FROM downloadplandtl1 d2 
WHERE  d1.pid=d2.pid AND d1.pastureid = d2.pastureid AND d2.intime<d1.intime)
, (SELECT MAX(intime) FROM downloadedplan d2 
WHERE  d1.date=d2.mydate AND d1.pastureid = d2.pastureid AND d2.id=d1.pid)
), '%Y-%m-%d %H:%i:%s') 
   startTime  ,
	 date_format(d1.intime,'%Y-%m-%d %H:%i:%s')   endTime, driver.drivername tmrName ,d1.feedallowratio allowable_error
	from downloadplandtl1  d1 join  downloadedplan d on d.id = d1.pid
	left join feedtempletdate ft  on ft.id = d.tempid  and ft.date = d1.date
	left join feed f on f.feedcode  = d1.feedcode
	left join feedclass fc on fc.id = f.fclassid
	left join ftdetaildate  ftd  on  ftd.date =  d1.date and ftd.ftid = d1.fid
	join tmr t on t.id = d.tmrid 
	left join  driver on driver.drivercode = t.eqcode
	where d1.date = ? and d.havebutton = 1 and d1.type = 0 `, now).Query().List()
	if err != nil {
		logging.Error(err)
		return err
	}

	dataByte, _ := json.Marshal(&dataList)

	reqJson := `{
    "reqMethod": "PARTY",
    "param": {
        "code": "1",
        "method": "uploadadddata",
        "resultData": %s,
        "farmId": "%s",
        "rowCount": %d,
        "errMessage": ""
    },
    "regCode": "cpt180511",
    "command": "3d6e4752",
    "apiId": "getCptData"
}`

	reqJson = fmt.Sprintf(reqJson, string(dataByte), farmId, len(dataList))
	postPush(reqJson, 0, tx, pastureId, token)
	fmt.Println(reqJson)
	return nil
}

func YcBarFeedRemainPush(pastureId, farmId, date, token string) error {
	tx := restful.Engine.NewSession()
	defer tx.Close()

	var now string
	if date != "" {
		now = date
	} else {
		now = time.Now().AddDate(0, 0, -1).Format("2006-01-02")
	}

	dataList, err := tx.SQL(`SELECT
	date_format( remaindate, '%Y-%m-%d' ) overplusDate,
	ifnull(b.bcode,b.id) AS penId,
	b.BNAME AS penName,
	br.Remain AS actualWeight
FROM
	barfeedremain br
	LEFT JOIN feedp fp ON br.barid = fp.barid
	left join bar b on b.id = fp.barid
WHERE
	date_format( remaindate, '%Y-%m-%d' ) =?  `, now).Query().List()
	if err != nil {
		logging.Error(err)
		return err
	}

	dataByte, _ := json.Marshal(&dataList)

	reqJson := `{
    "reqMethod": "PARTY",
    "param": {
        "code": "1",
        "method": "uploadoverplusdata",
        "resultData": %s,
        "farmId":"%s",
        "rowCount": %d,
        "errMessage": ""
    },
    "regCode": "cpt180511",
    "command": "3d6e4752",
    "apiId": "getCptData"
}`
	reqJson = fmt.Sprintf(reqJson, string(dataByte), farmId, len(dataList))
	//  '0饲喂  1剩料  2原料  3栏舍  4配方 5栏舍牛头数 6库存',
	fmt.Println(reqJson)
	postPush(reqJson, 1, tx, pastureId, token)
	return nil
}

func YcMaterialIssuePush(pastureId, farmId, date, token string) error {
	tx := restful.Engine.NewSession()
	defer tx.Close()

	var now string
	if date != "" {
		now = date
	} else {
		now = time.Now().AddDate(0, 0, -1).Format("2006-01-02")
	}

	dataList, err := tx.SQL(`SELECT 
	DATE_FORMAT(d.mydate,'%Y-%m-%d')  dropDate,
	d.datacaptureno tmrNo,
	d.times dropShift,
	b.bcode penId,
	b.bname penName,
	fp.ccount  cowCount,
	d2.sort feedingNo,
	d2.lweight expWeight,
	d2.actualweight actualWeight,
	if((select count(1)  from downloadplandtl2 where pid = d.id and sort < d2.sort ) = 0 ,(select  DATE_FORMAT(intime,'%Y-%m-%d %H:%i:%s')  from downloadplandtl1 where pid = d.id  order by sort desc limit 1 ),(select  DATE_FORMAT(intime,'%Y-%m-%d %H:%i:%s')  from downloadplandtl2 where pid = d.id and sort < d2.sort  order by sort desc limit 1)) startTime,
	 DATE_FORMAT(d2.intime,'%Y-%m-%d %H:%i:%s')  endTime,
	 d.tmrtname tmrName, driver.drivername  driverName,d.id planId,1 calculation,
	 ifnull((select weight  from fpdetaildate where date = d2.date and barid = d2.fbarid  and times = 1 ) ,0) shift1,
	  ifnull( (select weight  from fpdetaildate where date = d2.date and barid = d2.fbarid  and times = 2 ) ,0) shift2,
	  ifnull( (select weight  from fpdetaildate where date = d2.date and barid = d2.fbarid  and times = 3 ) ,0) shift3,
		 ifnull( (select weight  from fpdetaildate where date = d2.date and barid = d2.fbarid  and times = 4 ) ,0) shift4,
		  ifnull( (select weight  from fpdetaildate where date = d2.date and barid = d2.fbarid  and times = 5 ) ,0) shift5,
		ifnull( (select weight  from fpdetaildate where date = d2.date and barid = d2.fbarid  and times = 6 ),0)  shift6,
		d.tempid  recipeId,d.templetname recipeName,   d.completedtime  isCompleted
	FROM
		downloadedplan d
		JOIN downloadplandtl2 d2 ON d.id = d2.pid
		JOIN bar b ON d2.fbarid = b.id
		join feedp fp on fp.barid = b.id 
			join tmr t on t.id = d.tmrid 
		left join driver on driver.drivercode = t.eqcode where d.mydate = ? and d.havebutton = 1
	 `, now).Query().List()
	if err != nil {
		logging.Error(err)
		return err
	}

	dataByte, _ := json.Marshal(&dataList)

	reqJson := `{
    "reqMethod": "PARTY",
    "param": {
        "code": "1",
        "method": "uploaddiliverdata",
        "resultData": %s,
        "farmId": "%s",
        "rowCount": %d,
        "errMessage": ""
    },
    "regCode": "cpt180511",
    "command": "3d6e4752",
    "apiId": "getCptData"
}`
	reqJson = fmt.Sprintf(reqJson, string(dataByte), farmId, len(dataList))
	//  '0饲喂  1剩料  2原料  3栏舍  4配方 5栏舍牛头数 6库存',
	postPush(reqJson, 0, tx, pastureId, token)
	fmt.Println(reqJson)
	return nil
}

func syncBar(token, pastureid string) {

	req, err := http.NewRequest("GET", "https://test.vmuyun.com/project-server/openApi/feeding/penList", nil)
	if err != nil {
		logs.Error(err)
		// return nil
	}
	req.Header.Set("Authorization", token)
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logs.Error(err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	// fmt.Println(string(body)
	data := make(map[string]interface{}, 0)
	json.Unmarshal(body, &data)
	dataList := data["data"].([]interface{})

	tx := restful.Engine.NewSession()
	defer tx.Close()

	for _, item := range dataList {
		arg := item.(map[string]interface{})
		fmt.Println(arg)
		_, err := tx.Exec(` insert into bar(pen,bname,bcode,pastureid)values(?,?,?,?)  ON DUPLICATE KEY UPDATE  pen = ? `, arg["districtName"],
			fmt.Sprintf("%v-%v", arg["houseName"], arg["compartmentName"]), fmt.Sprintf("%v-%v", arg["houseName"], arg["compartmentName"]), pastureid, arg["houseName"])
		fmt.Println(err)
	}

}