package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"sort"

	"github.com/AlecAivazis/survey"
)

type Region struct {
	RegionID          string        `json:"regionID"`
	BasicServiceAreas []ServiceArea `json:"basicServiceAreas"`
	RegionName        string        `json:"regionName"`
	Active            bool          `json:"active"`
}

type ServiceArea struct {
	ServiceAreaID         string   `json:"serviceAreaID"`
	Operational           bool     `json:"operational"`
	OnboardingEnabled     bool     `json:"onboardingEnabled"`
	DefaultStationCode    string   `json:"defaultStationCode"`
	AvailableOMWPrograms  []string `json:"availableOMWPrograms"`
	DefaultAccessPointID  string   `json:"defaultAccessPointId"`
	ProgramTypes          []string `json:"programTypes"`
	CountryCode           string   `json:"countryCode"`
	PickUpLocationAddress struct {
		CountryCode string      `json:"countryCode"`
		PostalCode  string      `json:"postalCode"`
		City        string      `json:"city"`
		Phone       interface{} `json:"phone"`
		State       string      `json:"state"`
		Address3    interface{} `json:"address3"`
		Address2    interface{} `json:"address2"`
		Address1    string      `json:"address1"`
		Name        string      `json:"name"`
	} `json:"pickUpLocationAddress"`
	OperatingEntity string `json:"operatingEntity"`
	TimeZone        string `json:"timeZone"`
	PickUpLocation  struct {
		Longitude float64 `json:"longitude"`
		Latitude  float64 `json:"latitude"`
	} `json:"pickUpLocation"`
	ServiceAreaName string `json:"serviceAreaName"`
}

type PersonalInfo struct {
	Address  string `json:"address"`
	Address2 string `json:"address2"`
	Fname    string `json:"firstName"`
	Lname    string `json:"lastName"`
	City     string `json:"city"`
	State    string `json:"state"`
	Zip      string `json:"postalCode"`
	Phone    string `json:"phoneNumber"`
	County   string `json:"county"`
	Country  string `json:"countryCode"`
}

func main() {
	fmt.Println("First we need to log into our account before we can continue")
	loginq := []*survey.Question{
		{
			Name:   "email",
			Prompt: &survey.Input{Message: "Email:"},
		},
		{
			Name:   "password",
			Prompt: &survey.Password{Message: "Password:"},
		},
	}
	logina := struct {
		Email    string
		Password string
	}{}
	survey.Ask(loginq, &logina)
	api_file, err := os.Open("amazon-api.json")
	defer api_file.Close()
	if err != nil {
		fmt.Println("Required files are missing, are you sure you have permission to run this?")
		return
	}
	json.NewDecoder(api_file).Decode(&api)
	api.Payload.AuthData.User.UserId = logina.Email
	api.Payload.AuthData.User.Password = logina.Password
	login()
	log_cookies()
	choicea := ""
	choiceq := &survey.Select{
		Message: "Choose an option:",
		Options: []string{"Region/Warehouse", "Personal Info"},
	}
	survey.AskOne(choiceq, &choicea, nil)
	switch choicea {
	case "Region/Warehouse":
		location()
	case "Personal Info":
		personal()
	}
}

func location() {
	var regions []Region
	resp, err := http.Get("https://logistics.amazon.com/flex/api/getOperationalRegions")
	if err != nil {
		fmt.Println(err.Error())
	}
	json.NewDecoder(resp.Body).Decode(&regions)
	var region_list []string
	for _, reg := range regions {
		region_list = append(region_list, reg.RegionName)
	}
	sort.Strings(region_list)
	rega := ""
	regq := &survey.Select{
		Message: "Choose Region:",
		Options: region_list,
	}
	survey.AskOne(regq, &rega, nil)
	var services []ServiceArea
	var regionid string
	for _, reg := range regions {
		if reg.RegionName == rega {
			regionid = reg.RegionID
			services = reg.BasicServiceAreas
			break
		}
	}
	var wh_list []string
	for _, wh := range services {
		for _, prog := range wh.AvailableOMWPrograms {
			if prog == "CSP" {
				wh_list = append(wh_list, wh.ServiceAreaName)
				break
			}
		}
	}
	sort.Strings(wh_list)
	wha := ""
	whq := &survey.Select{
		Message: "Choose Warehouse:",
		Options: wh_list,
	}
	survey.AskOne(whq, &wha, nil)
	var serviceareaid string
	for _, wh := range services {
		if wh.ServiceAreaName == wha {
			serviceareaid = wh.ServiceAreaID
			break
		}
	}
	fmt.Printf("Region: %s\nWarehouse: %s\n", regionid, serviceareaid)
	reg_body := struct {
		Region string `json:"regionId"`
	}{regionid}
	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(reg_body)
	reg_req, _ := http.NewRequest("POST", "https://logistics.amazon.com/onboarding/data/update-region", b)
	reg_req.Header.Add("User-Agent", api.Headers.Refresh)
	reg_req.Header.Add("X-Requested-With", "com.amazon.rabbit")
	reg_req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	for _, one := range logistics.Response.Tokens.Cookies.AmazonCom {
		reg_req.Header.Add("Cookie", fmt.Sprintf("%s=%s", one.Name, one.Value))
	}
	client := &http.Client{}
	reg_resp, _ := client.Do(reg_req)
	defer reg_resp.Body.Close()
	var body struct {
		Success  bool   `json:"success"`
		DirectTo string `json:"directTo"`
		Error    string `json:"errorReasonCode"`
		Data     string `json:"data"`
	}
	json.NewDecoder(reg_resp.Body).Decode(&body)
	if body.Success {
		fmt.Println("Region Successfully Changed")
	} else {
		fmt.Println("Region Change Failed", reg_resp.StatusCode, body.Error)
	}
	FlexHead.Setup()
	wh_body := struct {
		Type    string   `json:"__type"`
		Service []string `json:"serviceAreaIds"`
	}{"SetEligibleServiceAreasInput:http://internal.amazon.com/coral/com.amazon.omwbuseyservice/", []string{serviceareaid}}
	wh_b := new(bytes.Buffer)
	json.NewEncoder(wh_b).Encode(wh_body)
	wh_req, _ := http.NewRequest("POST", "https://flex-capacity-na.amazon.com/eligibleServiceAreas", wh_b)
	wh_req.Header = FlexHead.Auth(wh_req.Method, wh_req.URL.Path, wh_req.Host)
	wh_resp, _ := client.Do(wh_req)
	defer wh_resp.Body.Close()
	if wh_resp.StatusCode == 200 {
		fmt.Println("Warehouse Successfully Changed")
	} else {
		fmt.Println("Warehouse Change Failed")
	}
	io.Copy(ioutil.Discard, wh_resp.Body)
}

func personal() {
	fmt.Println("Changing User Info May Trigger a Tax Info Update")
	var body_response struct {
		Success  bool         `json:"success"`
		DirectTo string       `json:"directTo"`
		Error    string       `json:"errorReasonCode"`
		Data     PersonalInfo `json:"data"`
	}
	get_req, _ := http.NewRequest("GET", "https://logistics.amazon.com/onboarding/account/data/get-personal-info", nil)
	get_req.Header.Add("User-Agent", api.Headers.Refresh)
	get_req.Header.Add("X-Requested-With", "com.amazon.rabbit")
	get_req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	for _, one := range logistics.Response.Tokens.Cookies.AmazonCom {
		get_req.Header.Add("Cookie", fmt.Sprintf("%s=%s", one.Name, one.Value))
	}
	client := &http.Client{}
	get_resp, _ := client.Do(get_req)
	defer get_resp.Body.Close()
	json.NewDecoder(get_resp.Body).Decode(&body_response)
	infoq := []*survey.Question{
		{
			Name: "fname",
			Prompt: &survey.Input{Message: "First Name:",
				Default: body_response.Data.Fname,
			},
		},
		{
			Name: "lname",
			Prompt: &survey.Input{Message: "Last Name:",
				Default: body_response.Data.Lname,
			},
		},
		{
			Name: "address",
			Prompt: &survey.Input{Message: "Address:",
				Default: body_response.Data.Address,
			},
		},
		{
			Name: "address2",
			Prompt: &survey.Input{Message: "Address2:",
				Default: body_response.Data.Address2,
			},
		},
		{
			Name: "city",
			Prompt: &survey.Input{Message: "City:",
				Default: body_response.Data.City,
			},
		},
		{
			Name: "state",
			Prompt: &survey.Input{Message: "State:",
				Default: body_response.Data.State,
			},
		},
		{
			Name: "zip",
			Prompt: &survey.Input{Message: "Zip:",
				Default: body_response.Data.Zip,
			},
		},
		{
			Name: "county",
			Prompt: &survey.Input{Message: "County:",
				Default: body_response.Data.County,
			},
		},
		{
			Name: "country",
			Prompt: &survey.Input{Message: "Country:",
				Default: body_response.Data.Country,
			},
		},
		{
			Name: "phone",
			Prompt: &survey.Input{Message: "Phone Number:",
				Default: body_response.Data.Phone,
			},
		},
	}
	var infoa PersonalInfo
	survey.Ask(infoq, &infoa)
	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(infoa)
	set_req, _ := http.NewRequest("POST", "https://logistics.amazon.com/onboarding/account/data/submit-personal-info", b)
	set_req.Header.Add("User-Agent", api.Headers.Refresh)
	set_req.Header.Add("X-Requested-With", "com.amazon.rabbit")
	set_req.Header.Add("Content-Type", "application/json;charset=UTF-8")
	for _, one := range logistics.Response.Tokens.Cookies.AmazonCom {
		set_req.Header.Add("Cookie", fmt.Sprintf("%s=%s", one.Name, one.Value))
	}
	set_resp, _ := client.Do(set_req)
	defer set_resp.Body.Close()
	json.NewDecoder(set_resp.Body).Decode(&body_response)
	if body_response.Success {
		fmt.Println("Info Successfully Updated")
	}
}
