package cli

import (
	"bytes"
	"encoding/json"
	"strings"
	"testing"

	"git.cloudinit.dev/coreci/orca/internal/certpaths"
	"git.cloudinit.dev/coreci/orca/internal/store"
)

func TestAuditListEmpty(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"audit", "list"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("audit list: %v", err)
	}
	if !strings.Contains(buf.String(), "No audit entries") {
		t.Errorf("audit list empty output unexpected: %s", buf.String())
	}
}

func TestAuditListJSONEmpty(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"audit", "list", "--json"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("audit list --json: %v", err)
	}
	var entries []map[string]any
	if err := json.Unmarshal(bytes.TrimSpace(buf.Bytes()), &entries); err != nil {
		t.Fatalf("unmarshal audit json: %v\n%s", err, buf.String())
	}
	if len(entries) != 0 {
		t.Errorf("audit list --json empty = %d entries, want 0", len(entries))
	}
}

func TestAuditListWithEntries(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	db, err := store.Open(certpaths.DBPath())
	if err != nil {
		t.Fatalf("open db: %v", err)
	}
	defer db.Close()
	repo := store.NewAuditRepo(db)
	ctx := t.Context()
	if err := repo.Append(ctx, &store.AuditEntry{
		Actor: "test", Action: "test.action", Resource: "res", Result: "success",
	}); err != nil {
		t.Fatalf("append audit: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"audit", "list"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("audit list: %v", err)
	}
	out := buf.String()
	if !strings.Contains(out, "test.action") {
		t.Errorf("audit list missing entry: %s", out)
	}
	if !strings.Contains(out, "TIMESTAMP") {
		t.Errorf("audit list missing header: %s", out)
	}
}

func TestAuditListLimitFlag(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	db, err := store.Open(certpaths.DBPath())
	if err != nil {
		t.Fatalf("open db: %v", err)
	}
	defer db.Close()
	repo := store.NewAuditRepo(db)
	ctx := t.Context()
	for i := 0; i < 5; i++ {
		if err := repo.Append(ctx, &store.AuditEntry{
			Actor: "test", Action: "test.action", Resource: "res", Result: "success",
		}); err != nil {
			t.Fatalf("append audit %d: %v", i, err)
		}
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"audit", "list", "--json", "--limit", "2"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("audit list --json --limit 2: %v", err)
	}
	var entries []map[string]any
	if err := json.Unmarshal(bytes.TrimSpace(buf.Bytes()), &entries); err != nil {
		t.Fatalf("unmarshal audit json: %v\n%s", err, buf.String())
	}
	if len(entries) != 2 {
		t.Errorf("audit list --limit 2 = %d entries, want 2", len(entries))
	}
}
