package apidApigeeSync

import (
	"encoding/json"
	"github.com/30x/apid"
	"github.com/30x/apid/factory"
	"github.com/apigee-labs/transicator/common"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"time"
)

var _ = Describe("api", func() {

	var server *httptest.Server

	BeforeSuite(func() {
		apid.Initialize(factory.DefaultServicesFactory())
	})

	AfterSuite(func() {
		apid.Events().Close()
		server.Close()
	})

	It("perform sync round-trip", func(done Done) {
		scount := 0
		phase := 0
		scope := "bootstrap"
		key := "XXXXXXX"
		secret := "YYYYYYY"

		// mock upstream server
		server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {

			// first request is for a token
			if req.URL.Path == "/accesstoken" {
				Expect(req.Method).To(Equal("POST"))
				Expect(req.Header.Get("Content-Type")).To(Equal("application/x-www-form-urlencoded; param=value"))

				err := req.ParseForm()
				Expect(err).NotTo(HaveOccurred())
				Expect(req.Form.Get("grant_type")).To(Equal("client_credentials"))

				res := oauthTokenResp{}
				res.AccessToken = "accesstoken"
				body, err := json.Marshal(res)
				Expect(err).NotTo(HaveOccurred())
				w.Write(body)
				return
			}

			// next requests are for changes
			if req.URL.Path == "/snapshots" {
				Expect(req.Method).To(Equal("GET"))
				q := req.URL.Query()

				if phase == 0 {
					phase = 1
					Expect(q.Get("scope")).To(Equal(scope))

					apidcfgItem := common.Row{}
					apidcfgItems := []common.Row{}
					apidcfgItemCh := common.Row{}
					apidcfgItemsCh := []common.Row{}
					scv := &common.ColumnVal{
						Value: scope,
						Type:  1,
					}
					apidcfgItem["id"] = scv
					scv = &common.ColumnVal{
						Value: scope,
						Type:  1,
					}
					apidcfgItem["_apid_scope"] = scv
					apidcfgItems = append(apidcfgItems, apidcfgItem)

					scv = &common.ColumnVal{
						Value: "apid_config_scope_id_0",
						Type:  1,
					}
					apidcfgItemCh["id"] = scv

					scv = &common.ColumnVal{
						Value: "apid_config_scope_id_0",
						Type:  1,
					}
					apidcfgItemCh["_apid_scope"] = scv

					scv = &common.ColumnVal{
						Value: scope,
						Type:  1,
					}
					apidcfgItemCh["apid_config_id"] = scv

					scv = &common.ColumnVal{
						Value: "att~prod",
						Type:  1,
					}
					apidcfgItemCh["scope"] = scv

					apidcfgItemsCh = append(apidcfgItemsCh, apidcfgItemCh)

					res := &common.Snapshot{}
					res.SnapshotInfo = "snapinfo1"

					res.Tables = []common.Table{
						{
							Name: "edgex.apid_config",
							Rows: apidcfgItems,
						},
						{
							Name: "edgex.apid_config_scope",
							Rows: apidcfgItemsCh,
						},
					}

					body, err := json.Marshal(res)
					Expect(err).NotTo(HaveOccurred())
					w.Write(body)
					return
				} else {
					phase = 2
					Expect(q.Get("scope")).To(Equal("att~prod"))
					res := &common.Snapshot{}
					res.SnapshotInfo = "snapinfo1"

					apidcfgItems := []common.Row{}
					res.Tables = []common.Table{
						{
							Name: "kms.api_product",
							Rows: apidcfgItems,
						},
					}

					body, err := json.Marshal(res)
					Expect(err).NotTo(HaveOccurred())
					w.Write(body)
					return
				}

			}
			// next requests are for changes
			if req.URL.Path == "/changes" {
				Expect(req.Method).To(Equal("GET"))
				q := req.URL.Query()
				Expect(q.Get("snapshot")).To(Equal("snapinfo1"))
				scparams := q["scope"]
				Expect(scparams).To(ContainElement("att~prod"))
				Expect(scparams).To(ContainElement("bootstrap"))

				res := &common.ChangeList{}

				res.LastSequence = "lastSeq_01"
				mpItems := common.Row{}

				scv := &common.ColumnVal{
					Value: "apid_config_scope_id_1",
					Type:  1,
				}
				mpItems["id"] = scv

				scv = &common.ColumnVal{
					Value: scope,
					Type:  1,
				}
				mpItems["apid_config_id"] = scv

				scv = &common.ColumnVal{
					Value: "att~test",
					Type:  1,
				}
				mpItems["scope"] = scv

				res.Changes = []common.Change{
					{
						Table:     "edgex.apid_config_scope",
						NewRow:    mpItems,
						Operation: 1,
					},
				}
				body, err := json.Marshal(res)
				Expect(err).NotTo(HaveOccurred())
				w.Write(body)
				return
			}
			Fail("should not reach")
		}))

		config = apid.Config()
		config.Set(configProxyServerBaseURI, server.URL)
		config.Set(configSnapServerBaseURI, server.URL)
		config.Set(configChangeServerBaseURI, server.URL)
		config.Set(configScopeId, "apid_config_scope_0")
		config.Set(configSnapshotProtocol, "json")
		config.Set(configScopeId, scope)
		config.Set(configConsumerKey, key)
		config.Set(configConsumerSecret, secret)

		// set up temporary test database
		tmpDir, err := ioutil.TempDir("", "apigee_sync_test")
		Expect(err).NotTo(HaveOccurred())
		defer os.RemoveAll(tmpDir)

		config.Set("data_path", tmpDir)

		// start process -  plugin will automatically start polling
		apid.InitializePlugins()

		h := &test_handler{
			"sync data",
			func(event apid.Event) {
				_, ok := event.(*common.Snapshot)
				if ok {
					if phase > 1 {
						db, err := data.DB()
						Expect(err).NotTo(HaveOccurred())
						// verify event data (post snapshot)
						err = db.QueryRow("Select count(scp.id) from apid_config_scope as scp INNER JOIN apid_config as ap WHERE scp.apid_config_id = ap.id").Scan(&scount)
						Expect(err).NotTo(HaveOccurred())
						Expect(scount).Should(Equal(1))
					}
				} else {
					// verify event data (post change)
					// There should be 2 scopes now
					_, ok := event.(*common.ChangeList)
					if ok {
						time.Sleep(200 * time.Millisecond)
						db, err := data.DB()
						Expect(err).NotTo(HaveOccurred())
						err = db.QueryRow("Select count(scp.id) from apid_config_scope as scp INNER JOIN apid_config as ap WHERE scp.apid_config_id = ap.id").Scan(&scount)
						Expect(err).NotTo(HaveOccurred())
						Expect(scount).Should(Equal(2))
						close(done)
					} else {
						Fail("Unexpected event")
					}
				}

			},
		}

		apid.Events().Listen(ApigeeSyncEventSelector, h)
	})
})

type test_handler struct {
	description string
	f           func(event apid.Event)
}

func (t *test_handler) String() string {
	return t.description
}

func (t *test_handler) Handle(event apid.Event) {
	t.f(event)
}
