package main

import (
	"math/big"
	"os"
	"os/exec"
	"strings"
	"testing"
)

func TestPi10Decimals(t *testing.T) {
	cmd := exec.Command("./print_hej", "10")
	output, err := cmd.Output()
	if err != nil {
		t.Fatalf("Kunde inte köra program: %v", err)
	}
	
	result := strings.TrimSpace(string(output))
	expected := "3.1415926535"
	
	if result != expected {
		t.Errorf("Fel resultat för 10 decimaler.\nFörväntade: %s\nFick: %s", expected, result)
	}
}

func TestPi5Decimals(t *testing.T) {
	cmd := exec.Command("./print_hej", "5")
	output, err := cmd.Output()
	if err != nil {
		t.Fatalf("Kunde inte köra program: %v", err)
	}
	
	result := strings.TrimSpace(string(output))
	expected := "3.14159"
	
	if result != expected {
		t.Errorf("Fel resultat för 5 decimaler.\nFörväntade: %s\nFick: %s", expected, result)
	}
}

func TestPi1Decimal(t *testing.T) {
	cmd := exec.Command("./print_hej", "1")
	output, err := cmd.Output()
	if err != nil {
		t.Fatalf("Kunde inte köra program: %v", err)
	}
	
	result := strings.TrimSpace(string(output))
	expected := "3.1"
	
	if result != expected {
		t.Errorf("Fel resultat för 1 decimal.\nFörväntade: %s\nFick: %s", expected, result)
	}
}

func TestPiDefault(t *testing.T) {
	cmd := exec.Command("./print_hej")
	output, err := cmd.Output()
	if err != nil {
		t.Fatalf("Kunde inte köra program: %v", err)
	}
	
	result := strings.TrimSpace(string(output))
	
	// Läs facit
	facit, err := os.ReadFile("../facit.txt")
	if err != nil {
		t.Fatalf("Kunde inte läsa facit: %v", err)
	}
	
	expected := strings.TrimSpace(string(facit))
	expected = strings.ReplaceAll(expected, "\n", "")[:103]
	
	if result != expected {
		t.Errorf("Fel resultat för default (100 decimaler).\nFörväntade: %s\nFick: %s", expected, result)
	}
}

func TestPiInvalidInput(t *testing.T) {
	cmd := exec.Command("./print_hej", "abc")
	output, err := cmd.Output()
	if err != nil {
		t.Fatalf("Kunde inte köra program: %v", err)
	}
	
	result := strings.TrimSpace(string(output))
	
	// Ska använda default (100 decimaler)
	if !strings.HasPrefix(result, "3.1415926535") {
		t.Errorf("Hanterar inte ogiltig input korrekt.\nFick: %s", result)
	}
}

func TestCalculatePiExact(t *testing.T) {
	pi := calculatePiExact(10)
	result := formatPiExact(pi, 10)
	
	expected := "3.1415926535"
	if result != expected {
		t.Errorf("calculatePiExact gav fel resultat.\nFörväntade: %s\nFick: %s", expected, result)
	}
}

func TestArctanExact(t *testing.T) {
	scale := new(big.Int).Exp(big.NewInt(10), big.NewInt(20), nil)
	
	// arctan(1/5) ska vara ungefär 0.1973955598...
	atan1_5 := arctanExact(5, scale)
	
	// Kontrollera att resultatet är positivt
	if atan1_5.Sign() <= 0 {
		t.Errorf("arctan(1/5) ska vara positivt, fick: %v", atan1_5)
	}
}

func TestFormatPiExact(t *testing.T) {
	// Skapa ett pi-värde: 31415926535... (skalat med 10^10)
	pi := big.NewInt(31415926535)
	
	result := formatPiExact(pi, 10)
	expected := "3.1415926535"
	
	if result != expected {
		t.Errorf("formatPiExact gav fel resultat.\nFörväntade: %s\nFick: %s", expected, result)
	}
}