package wal

import (
	"errors"
	"testing"
)

func TestHeaderRoundtrip(t *testing.T) {
	orig := &WalFileHeader{
		BlockSize:     32 * 1024, // 32 KB
		SegmentID:     5,
		StartSequence: 1000,
	}

	encoded := EncodeWalHeader(orig)
	decoded, err := DecodeWalHeader(encoded[:])
	if err != nil {
		t.Fatalf("DecodeWalHeader returned error: %v", err)
	}

	if decoded.Magic != walMagic {
		t.Errorf("Magic = %x, want %x", decoded.Magic, walMagic)
	}
	if decoded.FormatVersion != walFormatVersion {
		t.Errorf("FormatVersion = %d, want %d", decoded.FormatVersion, walFormatVersion)
	}
	if decoded.HeaderSize != walFileHeaderSize {
		t.Errorf("HeaderSize = %d, want %d", decoded.HeaderSize, walFileHeaderSize)
	}
	if decoded.BlockSize != orig.BlockSize {
		t.Errorf("BlockSize = %d, want %d", decoded.BlockSize, orig.BlockSize)
	}
	if decoded.SegmentID != orig.SegmentID {
		t.Errorf("SegmentID = %d, want %d", decoded.SegmentID, orig.SegmentID)
	}
	if decoded.StartSequence != orig.StartSequence {
		t.Errorf("StartSequence = %d, want %d", decoded.StartSequence, orig.StartSequence)
	}
	if decoded.HeaderCRC != orig.HeaderCRC {
		t.Errorf("HeaderCRC = %x, want %x", decoded.HeaderCRC, orig.HeaderCRC)
	}
}

func TestHeaderCRC(t *testing.T) {
	h := &WalFileHeader{
		BlockSize:     32 * 1024,
		SegmentID:     1,
		StartSequence: 0,
	}
	encoded := EncodeWalHeader(h)

	// Flip a byte in the magic field (bytes 0-3)
	encoded[0] ^= 0xFF

	_, err := DecodeWalHeader(encoded[:])
	if !errors.Is(err, errCRCMismatch) && !errors.Is(err, errBadMagic) {
		// Flipping magic may fail on magic check first or CRC check
		// Either way, decoding must fail
		t.Fatalf("expected CRC or magic error, got: %v", err)
	}

	// Restore magic and flip a byte in the payload instead
	encoded[0] = byte(walMagic & 0xFF)
	encoded[12] ^= 0x01 // flip byte in SegmentID

	_, err = DecodeWalHeader(encoded[:])
	if !errors.Is(err, errCRCMismatch) {
		t.Fatalf("expected errCRCMismatch, got: %v", err)
	}
}

func TestHeaderBadMagic(t *testing.T) {
	data := make([]byte, 32)
	// All zeros — magic won't match
	_, err := DecodeWalHeader(data)
	if !errors.Is(err, errBadMagic) {
		t.Fatalf("expected errBadMagic, got: %v", err)
	}
}

func TestHeaderShortData(t *testing.T) {
	data := make([]byte, 16) // too short
	_, err := DecodeWalHeader(data)
	if !errors.Is(err, errHeaderTooShort) {
		t.Fatalf("expected errHeaderTooShort, got: %v", err)
	}
}
