package store

import "encoding/json"

// HostOOBRow is the latest operator-access (OOB) state per host (TASK H1), parsed from the newest
// host_report. Present is false when the agent sent no oob stanza (pre-H1 / feature off) → never
// alerted.
type HostOOBRow struct {
	HostID                 string
	CustomerID             string
	Present                bool
	FelhomSshdActive       bool
	FelhomSshdPort         int
	Reachable              bool
	ConfigInvalid          bool
	OperatorPeerConfigured bool
}

// GetHostOOBStates returns the latest oob stanza per host (mirrors GetHostMgmtPlaneStates). A report
// without the stanza yields Present=false; malformed JSON degrades to zero values, never an error.
func (s *Store) GetHostOOBStates() ([]HostOOBRow, error) {
	rows, err := s.db.Query(`
		SELECT hr.host_id, hr.customer_id, hr.report_json
		FROM host_reports hr
		JOIN (SELECT host_id, MAX(id) AS mx FROM host_reports GROUP BY host_id) latest
		  ON hr.id = latest.mx`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var out []HostOOBRow
	for rows.Next() {
		var r HostOOBRow
		var reportJSON string
		if err := rows.Scan(&r.HostID, &r.CustomerID, &reportJSON); err != nil {
			return nil, err
		}
		var body struct {
			OOB *struct {
				FelhomSshdActive       bool `json:"felhom_sshd_active"`
				FelhomSshdPort         int  `json:"felhom_sshd_port"`
				Reachable              bool `json:"reachable"`
				ConfigInvalid          bool `json:"config_invalid"`
				OperatorPeerConfigured bool `json:"operator_peer_configured"`
			} `json:"oob"`
		}
		_ = json.Unmarshal([]byte(reportJSON), &body)
		if body.OOB != nil {
			r.Present = true
			r.FelhomSshdActive = body.OOB.FelhomSshdActive
			r.FelhomSshdPort = body.OOB.FelhomSshdPort
			r.Reachable = body.OOB.Reachable
			r.ConfigInvalid = body.OOB.ConfigInvalid
			r.OperatorPeerConfigured = body.OOB.OperatorPeerConfigured
		}
		out = append(out, r)
	}
	return out, rows.Err()
}
