package platform

import (
	"context"
	"encoding/json"
	"errors"
	"os/exec"
	"strings"
)

type CapacityCheckResult struct {
	Status          string          `json:"status"`
	CapacityMetrics CapacityMetrics `json:"capacity_metrics"`
	Findings        []string        `json:"findings"`
}

type capacityCheckReport struct {
	Status string `json:"status"`
	Totals struct {
		ActiveConnections          int64   `json:"active_connections"`
		KafkaLag                   float64 `json:"kafka_lag"`
		BridgeConsumerPending      float64 `json:"bridge_consumer_pending"`
		BridgeAckPending           float64 `json:"bridge_ack_pending"`
		BridgeBatchPendingMessages float64 `json:"bridge_batch_pending_messages"`
		FastWriterConsumerPending  float64 `json:"fast_writer_consumer_pending"`
		FastWriterAckPending       float64 `json:"fast_writer_ack_pending"`
		FastWriterBatchPending     float64 `json:"fast_writer_batch_pending_messages"`
		HistoryBatchPending        float64 `json:"history_batch_pending_messages"`
		HistoryRowsPending         float64 `json:"history_rows_pending"`
	} `json:"totals"`
	Findings []string `json:"findings"`
}

type CapacityCheckCommand struct {
	bin string
}

func NewCapacityCheckCommand(bin string) *CapacityCheckCommand {
	return &CapacityCheckCommand{bin: strings.TrimSpace(bin)}
}

func (c *CapacityCheckCommand) CheckCapacity(ctx context.Context) (CapacityCheckResult, error) {
	if c.bin == "" {
		return CapacityCheckResult{}, errors.New("capacity-check bin is empty")
	}
	output, err := exec.CommandContext(ctx, c.bin).CombinedOutput()
	var report capacityCheckReport
	if jsonErr := json.Unmarshal(output, &report); jsonErr != nil {
		if err != nil {
			return CapacityCheckResult{}, errors.New(err.Error() + ": " + strings.TrimSpace(string(output)))
		}
		return CapacityCheckResult{}, jsonErr
	}
	return CapacityCheckResult{
		Status: report.Status,
		CapacityMetrics: CapacityMetrics{
			ActiveConnections:          int(report.Totals.ActiveConnections),
			KafkaLag:                   int(report.Totals.KafkaLag),
			BridgeConsumerPending:      int(report.Totals.BridgeConsumerPending),
			BridgeAckPending:           int(report.Totals.BridgeAckPending),
			BridgeBatchPendingMessages: int(report.Totals.BridgeBatchPendingMessages),
			FastWriterConsumerPending:  int(report.Totals.FastWriterConsumerPending),
			FastWriterAckPending:       int(report.Totals.FastWriterAckPending),
			FastWriterBatchPending:     int(report.Totals.FastWriterBatchPending),
			HistoryBatchPending:        int(report.Totals.HistoryBatchPending),
			HistoryRowsPending:         int(report.Totals.HistoryRowsPending),
		},
		Findings: report.Findings,
	}, nil
}
