package google

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"git.trj.tw/golang/mtfosbot/module/apis"

	"git.trj.tw/golang/mtfosbot/module/config"
)

var baseURL = "https://www.googleapis.com"

func getURL(p string, querystring ...interface{}) (string, bool) {
	u, err := url.Parse(baseURL)
	if err != nil {
		return "", false
	}
	ref, err := u.Parse(p)
	if err != nil {
		return "", false
	}
	if len(querystring) > 0 {
		switch querystring[0].(type) {
		case string:
			ref, err = ref.Parse(fmt.Sprintf("?%s", (querystring[0].(string))))
			if err != nil {
				return "", false
			}
			break
		default:
		}
	}

	str := ref.String()
	return str, true
}

func getHeaders(token ...interface{}) map[string]string {
	m := make(map[string]string)
	m["Content-Type"] = "application/json"
	return m
}

type channelItem struct {
	ID      string         `json:"id"`
	Sinppet channelSinppet `json:"sinppet"`
}
type channelSinppet struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	CustomURL   string `json:"customUrl"`
}

// QueryYoutubeName -
func QueryYoutubeName(id string) (n string, err error) {
	conf := config.GetConf()
	if len(id) == 0 {
		return "", errors.New("id is empty")
	}
	qs := url.Values{}
	qs.Add("id", id)
	qs.Add("key", conf.Google.APIKey)
	qs.Add("part", "snippet")

	apiURL, ok := getURL("/youtube/v3/channels", qs.Encode())
	if !ok {
		return "", errors.New("url parser fail")
	}
	reqObj := apis.RequestObj{
		Method:  "GET",
		URL:     apiURL,
		Headers: getHeaders(),
	}

	req, err := apis.GetRequest(reqObj)
	if err != nil {
		return "", err
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 || !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") {
		return "", errors.New("api response fail")
	}

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	apiRes := struct {
		Items []channelItem `json:"items"`
	}{}

	err = json.Unmarshal(bodyBytes, &apiRes)
	if err != nil {
		return "", err
	}

	if len(apiRes.Items) == 0 {
		return "", errors.New("channel data not found")
	}

	for _, v := range apiRes.Items {
		if v.ID == id {
			return v.Sinppet.Title, nil
		}
	}

	return "", errors.New("channel data not found")
}

// SubscribeYoutube -
func SubscribeYoutube(id string) {
	if len(id) == 0 {
		return
	}
	conf := config.GetConf()
	apiURL := "https://pubsubhubbub.appspot.com/subscribe"
	cbURL, err := url.Parse(conf.URL)
	if err != nil {
		return
	}
	cbURL, err = cbURL.Parse(fmt.Sprintf("/google/youtube/webhook?id=%s", id))
	if err != nil {
		return
	}

	qs := url.Values{}
	qs.Add("hub.mode", "subscribe")
	qs.Add("hub.verify", "async")
	qs.Add("hub.topic", fmt.Sprintf("https://www.youtube.com/xml/feeds/videos.xml?channel_id=%s", id))
	qs.Add("hub.callback", cbURL.String())
	qs.Add("hub.lease_seconds", "86400")

	req, err := http.NewRequest("POST", apiURL, strings.NewReader(qs.Encode()))
	if err != nil {
		return
	}
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	return
}
