package cli

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

func TestDoctorText(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor: %v", err)
	}
	out := buf.String()
	for _, want := range []string{"CA", "cert", "PASS", "WARN", "FAIL"} {
		_ = want
	}
	if !strings.Contains(out, "CA") {
		t.Errorf("doctor output missing CA check: %s", out)
	}
}

func TestDoctorJSON(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "--json"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor --json: %v", err)
	}
	var checks []map[string]any
	if err := json.Unmarshal(bytes.TrimSpace(buf.Bytes()), &checks); err != nil {
		t.Fatalf("unmarshal doctor json: %v\n%s", err, buf.String())
	}
	if len(checks) == 0 {
		t.Errorf("doctor --json returned no checks: %s", buf.String())
	}
}

func TestDoctorCertSubcommand(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "cert"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor cert: %v", err)
	}
	out := buf.String()
	if !strings.Contains(out, "CA") {
		t.Errorf("doctor cert output missing CA: %s", out)
	}
}

func TestDoctorCertJSON(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "cert", "--json"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor cert --json: %v", err)
	}
	var results []map[string]any
	if err := json.Unmarshal(bytes.TrimSpace(buf.Bytes()), &results); err != nil {
		t.Fatalf("unmarshal doctor cert json: %v\n%s", err, buf.String())
	}
	if len(results) == 0 {
		t.Errorf("doctor cert --json returned no results: %s", buf.String())
	}
}

func TestDoctorDBSubcommand(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "db"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor db: %v", err)
	}
	out := buf.String()
	if !strings.Contains(out, "db") {
		t.Errorf("doctor db output unexpected: %s", out)
	}
}

func TestDoctorOSSubcommand(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "os"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor os: %v", err)
	}
}

func TestDoctorOSJSON(t *testing.T) {
	_, cleanup := initTestEnv(t)
	defer cleanup()
	if err := runInit(discardWriter{}); err != nil {
		t.Fatalf("init: %v", err)
	}
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "os", "--json"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor os --json: %v", err)
	}
	var result map[string]any
	if err := json.Unmarshal(bytes.TrimSpace(buf.Bytes()), &result); err != nil {
		t.Fatalf("unmarshal doctor os json: %v\n%s", err, buf.String())
	}
	if result["Name"] == nil {
		t.Errorf("doctor os --json missing Name: %v", result)
	}
}

func TestDoctorNetworkSubcommand(t *testing.T) {
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "network"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor network: %v", err)
	}
}

func TestDoctorProxmoxSubcommand(t *testing.T) {
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "proxmox"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor proxmox: %v", err)
	}
}

func TestDoctorProxmoxJSON(t *testing.T) {
	resetRootFlags(t)
	var buf bytes.Buffer
	rootCmd.SetOut(&buf)
	rootCmd.SetErr(&buf)
	rootCmd.SetArgs([]string{"doctor", "proxmox", "--json"})
	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("doctor proxmox --json: %v", err)
	}
	var result map[string]any
	if err := json.Unmarshal(bytes.TrimSpace(buf.Bytes()), &result); err != nil {
		t.Fatalf("unmarshal doctor proxmox json: %v\n%s", err, buf.String())
	}
	if result["Name"] == nil {
		t.Errorf("doctor proxmox --json missing Name: %v", result)
	}
}
