package main

import (
	"crypto/subtle"
	"fmt"
	"net/url"
)

const opaquePartBytes = 43

// validReforgedTransportTicket accepts the distinct high-entropy secret used
// only by the Reforged transport handshake. The controller lifecycle bearer
// never enters this bridge.
func validReforgedTransportTicket(value string) bool {
	const prefix = "rft_"
	if len(value) != len(prefix)+opaquePartBytes ||
		value[:len(prefix)] != prefix {
		return false
	}
	validToken := func(token string) bool {
		for index := 0; index < len(token); index++ {
			character := token[index]
			if (character >= 'A' && character <= 'Z') ||
				(character >= 'a' && character <= 'z') ||
				(character >= '0' && character <= '9') ||
				character == '_' || character == '-' {
				continue
			}
			return false
		}
		return true
	}
	return validToken(value[len(prefix):])
}

// The public WebTransport request path is deliberately secret-free. The
// ticket arrives in the first control-stream message after upgrade and before
// any private relay plane is dialed or active slot is replaced.
func validReforgedRouteQuery(raw string) bool {
	return raw == ""
}

func validReforgedRelayPlane(plane string) bool {
	switch plane {
	case "resource", "frame", "recovery", "input":
		return true
	default:
		return false
	}
}

func reforgedRelayTarget(base, plane string) (string, bool) {
	parsed, err := url.Parse(base)
	if err != nil || !validReforgedRelayPlane(plane) ||
		parsed.Scheme != "ws" || parsed.Hostname() != "127.0.0.1" ||
		parsed.Port() == "" || parsed.User != nil || parsed.Path != "" ||
		parsed.RawQuery != "" || parsed.Fragment != "" {
		return "", false
	}
	return base + "/" + plane, true
}

func reforgedRelayAuthMessage(ticket string) ([]byte, bool) {
	if !validReforgedTransportTicket(ticket) {
		return nil, false
	}
	return []byte(fmt.Sprintf(
		`{"type":"auth","profile":"%s","ticket":"%s"}`,
		reforgedProfile, ticket)), true
}

func validReforgedRelayAuthAck(message []byte, plane string) bool {
	if !validReforgedRelayPlane(plane) {
		return false
	}
	expected := fmt.Sprintf(
		`{"type":"authOk","profile":"%s","plane":"%s"}`,
		reforgedProfile, plane)
	return subtle.ConstantTimeCompare(message, []byte(expected)) == 1
}

func validateReforgedRelayHost(host string) error {
	if host != "127.0.0.1" {
		return fmt.Errorf("Reforged relay host must be exact IPv4 loopback")
	}
	return nil
}

// transportSessionLogLabel preserves the existing Classic label and redacts
// every Reforged credential before any shared bridge log call.
func transportSessionLogLabel(sessionID, profile string) string {
	if profile != "" {
		return "[redacted]"
	}
	return sessionID
}

// validReforgedHello uses a constant-time byte comparison for the secret-
// bearing canonical message. This rejects duplicate fields, escaped aliases,
// unknown fields, and spectator requests before any relay plane is dialed.
func validReforgedHello(raw []byte, ticket, profile string) bool {
	if !validReforgedTransportTicket(ticket) || profile != reforgedProfile {
		return false
	}
	expected := fmt.Sprintf(
		`{"t":"hello","profile":"%s","ticket":"%s"}`,
		profile, ticket)
	return subtle.ConstantTimeCompare(raw, []byte(expected)) == 1
}

func reforgedTransportTicketFromHello(raw []byte, profile string) (string, bool) {
	if profile != reforgedProfile {
		return "", false
	}
	prefix := []byte(`{"t":"hello","profile":"` + profile + `","ticket":"`)
	suffix := []byte(`"}`)
	if len(raw) != len(prefix)+len("rft_")+opaquePartBytes+len(suffix) ||
		subtle.ConstantTimeCompare(raw[:len(prefix)], prefix) != 1 ||
		subtle.ConstantTimeCompare(raw[len(raw)-len(suffix):], suffix) != 1 {
		return "", false
	}
	ticket := string(raw[len(prefix) : len(raw)-len(suffix)])
	if !validReforgedHello(raw, ticket, profile) {
		return "", false
	}
	return ticket, true
}

// validateReforgedRouteConfig keeps the new path disabled unless both of its
// explicit flags are valid. Classic remains the only registered route under
// the default zero/zero configuration.
func validateReforgedRouteConfig(relayBase, slots int) (bool, error) {
	if relayBase == 0 && slots == 0 {
		return false, nil
	}
	if relayBase == 0 || slots == 0 {
		return false, fmt.Errorf(
			"reforged-relay-base and reforged-slots must be enabled together")
	}
	if slots < 1 || slots > 99 {
		return false, fmt.Errorf("reforged-slots must be between 1 and 99")
	}
	if relayBase < 1024 || relayBase > 65535-slots {
		return false, fmt.Errorf("reforged relay port range is invalid")
	}
	return true, nil
}
