package main

import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type billing struct {
}

func (b billing) list(c echo.Context) error {

	type InvoiceLists struct {
		Embedded struct {
			IaaSInvoices []struct {
				CreatedAt       time.Time `json:"createdAt"`
				UpdatedAt       time.Time `json:"updatedAt"`
				UUID            string    `json:"uuid"`
				CustomerID      string    `json:"customerId"`
				Plan            string    `json:"plan"`
				DurationDay     int       `json:"durationDay"`
				VcoreQuantity   int       `json:"vcoreQuantity"`
				VcoreCost       float64   `json:"vcoreCost"`
				RAMQuantity     int       `json:"ramQuantity"`
				RAMCost         float64   `json:"ramCost"`
				StorageQuantity int       `json:"storageQuantity"`
				StorageCost     float64   `json:"storageCost"`
				ExtraIPCount    int       `json:"extraIpCount"`
				ExtraIPCost     float64   `json:"extraIpCost"`
				ExtraBwQuantity int       `json:"extraBwQuantity"`
				ExtraBwCost     float64   `json:"extraBwCost"`
				Sum             float64   `json:"sum"`
				Links           struct {
					Self struct {
						Href string `json:"href"`
					} `json:"self"`
					IaaSInvoice struct {
						Href string `json:"href"`
					} `json:"iaaSInvoice"`
				} `json:"_links"`
			} `json:"iaaSInvoices"`
		} `json:"_embedded"`
		Links struct {
			Self struct {
				Href string `json:"href"`
			} `json:"self"`
		} `json:"_links"`
	}
	type InvoiceListsResponse struct {
		Data []struct {
			SUM          float64   `json:"sum"`
			PaidState    bool      `json:"paidstate"`
			DueDate      time.Time `json:"duedate"`
			RemainedDays int64     `json:"remaineddays"`
			InvoiceUUID  string    `json:"invoiceUUID"`
		} `json:"data"`
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	UserUUID := login(BA).AuthenticatedUser.ID
	url := "http://172.20.15.24/iaaSInvoices/search/findByCustomerIdEquals?customerId=" + UserUUID
	method := "GET"

	client := &http.Client{
	}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
		return nil
	}
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	//fmt.Println(string(body))
	_InvoiceList := InvoiceLists{}
	err = json.Unmarshal(body, &_InvoiceList)
	if err != nil {
		fmt.Println(err)
		//return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice
	}
	//fmt.Println("Length: ", len(_InvoiceList.Embedded.IaaSInvoices))
	_InvoiceListsResponse := InvoiceListsResponse{
		Data:    nil,
		Message: "Done",
		Origin:  "Billing-listInvoices",
		Code:    1000,
	}
	_Data := _InvoiceListsResponse.Data
	x := struct {
		SUM          float64   `json:"sum"`
		PaidState    bool      `json:"paidstate"`
		DueDate      time.Time `json:"duedate"`
		RemainedDays int64     `json:"remaineddays"`
		InvoiceUUID  string    `json:"invoiceUUID"`
	}{}

	y := x
	for _, i := range _InvoiceList.Embedded.IaaSInvoices {
		y.SUM = i.Sum
		y.InvoiceUUID = i.UUID
		y.PaidState = false
		y.DueDate = i.CreatedAt
		y.RemainedDays = (i.CreatedAt.Unix() - time.Now().Unix()) / 3600 / 24
		_Data = append(_Data, y)
	}

	//fmt.Println("length of data: ",len(_Data))

	_InvoiceListsResponse.Data = _Data
	return c.JSON(http.StatusOK, _InvoiceListsResponse)
}

func (b billing) Show(c echo.Context) error {
	type Invoice struct {
		CreatedAt       time.Time `json:"createdAt"`
		UpdatedAt       time.Time `json:"updatedAt"`
		ID              int       `json:"id"`
		UUID            string    `json:"uuid"`
		CustomerID      string    `json:"customerId"`
		Plan            string    `json:"plan"`
		DurationDay     int       `json:"durationDay"`
		VcoreQuantity   int       `json:"vcoreQuantity"`
		VcoreCost       float64   `json:"vcoreCost"`
		RAMQuantity     int       `json:"ramQuantity"`
		RAMCost         float64   `json:"ramCost"`
		StorageQuantity int       `json:"storageQuantity"`
		StorageCost     float64   `json:"storageCost"`
		ExtraIPCount    int       `json:"extraIpCount"`
		ExtraIPCost     float64   `json:"extraIpCost"`
		ExtraBwQuantity int       `json:"extraBwQuantity"`
		ExtraBwCost     float64   `json:"extraBwCost"`
		Sum             float64   `json:"sum"`
	}
	type InvoiceResponse struct {
		Data struct {
			CreatedAt       time.Time `json:"createdAt"`
			UpdatedAt       time.Time `json:"updatedAt"`
			ID              int       `json:"id"`
			UUID            string    `json:"uuid"`
			CustomerID      string    `json:"customerId"`
			Plan            string    `json:"plan"`
			DurationDay     int       `json:"durationDay"`
			VcoreQuantity   int       `json:"vcoreQuantity"`
			VcoreCost       float64   `json:"vcoreCost"`
			RAMQuantity     int       `json:"ramQuantity"`
			RAMCost         float64   `json:"ramCost"`
			StorageQuantity int       `json:"storageQuantity"`
			StorageCost     float64   `json:"storageCost"`
			ExtraIPCount    int       `json:"extraIpCount"`
			ExtraIPCost     float64   `json:"extraIpCost"`
			ExtraBwQuantity int       `json:"extraBwQuantity"`
			ExtraBwCost     float64   `json:"extraBwCost"`
			Sum             float64   `json:"sum"`
		} `json:"data"`
		Message string `json:"message"`
		Origin  string `json:"origin"`
		Code    int    `json:"code"`
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(jwt.MapClaims)
	_sha256 := sha256.Sum256([]byte(string(claims["name"].(string))))
	var hashChannel_ = make(chan []byte, 1)
	hashChannel_ <- _sha256[:]
	token := decrypt(<-hashChannel_, claims["IPAToken"].(string))
	_BA := strings.Split(token, ";")
	BA := _BA[len(_BA)-2]
	UserUUID := login(BA).AuthenticatedUser.ID
	InvoiceUUID := c.FormValue("InvoiceUUID")
	url := "http://172.20.15.24/invoice/iaas/get?uuid=" + InvoiceUUID
	method := "GET"
	client := &http.Client{
	}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
		return nil
	}
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	_Invoice := Invoice{}
	err = json.Unmarshal(body, &_Invoice)
	if err != nil {
		fmt.Println(err)
		//return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice
	}
	if _Invoice.CustomerID != UserUUID {
		resp := _response{
			Origin:  "Billing-ShowInvoice",
			Message: "Unauthorized Access",
			Code:    1001,
		}
		return c.JSON(403, resp)
	}
	_InvoiceResponse := InvoiceResponse{
		Data:    _Invoice,
		Message: "Done",
		Origin:  "Billing-ShowInvoice",
		Code:    1000,
	}
	return c.JSON(http.StatusOK, _InvoiceResponse)
}

func IaaSCreate(UserUUID string, period string, CPU string, memory string, storageVolume string, extraIP string, extraBW string) (CPUPrice float64, memPrice float64, StoragePrice float64, IPPrice float64, extraBWPrice float64, sum float64, InvoiceID string) {
	type CreateResponse struct {
		CreatedAt       time.Time `json:"createdAt"`
		UpdatedAt       time.Time `json:"updatedAt"`
		ID              int       `json:"id"`
		UUID            string    `json:"uuid"`
		CustomerID      string    `json:"customerId"`
		Plan            string    `json:"plan"`
		DurationDay     int       `json:"durationDay"`
		VcoreQuantity   int       `json:"vcoreQuantity"`
		VcoreCost       float64   `json:"vcoreCost"`
		RAMQuantity     int       `json:"ramQuantity"`
		RAMCost         float64   `json:"ramCost"`
		StorageQuantity int       `json:"storageQuantity"`
		StorageCost     float64   `json:"storageCost"`
		ExtraIPCount    int       `json:"extraIpCount"`
		ExtraIPCost     float64   `json:"extraIpCost"`
		ExtraBwQuantity int       `json:"extraBwQuantity"`
		ExtraBwCost     float64   `json:"extraBwCost"`
		Sum             float64   `json:"sum"`
	}
	url := "http://172.20.15.24:80/invoice/iaas/create"
	method := "POST"
	//_period, _ := strconv.Atoi(period)
	_CPU, _ := strconv.Atoi(CPU)
	_memory, _ := strconv.Atoi(memory)
	//_storageVolume := 40//strconv.Atoi(storageVolume)
	_extraIP, _ := strconv.Atoi(extraIP)
	_extraBW, _ := strconv.Atoi(extraBW)
	payload := strings.NewReader(fmt.Sprintf(`{
    "customerId": "%s",
    "durationDay": "%d",
    "vCoreCount": "%d",
    "ramVolume": "%d",
    "storageVolume": "40",
    "extraIPCount": "%d",
    "extraBW": "%d"
}`, UserUUID, 1*30, _CPU, _memory/1024/1024/1024,  _extraIP, _extraBW))
//}`, UserUUID, _period*30, _CPU, _memory/1024/1024/1024, _storageVolume/1024/1024/1024, _extraIP, _extraBW))
	//fmt.Println("Mem1 :",memory," Mem2:",_memory,"Array: ",payload)

	client := &http.Client{
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice, sum, InvoiceID
	}
	req.Header.Add("Content-Type", "application/json")

	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice, sum, InvoiceID
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice, sum, InvoiceID
	}
	//fmt.Println(string(body))
	//return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice
	_CreateResponse := CreateResponse{}
	err = json.Unmarshal(body, &_CreateResponse)
	if err != nil {
		fmt.Println(err)
		//return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice
	}
	CPUPrice = _CreateResponse.VcoreCost
	memPrice = _CreateResponse.RAMCost
	extraBWPrice = _CreateResponse.ExtraBwCost
	IPPrice = _CreateResponse.ExtraIPCost
	StoragePrice = _CreateResponse.StorageCost
	return CPUPrice, memPrice, StoragePrice, IPPrice, extraBWPrice, _CreateResponse.Sum, _CreateResponse.UUID
}
