package ui

import (
	"math"
	"strings"
)

// renderButterfly draws a symmetric Rorschach/butterfly pattern using Braille
// dots. The spectrum bands are mirrored horizontally from the center, and
// organic variation is added via sine wobble and scatterHash to create
// ink-blot-like shapes that pulse with the music.
func (v *Visualizer) renderButterfly(bands []float64) string {
	height := v.Rows
	dotRows := height * 4
	dotCols := PanelWidth * 2
	centerX := dotCols / 2
	bandCount := len(bands)

	grid := make([]bool, dotRows*dotCols)

	for dy := range dotRows {
		// Map vertical position to a band index.
		bandF := float64(dy) / float64(max(1, dotRows-1)) * float64(bandCount-1)
		bi := int(bandF)
		frac := bandF - float64(bi)
		var energy float64
		if bi >= bandCount-1 {
			energy = bands[bandCount-1]
		} else {
			energy = bands[bi]*(1-frac) + bands[bi+1]*frac
		}

		// Wing width: how far from center the pattern extends.
		t := float64(v.frame)*0.08 + float64(dy)*0.3
		wobble := math.Sin(t) * 0.15
		wingWidth := int(float64(centerX) * (energy + wobble) * 0.9)

		for dx := range wingWidth {
			// Distance from center normalized to wing width.
			norm := float64(dx) / float64(max(1, wingWidth))

			// Organic edge: denser near center, sparser at edges.
			threshold := (1.0 - norm*norm) * energy
			// Add frame-based flicker at the edges.
			if norm > 0.6 {
				threshold *= 0.5 + 0.5*math.Sin(float64(v.frame)*0.1+float64(dy)*0.5+float64(dx)*0.3)
			}

			if scatterHash(bi, dy, dx, v.frame/3) < threshold {
				// Right wing.
				rx := centerX + dx
				if rx < dotCols {
					grid[dy*dotCols+rx] = true
				}
				// Left wing (mirror).
				lx := centerX - 1 - dx
				if lx >= 0 {
					grid[dy*dotCols+lx] = true
				}
			}
		}

		// Central spine — always drawn.
		if energy > 0.05 {
			grid[dy*dotCols+centerX] = true
			if centerX > 0 {
				grid[dy*dotCols+centerX-1] = true
			}
		}
	}

	// Render braille with row-based coloring.
	lines := make([]string, height)
	for row := range height {
		var content strings.Builder
		for ch := range PanelWidth {
			var braille rune = '\u2800'
			for dr := range 4 {
				for dc := range 2 {
					if grid[(row*4+dr)*dotCols+ch*2+dc] {
						braille |= brailleBit[dr][dc]
					}
				}
			}
			content.WriteRune(braille)
		}
		// Color gradient from top to bottom.
		norm := float64(row) / float64(max(1, height-1))
		lines[row] = specWrap(norm, content.String())
	}

	return strings.Join(lines, "\n")
}
