package service

import (
	"context"
	"encoding/json"
	"net/http"
	"strconv"
	"time"

	"github.com/spf13/viper"

	"data-platform/pkg/errors"
	"data-platform/pkg/log"
)

type connStatus struct {
	Code string `json:"code"`
	Data struct {
		Status struct {
			SyncState string `json:"sync_state"`
		} `json:"status"`
	} `json:"data"`
}

func triggerOrgRevrec(ctx context.Context) error {
	log.L(ctx).Info("start triggerOrgRevrec")

	connID := viper.GetString("fivetran.org-connector-id")
	base64key := viper.GetString("fivetran.base64key")
	baseUrl := viper.GetString("fivetran.base-url")

	url := baseUrl + "connectors/" + connID + "/sync"

	req, err := http.NewRequestWithContext(ctx, "POST", url, nil)
	if err != nil {
		log.L(ctx).Errorf("error creating request: %v", err)

		return err
	}
	req.Header.Set("Authorization", "Basic "+base64key)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.L(ctx).Errorf("error sending request: %v", err)

		return err
	}

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		log.L(ctx).Infof("triggerOrgRevrec success")
	} else {
		log.L(ctx).Errorf("triggerOrgRevrec failed, status code: %v", resp.StatusCode)

		return errors.New("triggerOrgRevrec failed, status code: " + strconv.Itoa(resp.StatusCode))
	}

	// check state
	url = baseUrl + "connectors/" + connID
	req, err = http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		log.L(ctx).Errorf("error creating request: %v", err)

		return err
	}
	req.Header.Set("Authorization", "Basic "+base64key)

	i := 0
	for {
		resp, err = http.DefaultClient.Do(req)
		if err != nil {
			log.L(ctx).Errorf("error sending request: %v", err)

			return err
		}

		if resp.StatusCode >= 200 && resp.StatusCode < 300 {
			log.L(ctx).Infof("get connector status success")
		} else {
			log.L(ctx).Errorf("triggerOrgRevrec failed, status code: %v", resp.StatusCode)

			return errors.New("triggerOrgRevrec failed, status code: " + strconv.Itoa(resp.StatusCode))
		}

		var status connStatus
		if err = json.NewDecoder(resp.Body).Decode(&status); err != nil {
			log.L(ctx).Errorf("error decoding response: %v", err)

			return err
		}

		if status.Data.Status.SyncState == "scheduled" {
			log.L(ctx).Info("triggerOrgRevrec end")

			break
		}

		if status.Data.Status.SyncState != "syncing" {
			log.L(ctx).Error("triggerOrgRevrec failed")

			return errors.New("triggerOrgRevrec failed")
		}

		log.L(ctx).Infof("waiting for triggerOrgRevrec status: %s", status.Data.Status.SyncState)

		time.Sleep(10 * time.Second)
		i++

		if i > 10 {
			log.L(ctx).Error("triggerOrgRevrec timeout")

			return errors.New("triggerOrgRevrec timeout")
		}
	}

	return nil
}
