package output

import (
	"encoding/json"
	"io"
	"time"

	"github.com/salvacybersec/keyhunter/pkg/engine"
)

func init() {
	Register("json", JSONFormatter{})
}

// JSONFormatter renders findings as a JSON array with 2-space indent.
// Empty input produces "[]\n". When Options.Unmask is false the "key"
// field carries the masked representation; "key_masked" always carries
// the masked form regardless of Unmask. Verification fields are omitted
// when empty so unverified scans stay compact.
type JSONFormatter struct{}

type jsonFinding struct {
	Provider       string            `json:"provider"`
	Key            string            `json:"key"`
	KeyMasked      string            `json:"key_masked"`
	Confidence     string            `json:"confidence"`
	Source         string            `json:"source"`
	SourceType     string            `json:"source_type"`
	Line           int               `json:"line"`
	Offset         int64             `json:"offset"`
	DetectedAt     string            `json:"detected_at"`
	Verified       bool              `json:"verified"`
	VerifyStatus   string            `json:"verify_status,omitempty"`
	VerifyHTTPCode int               `json:"verify_http_code,omitempty"`
	VerifyMetadata map[string]string `json:"verify_metadata,omitempty"`
	VerifyError    string            `json:"verify_error,omitempty"`
}

// Format implements the Formatter interface.
func (JSONFormatter) Format(findings []engine.Finding, w io.Writer, opts Options) error {
	out := make([]jsonFinding, 0, len(findings))
	for _, f := range findings {
		key := f.KeyMasked
		if opts.Unmask {
			key = f.KeyValue
		}
		out = append(out, jsonFinding{
			Provider:       f.ProviderName,
			Key:            key,
			KeyMasked:      f.KeyMasked,
			Confidence:     f.Confidence,
			Source:         f.Source,
			SourceType:     f.SourceType,
			Line:           f.LineNumber,
			Offset:         f.Offset,
			DetectedAt:     f.DetectedAt.Format(time.RFC3339),
			Verified:       f.Verified,
			VerifyStatus:   f.VerifyStatus,
			VerifyHTTPCode: f.VerifyHTTPCode,
			VerifyMetadata: f.VerifyMetadata,
			VerifyError:    f.VerifyError,
		})
	}
	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")
	return enc.Encode(out)
}
