package tools

import (
	"fmt"
	"os"
	"strings"

	"skraak/utils"
)

// CallsShowImagesInput defines the input for the show-images tool
type CallsShowImagesInput struct {
	DataFilePath string `json:"data_file_path"`
	Color        bool   `json:"color"`
	ImageSize    int    `json:"image_size"`
	Sixel        bool   `json:"sixel"`
	ITerm        bool   `json:"iterm"`
}

// CallsShowImagesOutput defines the output for the show-images tool
type CallsShowImagesOutput struct {
	SegmentsShown int    `json:"segments_shown"`
	WavFile       string `json:"wav_file"`
	Error         string `json:"error,omitempty"`
}

// CallsShowImages reads a .data file and displays spectrogram images for each segment
func CallsShowImages(input CallsShowImagesInput) (CallsShowImagesOutput, error) {
	var output CallsShowImagesOutput

	// Validate file exists
	if _, err := os.Stat(input.DataFilePath); os.IsNotExist(err) {
		output.Error = fmt.Sprintf("File not found: %s", input.DataFilePath)
		return output, fmt.Errorf("%s", output.Error)
	}

	// Derive WAV file path (strip .data suffix)
	wavPath := strings.TrimSuffix(input.DataFilePath, ".data")
	output.WavFile = wavPath

	// Check WAV file exists
	if _, err := os.Stat(wavPath); os.IsNotExist(err) {
		output.Error = fmt.Sprintf("WAV file not found: %s", wavPath)
		return output, fmt.Errorf("%s", output.Error)
	}

	// Parse .data file (includes labels for future filtering)
	dataFile, err := utils.ParseDataFile(input.DataFilePath)
	if err != nil {
		output.Error = err.Error()
		return output, fmt.Errorf("%s", output.Error)
	}

	if len(dataFile.Segments) == 0 {
		output.Error = "No segments found in .data file"
		return output, fmt.Errorf("%s", output.Error)
	}

	// Resolve image size
	imgSize := input.ImageSize
	if imgSize == 0 {
		imgSize = utils.SpectrogramDisplaySize
	}

	// Select graphics protocol
	protocol := utils.ProtocolKitty
	if input.ITerm {
		protocol = utils.ProtocolITerm
	} else if input.Sixel {
		protocol = utils.ProtocolSixel
	}

	// Generate spectrogram for each segment and output
	for i, seg := range dataFile.Segments {
		// Generate spectrogram image
		img, err := utils.GenerateSegmentSpectrogram(input.DataFilePath, seg.StartTime, seg.EndTime, input.Color, imgSize)
		if err != nil || img == nil {
			continue
		}

		// Print segment info
		labelInfo := formatSegmentLabels(seg.Labels)
		fmt.Fprintf(os.Stderr, "Segment %d: %.1fs - %.1fs (%.1fs)%s\n",
			i+1, seg.StartTime, seg.EndTime, seg.EndTime-seg.StartTime, labelInfo)

		// Write to stdout via terminal graphics protocol
		if err := utils.WriteImage(img, os.Stdout, protocol); err != nil {
			output.Error = fmt.Sprintf("Failed to write image: %v", err)
			return output, fmt.Errorf("%s", output.Error)
		}
		fmt.Println() // Newline after image
	}

	output.SegmentsShown = len(dataFile.Segments)
	return output, nil
}

// formatSegmentLabels formats labels for display in segment info
func formatSegmentLabels(labels []*utils.Label) string {
	if len(labels) == 0 {
		return ""
	}
	var parts []string
	for _, l := range labels {
		part := l.Species
		if l.CallType != "" {
			part += "/" + l.CallType
		}
		if l.Filter != "" {
			part += " [" + l.Filter + "]"
		}
		parts = append(parts, part)
	}
	return "  " + strings.Join(parts, ", ")
}