package client

import "encoding/json"

// FullSysCheckReport is returned by the full_sys_check command (read-only recon).
type FullSysCheckReport struct {
	GeneratedAt string `json:"generated_at"`
	Platform    string `json:"platform"`
	Arch        string `json:"arch"`
	OSVersion   string `json:"os_version,omitempty"`
	Hostname    string `json:"hostname,omitempty"`
	WorkerName  string `json:"worker_name,omitempty"`
	BuildID     string `json:"build_id,omitempty"`
	AgentID     string `json:"agent_id,omitempty"`

	Identity    *SysCheckIdentity    `json:"identity,omitempty"`
	Hardware    *SysCheckHardware    `json:"hardware,omitempty"`
	Security    *SysCheckSecurity    `json:"security,omitempty"`
	Network     *SysCheckNetwork     `json:"network,omitempty"`
	Resources   *ResourcePressure    `json:"resources,omitempty"`
	ListenPorts *ListenPortsReport   `json:"listen_ports,omitempty"`
	Patch       *PatchStatusReport   `json:"patch,omitempty"`
	Environment *SysCheckEnvironment `json:"environment,omitempty"`
	Neighbors   *SysCheckNeighbors   `json:"neighbors,omitempty"`
	KEVExposure *KEVScanReport       `json:"kev_exposure,omitempty"`

	RawSysinfo   string `json:"raw_sysinfo,omitempty"`
	RawIPConfig  string `json:"raw_ipconfig,omitempty"`
	RawNetstat   string `json:"raw_netstat,omitempty"`
	ProbeErrors  []string `json:"probe_errors,omitempty"`
}

type SysCheckIdentity struct {
	Username      string `json:"username,omitempty"`
	Domain        string `json:"domain,omitempty"`
	ComputerName  string `json:"computer_name,omitempty"`
	AgentElevated bool   `json:"agent_elevated,omitempty"`
	MACAddress    string `json:"mac_address,omitempty"`
}

type SysCheckHardware struct {
	Manufacturer string              `json:"manufacturer,omitempty"`
	Model        string              `json:"model,omitempty"`
	Serial       string              `json:"serial,omitempty"`
	BIOSVersion  string              `json:"bios_version,omitempty"`
	CPUs         []SysCheckCPU       `json:"cpus,omitempty"`
	MemoryGB     float64             `json:"memory_gb,omitempty"`
	GPUs         []SysCheckGPU       `json:"gpus,omitempty"`
	Disks        []SysCheckDisk      `json:"disks,omitempty"`
	UptimeHours  float64             `json:"uptime_hours,omitempty"`
}

type SysCheckCPU struct {
	Name       string `json:"name,omitempty"`
	Cores      int    `json:"cores,omitempty"`
	Logical    int    `json:"logical,omitempty"`
	MaxMHz     int    `json:"max_mhz,omitempty"`
	CurrentMHz int    `json:"current_mhz,omitempty"`
}

type SysCheckGPU struct {
	Name       string `json:"name,omitempty"`
	Driver     string `json:"driver,omitempty"`
	VRAM_MB    int    `json:"vram_mb,omitempty"`
}

type SysCheckDisk struct {
	Mount      string  `json:"mount,omitempty"`
	Label      string  `json:"label,omitempty"`
	FSType     string  `json:"fs_type,omitempty"`
	TotalGB    float64 `json:"total_gb,omitempty"`
	FreeGB     float64 `json:"free_gb,omitempty"`
	FreePct    int     `json:"free_pct,omitempty"`
}

type SysCheckSecurity struct {
	PostureScore    int             `json:"posture_score,omitempty"`
	DefenderEnabled *bool           `json:"defender_enabled,omitempty"`
	DefenderRTP     *bool           `json:"defender_rtp,omitempty"`
	AVProducts      []string        `json:"av_products,omitempty"`
	FirewallDomain  *bool           `json:"firewall_domain,omitempty"`
	FirewallPrivate *bool           `json:"firewall_private,omitempty"`
	FirewallPublic  *bool           `json:"firewall_public,omitempty"`
	SSHListening    *bool           `json:"ssh_listening,omitempty"`
	PendingUpdates  *int            `json:"pending_updates,omitempty"`
	LastPatch       *string         `json:"last_patch,omitempty"`
	LastPatchDays   *int            `json:"last_patch_days,omitempty"`
	RebootPending   *bool           `json:"reboot_pending,omitempty"`
	Services        []ServiceStatus `json:"services,omitempty"`
}

type SysCheckNetwork struct {
	PrimaryLocalIP   string              `json:"primary_local_ip,omitempty"`
	ExternalIP       string              `json:"external_ip,omitempty"`
	ExternalIPSource string              `json:"external_ip_source,omitempty"`
	Geo              *SysCheckGeo        `json:"geo,omitempty"`
	DNS              *DNSConfig          `json:"dns,omitempty"`
	Interfaces       []SysCheckInterface `json:"interfaces,omitempty"`
	DefaultGateway   string              `json:"default_gateway,omitempty"`
	RoutesSummary    string              `json:"routes_summary,omitempty"`
}

type SysCheckGeo struct {
	Query       string  `json:"query,omitempty"`
	Country     string  `json:"country,omitempty"`
	Region      string  `json:"region,omitempty"`
	City        string  `json:"city,omitempty"`
	ISP         string  `json:"isp,omitempty"`
	Org         string  `json:"org,omitempty"`
	Lat         float64 `json:"lat,omitempty"`
	Lon         float64 `json:"lon,omitempty"`
}

type SysCheckInterface struct {
	Name   string   `json:"name,omitempty"`
	MAC    string   `json:"mac,omitempty"`
	IPv4   []string `json:"ipv4,omitempty"`
	IPv6   []string `json:"ipv6,omitempty"`
}

type SysCheckEnvironment struct {
	Timezone   string `json:"timezone,omitempty"`
	Locale     string `json:"locale,omitempty"`
	HomeDir    string `json:"home_dir,omitempty"`
	TempDir    string `json:"temp_dir,omitempty"`
	InstallDir string `json:"install_dir,omitempty"`
}

type SysCheckNeighbors struct {
	ArpHosts    []string `json:"arp_hosts,omitempty"`
	SubnetScan  string   `json:"subnet_scan,omitempty"`
	ArpCount    int      `json:"arp_count,omitempty"`
}

func (r *FullSysCheckReport) JSON() string {
	b, _ := json.Marshal(r)
	return string(b)
}

func securityFromPosture(p *PostureReport) *SysCheckSecurity {
	if p == nil {
		return nil
	}
	return &SysCheckSecurity{
		PostureScore:    p.PostureScore,
		DefenderEnabled: p.DefenderEnabled,
		DefenderRTP:     p.DefenderRTP,
		AVProducts:      p.AVProducts,
		FirewallDomain:  p.FirewallDomain,
		FirewallPrivate: p.FirewallPrivate,
		FirewallPublic:  p.FirewallPublic,
		SSHListening:    p.SSHListening,
		PendingUpdates:  p.PendingUpdates,
		LastPatch:       p.LastPatch,
		LastPatchDays:   p.LastPatchDays,
		RebootPending:   p.RebootPending,
		Services:        p.Services,
	}
}
