package JntExpressMalaysia

import (
	"bytes"
	"crypto/md5"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
)

func CreateShipment() {
	OrderID := "U1008"
	createShipmentResponse, err := postCreateShipment(&CreateShipmentRequest{
		Detail: []CreateShipmentRequestDetail{{
			Username:        "TEST",
			ApiKey:          "TES123",
			CustomerCode:    "ITTEST0001",
			Password:        "1234",
			OrderID:         OrderID,
			SenderName:      "Phuc Phan",
			SenderAddress:   "TEST ADDRESS",
			SenderContact:   "Phuc Phan",
			SenderPhone:     "60123698745",
			SenderZip:       "59200",
			ReceiverName:    "Poogky",
			ReceiverAddress: "TEST ADDRESS",
			ReceiverZip:     "83000",
			ReceiverPhone:   "60123456789",
			Quantity:        "3",
			Weight:          "50.12",
			ServiceType:     ServiceTypePickup,
			ItemName:        "IPHONE12",
			GoodsDesc:       "THIS IS REMARK",
			GoodsValue:      520,
			GoodsType:       GoodsTypeParcel,
			PayType:         PayTypePPPM,
			OfferFeeFlag:    OfferFeeFlagYes,
			ExpressType:     ExpressTypeEZ,
			Height:          "5",
			Length:          "5",
			Width:           "5",
			COD:             "100",
		}},
	})

	if err != nil {
		log.Println("Error", err)
		return
	}

	if createShipmentResponse.Details == nil || len(createShipmentResponse.Details) == 0 {
		log.Println("createShipmentResponse.Details empty")
		return
	}

	log.Println("Response", createShipmentResponse.Details[0].Data)
}

func CancelShipment() {
	AwbNo := "630020261448"
	OrderID := "U1007"
	cancelShipmentResponse, err := postCancelShipment(&CancelShipmentRequest{
		Username: "TEST",
		ApiKey:   "TES123",
		AwbNo:    AwbNo,
		OrderID:  OrderID,
		Remark:   "Seller cancelled",
	})

	if err != nil {
		log.Println("Error", err)
	}

	log.Println("Response", cancelShipmentResponse)
}

func GetTracking() {
	billCode := "630020261546"
	getTrackingResponse, err := postGetTracking(&GetTrackingRequest{
		QueryCodes: billCode,
		QueryType:  QueryTypeBillCode,
		Language:   LanguageEnglish,
	})

	if err != nil {
		log.Println("Error", err)
	}

	log.Println("Response", getTrackingResponse)
}

func GetWaybill() {
	billCode := "630020262206"
	getTrackingResponse, err := postGetWaybill(&GetWaybillRequest{
		Account:      "TEST",
		CustomerCode: "600000V013",
		Password:     "dKbxOE",
		BillCode:     billCode,
	})

	if err != nil {
		log.Println(err)
	}

	result, err := ioutil.ReadAll(getTrackingResponse.Data)
	if err != nil {
		log.Println(err)
	}

	if err := ioutil.WriteFile("waybill.pdf", result, 0644); err != nil {
		log.Println(err)
	}
}

func GetPostalCode() {
	getPostalCodeResponse, err := postGetPostalCode(&GetPostalCodeRequest{
		Size: PostalCodeSizeLessThanOrEqual3Kg,
	})

	if err != nil {
		log.Println(err)
	}

	log.Println(getPostalCodeResponse.Msg)
}

func post(path string, payload interface{}, response interface{}) error {
	//account: TEST
	//password: TES123
	secret := "AKe62df84bJ3d8e4b1hea2R45j11klsb"
	endpoint := "http://47.57.89.30/blibli" + path
	jsonStr, _ := json.Marshal(payload)
	dataParam := string(jsonStr)
	dataSign := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%x", md5.Sum([]byte(dataParam+secret)))))
	data := url.Values{
		"data_sign":  {dataSign},
		"data_param": {dataParam},
	}

	fmt.Println("Endpoint:", endpoint)
	fmt.Println("Request:", dataParam)

	res, err := http.PostForm(endpoint, data)
	if err != nil {
		return err
	}

	result, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return err
	}

	fmt.Println("Response:", string(result))

	if err := json.Unmarshal(result, &response); err != nil {
		return err
	}

	return nil
}

func postCreateShipment(createShipmentRequest *CreateShipmentRequest) (*CreateShipmentResponse, error) {
	createShipmentResponse := CreateShipmentResponse{}
	if err := post("/order/createOrder", createShipmentRequest, &createShipmentResponse); err != nil {
		return nil, err
	}
	return &createShipmentResponse, nil
}

func postCancelShipment(cancelShipmentRequest *CancelShipmentRequest) (*CancelShipmentResponse, error) {
	cancelShipmentResponse := CancelShipmentResponse{}
	if err := post("/order/cancelOrder", cancelShipmentRequest, &cancelShipmentResponse); err != nil {
		return nil, err
	}
	return &cancelShipmentResponse, nil
}

func postGetTracking(getTrackingRequest *GetTrackingRequest) (*GetTrackingResponse, error) {
	secret := "ffe62df84bb3d8e4b1eaa2c22775014d"
	endpoint := "http://47.57.89.30/common/track/trackings"
	jsonStr, _ := json.Marshal(getTrackingRequest)
	dataParam := string(jsonStr)
	dataSign := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%x", md5.Sum([]byte(dataParam+secret)))))
	data := url.Values{
		"logistics_interface": {dataParam},
		"data_digest":         {dataSign},
		"msg_type":            {"TRACK"},
		"eccompanyid":         {"TEST"},
	}

	fmt.Println("Endpoint:", endpoint)
	fmt.Println("Request:", dataParam)

	res, err := http.PostForm(endpoint, data)
	if err != nil {
		return nil, err
	}

	result, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	fmt.Println("Response:", string(result))

	getWaybillResponse := GetTrackingResponse{}
	if err := json.Unmarshal(result, &getWaybillResponse); err != nil {
		return nil, err
	}

	return &getWaybillResponse, nil
}

func postGetWaybill(getWaybillRequest *GetWaybillRequest) (*GetWaybillResponse, error) {
	endpoint := "http://47.57.89.30/jandt_web/print/facelistAction!print.action"
	jsonStr, _ := json.Marshal(getWaybillRequest)
	dataParam := string(jsonStr)
	dataSign := fmt.Sprintf("%x", md5.Sum([]byte(getWaybillRequest.BillCode)))
	data := url.Values{
		"logistics_interface": {dataParam},
		"data_digest":         {dataSign},
		"msg_type":            {"1"},
	}

	fmt.Println("Endpoint:", endpoint)
	fmt.Println("Request:", dataParam)

	res, err := http.PostForm(endpoint, data)
	if err != nil {
		return nil, err
	}

	fmt.Println("Response: binary data")

	return &GetWaybillResponse{
		Data: res.Body,
	}, nil
}

func postGetPostalCode(getPostalCodeRequest *GetPostalCodeRequest) (*GetPostalCodeResponse, error) {
	secret := "ffe62df84bb3d8e4b1eaa2c22775014d"
	endpoint := "http://47.57.89.30/open/api/postCode/list"
	jsonStr, _ := json.Marshal(getPostalCodeRequest)
	dataParam := string(jsonStr)
	h := sha256.New()
	h.Write([]byte(dataParam + secret))
	dataSign := hex.EncodeToString(h.Sum(nil))

	fmt.Println("Endpoint:", endpoint)
	fmt.Println("Request:", dataParam)

	client := &http.Client{}
	req, _ := http.NewRequest("POST", endpoint, bytes.NewBuffer(jsonStr))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("account", "TEST")
	req.Header.Set("sign", dataSign)
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	result, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	getPostalCodeResponse := GetPostalCodeResponse{}
	if err := json.Unmarshal(result, &getPostalCodeResponse); err != nil {
		return nil, err
	}

	return &getPostalCodeResponse, nil
}
