package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"log/slog"
	"strings"
	"time"

	twitter "github.com/g8rswimmer/go-twitter/v2"
	twitterscraper "github.com/imperatrona/twitter-scraper"
	"golang.org/x/time/rate"
)

func GetLoginAccount() ([]*twitterscraper.Scraper, error) {

	accounts, err := GetAvailableAccounts()

	if err != nil {
		return nil, err
	}

	fmt.Println("len(accounts)", len(accounts))

	res := make([]*twitterscraper.Scraper, 0, len(accounts))

	for _, v := range accounts {

		needLogin := false

		scraper := twitterscraper.New()

		fmt.Println("user cookies ", v.Username, v.Email)

		if v.Cookies != nil {
			//var cookies []*http.Cookie

			// if err := json.Unmarshal(v.Cookies, cookies); err != nil {
			// 	slog.Error("cookies json.Unmarshal(", "err", err.Error())
			// 	needLogin = true
			// }
			scraper.SetCookies(v.Cookies)
			if !scraper.IsLoggedIn() {
				needLogin = true
			} else {
				res = append(res, scraper)
				continue
			}
		} else {
			needLogin = true
		}

		fmt.Println("needLogin", needLogin)

		if needLogin {

			//if 	err := scraper.Login("wuljKNFZmI87376", "Twitter24081907", "000007@agidev.io")
			if err := scraper.Login(v.Username, v.Password, v.Email); err != nil {
				SetNotAvailable(v.Username, err.Error())
				slog.Error("scraper.Login", "err", err.Error())
				continue
			}

			cookies := scraper.GetCookies()

			// data, err := json.Marshal(cookies)

			// if err != nil {
			// 	slog.Error("cookies json.Marshal", "err", err.Error())
			// 	continue
			// }

			//fmt.Println("user cookies", v.Username, v.Email, string(data))

			if err := UpdateCookies(v.Username, cookies); err != nil {
				slog.Error("cookies UpdateCookies", "err", err.Error())
				continue
			}

			res = append(res, scraper)
		}
	}

	return res, nil
}

type ScraperWithTimer struct {
	*twitterscraper.Scraper
	Timer    *time.Timer
	Email    string
	UserName string
}

var accChan chan ScraperWithTimer = make(chan ScraperWithTimer, 20)

// func init() {

// }
func NewFollowerOb() *FollowerRateLimit {

	return &FollowerRateLimit{
		RateLimit: rate.NewLimiter(rate.Every(15*time.Minute), 40),
	}
}

type FollowerRateLimit struct {
	RateLimit *rate.Limiter
	Scraper   *twitterscraper.Scraper
}

func (f *FollowerRateLimit) TryProfileFollowerCount(username string) (int, error) {

	i := 0
	for {

		if i > 10 {
			return 0, fmt.Errorf("can not get the %v follower count", username)
		}

		fc, err := f.ProfileFollowerCount(username)

		if err != nil {

			f.Scraper.GetGuestToken()
			// twitterscraper.GetGuestToken()
			// c.Scraper = twitterscraper.New()
			slog.Error("ProfileFollowerCount", "err", err.Error())
			time.Sleep(time.Second * time.Duration(i))

			continue
		}

		return fc, nil
	}

}

func (f *FollowerRateLimit) ProfileFollowerCount(username string) (int, error) {

	if f.Scraper == nil {
		f.Scraper = twitterscraper.New()
	}

	//c.Scraper.GetProfile("aon_aonet")

	pro, err := f.Scraper.GetProfile(username)

	if err != nil {
		return 0, err
	}

	return pro.FollowersCount, nil

}

//= rate.NewLimiter(rate.Every(15*time.Minute), 40)

func (f *FollowerRateLimit) Follower(userName string, next string) ([]*twitter.UserObj, string, *twitter.RateLimit, error) {

	fmt.Println("Follower request-------------")

	//FollowerRateLimit.
	ctx := context.Background()

	err := f.RateLimit.Wait(ctx) // This is a blocking call.

	//err := c.RetweeterRatelimiter.Wait(ctx) // This is a blocking call.
	if err != nil {
		return nil, "", nil, err
	}

	select {
	case account := <-accChan:

		//users, next, err := account.WithDelay(300).FetchFollowers("bitcoin", 20, "")

		users, next, err := account.FetchFollowers(userName, 20, "")
		if err != nil {
			slog.Error(err.Error())
		}

		res := make([]*twitter.UserObj, 0, len(users))

		for _, v := range users {

			sDec, _ := base64.StdEncoding.DecodeString(v.UserID)
			userId, _ := strings.CutPrefix(string(sDec), "User:")

			res = append(res, &twitter.UserObj{
				ID:       userId,
				Name:     v.Name,
				UserName: v.Username,
			})
		}

		accChan <- account
		return res, next, nil, nil

	}
}
