package tmux

import (
	"context"
	"errors"
	"sync"
)

// FakePane is an in-memory PaneIO for testing the sidecar parser without a
// real tmux subprocess. Scripted: Send is no-op; Receive returns the next
// canned response. ResponseSequence lets tests inject malformed-then-good
// flows to exercise reformat retries.
type FakePane struct {
	mu        sync.Mutex
	pending   []string
	closed    bool
	sendQueue []string
}

// NewFakePane returns a fresh pane.
func NewFakePane() *FakePane { return &FakePane{} }

// QueueResponse enqueues the next response Receive will return.
func (p *FakePane) QueueResponse(s string) {
	p.mu.Lock()
	p.pending = append(p.pending, s)
	p.mu.Unlock()
}

// Send records what was sent (so tests can assert).
func (p *FakePane) Send(ctx context.Context, payload string) error {
	p.mu.Lock()
	defer p.mu.Unlock()
	if p.closed {
		return errors.New("pane closed")
	}
	p.sendQueue = append(p.sendQueue, payload)
	return nil
}

// Receive returns the next queued response.
func (p *FakePane) Receive(ctx context.Context) (string, error) {
	p.mu.Lock()
	defer p.mu.Unlock()
	if len(p.pending) == 0 {
		return "", errors.New("pane: no scripted response available")
	}
	s := p.pending[0]
	p.pending = p.pending[1:]
	return s, nil
}

// Close marks the pane unusable.
func (p *FakePane) Close() { p.mu.Lock(); p.closed = true; p.mu.Unlock() }

// Sent returns the slice of payloads that have been Send-d.
func (p *FakePane) Sent() []string {
	p.mu.Lock()
	defer p.mu.Unlock()
	out := make([]string, len(p.sendQueue))
	copy(out, p.sendQueue)
	return out
}
