package stats

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"github.com/sstent/go-garth/api/client"
	"github.com/sstent/go-garth/utils"
)

type Stats interface {
	List(end time.Time, period int, client *client.Client) ([]interface{}, error)
}

type BaseStats struct {
	Path     string
	PageSize int
}

func (b *BaseStats) List(end time.Time, period int, client *client.Client) ([]interface{}, error) {
	endDate := utils.FormatEndDate(end)
	var allData []interface{}
	var errs []error

	for period > 0 {
		pageSize := b.PageSize
		if period < pageSize {
			pageSize = period
		}

		page, err := b.fetchPage(endDate, pageSize, client)
		if err != nil {
			errs = append(errs, err)
			// Continue to next page even if current fails
		} else {
			allData = append(page, allData...)
		}

		// Move to previous page
		endDate = endDate.AddDate(0, 0, -pageSize)
		period -= pageSize
	}

	// Return partial data with aggregated errors
	var finalErr error
	if len(errs) > 0 {
		finalErr = fmt.Errorf("partial failure: %v", errs)
	}
	return allData, finalErr
}

func (b *BaseStats) fetchPage(end time.Time, period int, client *client.Client) ([]interface{}, error) {
	var start time.Time
	var path string

	if strings.Contains(b.Path, "daily") {
		start = end.AddDate(0, 0, -(period - 1))
		path = strings.Replace(b.Path, "{start}", start.Format("2006-01-02"), 1)
		path = strings.Replace(path, "{end}", end.Format("2006-01-02"), 1)
	} else {
		path = strings.Replace(b.Path, "{end}", end.Format("2006-01-02"), 1)
		path = strings.Replace(path, "{period}", fmt.Sprintf("%d", period), 1)
	}

	data, err := client.ConnectAPI(path, "GET", nil, nil)
	if err != nil {
		return nil, err
	}

	if len(data) == 0 {
		return []interface{}{}, nil
	}

	var responseSlice []map[string]interface{}
	if err := json.Unmarshal(data, &responseSlice); err != nil {
		return nil, err
	}

	if len(responseSlice) == 0 {
		return []interface{}{}, nil
	}

	var results []interface{}
	for _, itemMap := range responseSlice {
		// Handle nested "values" structure
		if values, exists := itemMap["values"]; exists {
			valuesMap := values.(map[string]interface{})
			for k, v := range valuesMap {
				itemMap[k] = v
			}
			delete(itemMap, "values")
		}

		snakeItem := utils.CamelToSnakeDict(itemMap)
		results = append(results, snakeItem)
	}

	return results, nil
}
