package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/google/uuid"
	"github.com/joho/godotenv"
)

/*
======================
 Models
======================
*/

type CreateChargeRequest struct {
	CorrelationID string `json:"correlationID"`
	Value         int    `json:"value"`
	ExpiresIn     int    `json:"expiresIn"`
	Comment       string `json:"comment,omitempty"`
}

type CreateChargeResponse struct {
	Charge struct {
		BRCode string `json:"brCode"`
	} `json:"charge"`
}

func main() {
	/*
	======================
	 Load .env
	======================
	*/
	_ = godotenv.Load()

	appID := os.Getenv("WOOVI_APPID")
	baseURL := os.Getenv("WOOVI_BASE_URL")

	if appID == "" || baseURL == "" {
		fmt.Fprintln(os.Stderr, "Erro: WOOVI_APPID ou WOOVI_BASE_URL não definidos")
		os.Exit(1)
	}

	/*
	======================
	 CLI flags
	======================
	*/
	value := flag.Int("value", 0, "Valor em centavos")
	expires := flag.Int("expires", 900, "Tempo de expiração em segundos")
	correlation := flag.String("correlation", "", "CorrelationID (opcional)")
	comment := flag.String("comment", "", "Comentário (opcional)")
	flag.Parse()

	if *value <= 0 {
		fmt.Fprintln(os.Stderr, "Erro: -value é obrigatório e deve ser > 0")
		os.Exit(1)
	}

	/*
	======================
	 CorrelationID
	======================
	*/
	corrID := *correlation
	if corrID == "" {
		corrID = uuid.New().String()
	}

	/*
	======================
	 Payload
	======================
	*/
	payload := CreateChargeRequest{
		CorrelationID: corrID,
		Value:         *value,
		ExpiresIn:     *expires,
		Comment:       *comment,
	}

	bodyJSON, err := json.Marshal(payload)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Erro ao gerar JSON:", err)
		os.Exit(1)
	}

	/*
	======================
	 HTTP Request
	======================
	*/
	req, err := http.NewRequest(
		"POST",
		baseURL+"/api/v1/charge",
		bytes.NewBuffer(bodyJSON),
	)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Erro ao criar request:", err)
		os.Exit(1)
	}

	req.Header.Set("Authorization", appID)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Erro ao chamar API:", err)
		os.Exit(1)
	}
	defer res.Body.Close()

	respBody, _ := io.ReadAll(res.Body)

	if res.StatusCode < 200 || res.StatusCode >= 300 {
		fmt.Fprintln(os.Stderr, string(respBody))
		os.Exit(1)
	}

	/*
	======================
	 Parse response
	======================
	*/
	var result CreateChargeResponse
	if err := json.Unmarshal(respBody, &result); err != nil {
		fmt.Fprintln(os.Stderr, "Erro ao parsear resposta:", err)
		os.Exit(1)
	}

	if result.Charge.BRCode == "" {
		fmt.Fprintln(os.Stderr, "Erro: BRCode não retornado")
		os.Exit(1)
	}

	/*
	======================
	 Output CLI (ONLY URL)
	======================
	*/
	fmt.Println(result.Charge.BRCode)
}
