package dryrun

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	cfgpkg "github.com/jan/fm-rds-tx/internal/config"
)

type FrameSummary struct {
	Mode             string    `json:"mode"`
	FrequencyMHz     float64   `json:"frequencyMHz"`
	StereoEnabled    bool      `json:"stereoEnabled"`
	RDSEnabled       bool      `json:"rdsEnabled"`
	CompositeRate    int       `json:"compositeRateHz"`
	DeviceRate       float64   `json:"deviceSampleRateHz"`
	PilotLevel       float64   `json:"pilotLevel"`
	RDSInjection     float64   `json:"rdsInjection"`
	OutputDrive      float64   `json:"outputDrive"`
	PreEmphasisTauUS float64   `json:"preEmphasisTauUS"`
	MaxDeviationHz   float64   `json:"maxDeviationHz"`
	LimiterEnabled   bool      `json:"limiterEnabled"`
	FMModulation     bool      `json:"fmModulationEnabled"`
	Source           string    `json:"source"`
	PreviewSamples   []float64 `json:"previewSamples"`
}

func Generate(cfg cfgpkg.Config) FrameSummary {
	preview := make([]float64, 16)
	base := cfg.Audio.Gain * cfg.FM.OutputDrive
	for i := range preview {
		sign := 1.0
		if i%2 == 1 {
			sign = -1.0
		}
		preview[i] = sign * base * float64(i+1) / 16.0
	}
	source := "tones"
	if cfg.Audio.InputPath != "" {
		source = cfg.Audio.InputPath
	}
	return FrameSummary{
		Mode:             "dry-run",
		FrequencyMHz:     cfg.FM.FrequencyMHz,
		StereoEnabled:    cfg.FM.StereoEnabled,
		RDSEnabled:       cfg.RDS.Enabled,
		CompositeRate:    cfg.FM.CompositeRateHz,
		DeviceRate:       cfg.EffectiveDeviceRate(),
		PilotLevel:       cfg.FM.PilotLevel,
		RDSInjection:     cfg.FM.RDSInjection,
		OutputDrive:      cfg.FM.OutputDrive,
		PreEmphasisTauUS: cfg.FM.PreEmphasisTauUS,
		MaxDeviationHz:   cfg.FM.MaxDeviationHz,
		LimiterEnabled:   cfg.FM.LimiterEnabled,
		FMModulation:     cfg.FM.FMModulationEnabled,
		Source:           source,
		PreviewSamples:   preview,
	}
}

func WriteJSON(path string, frame FrameSummary) error {
	data, err := json.MarshalIndent(frame, "", "  ")
	if err != nil {
		return fmt.Errorf("marshal dry-run frame: %w", err)
	}
	if path == "" || path == "-" {
		_, err = os.Stdout.Write(append(data, '\n'))
		return err
	}
	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
		return fmt.Errorf("create output dir: %w", err)
	}
	return os.WriteFile(path, append(data, '\n'), 0o644)
}
