// StashGamma EOD Data API — Go quickstart. Standard library only.
//
//	export STASHGAMMA_API_KEY=sg_live_...
//	go run main.go QQQ 2026-07-01 2026-08-01
//
// Docs: https://www.stashgamma.com/developer-docs
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"time"
)

const baseURL = "https://www.stashgamma.com/api/dataapi/v1"

type Bar struct {
	Date   string  `json:"date"`
	Open   float64 `json:"open"`
	High   float64 `json:"high"`
	Low    float64 `json:"low"`
	Close  float64 `json:"close"`
	Volume int64   `json:"volume"`
}

type EodResponse struct {
	Symbol string `json:"symbol"`
	Count  int    `json:"count"`
	Bars   []Bar  `json:"bars"`
	Error  string `json:"error"`
}

// getEodBars fetches daily OHLCV bars for symbol, retrying once on a 429 using Retry-After.
func getEodBars(symbol, from, to, apiKey string) (*EodResponse, error) {
	client := &http.Client{Timeout: 10 * time.Second}

	q := url.Values{}
	if from != "" {
		q.Set("from", from)
	}
	if to != "" {
		q.Set("to", to)
	}
	reqURL := fmt.Sprintf("%s/eod/%s?%s", baseURL, symbol, q.Encode())

	for attempt := 0; attempt <= 3; attempt++ {
		req, err := http.NewRequest("GET", reqURL, nil)
		if err != nil {
			return nil, err
		}
		req.Header.Set("X-Api-Key", apiKey)

		resp, err := client.Do(req)
		if err != nil {
			return nil, err
		}

		if resp.StatusCode == 429 && attempt < 3 {
			retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After"))
			if retryAfter == 0 {
				retryAfter = 5
			}
			resp.Body.Close()
			fmt.Fprintf(os.Stderr, "Rate limited, retrying in %ds...\n", retryAfter)
			time.Sleep(time.Duration(retryAfter) * time.Second)
			continue
		}

		defer resp.Body.Close()
		var out EodResponse
		if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
			return nil, err
		}
		if resp.StatusCode != 200 {
			return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, out.Error)
		}
		return &out, nil
	}

	return nil, fmt.Errorf("still rate-limited after retries")
}

func main() {
	symbol, from, to := "QQQ", "2026-07-01", "2026-08-01"
	args := os.Args[1:]
	if len(args) > 0 {
		symbol = args[0]
	}
	if len(args) > 1 {
		from = args[1]
	}
	if len(args) > 2 {
		to = args[2]
	}

	apiKey := os.Getenv("STASHGAMMA_API_KEY")
	if apiKey == "" {
		fmt.Fprintln(os.Stderr, "Set STASHGAMMA_API_KEY first — get a free key at "+
			"https://www.stashgamma.com/profile?tab=developer")
		os.Exit(1)
	}

	eod, err := getEodBars(symbol, from, to, apiKey)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error:", err)
		os.Exit(1)
	}

	fmt.Printf("%s: %d bars\n", eod.Symbol, eod.Count)
	for i, bar := range eod.Bars {
		if i >= 5 {
			break
		}
		fmt.Printf("%+v\n", bar)
	}
}
