package wiretypes

import (
	"encoding/json"
	"net/http"
	"time"
)

// CommandType is a discriminator for different kinds of polled commands.
type CommandType string

const (
	// CommandTypeJSONRPC indicates a standard JSON-RPC command payload.
	CommandTypeJSONRPC CommandType = "jsonrpc"
	// CommandTypeOAuthDiscovery indicates an OAuth discovery command payload.
	CommandTypeOAuthDiscovery CommandType = "oauth_discovery"
	// CommandTypeSessionTermination indicates an explicit Streamable HTTP session close.
	CommandTypeSessionTermination CommandType = "session_termination"
)

type ResponsePayloadType string

const (
	ResponsePayloadJSONRPC            ResponsePayloadType = "jsonrpc_response"
	ResponsePayloadJSONRPCNotify      ResponsePayloadType = "jsonrpc_notify"
	ResponsePayloadNotifyAck          ResponsePayloadType = "notify_ack"
	ResponsePayloadOAuth              ResponsePayloadType = "oauth_discovery_response"
	ResponsePayloadSessionTermination ResponsePayloadType = "session_termination_response"
)

// TunnelResponsePayload mirrors the body posted to POST /v1/tunnel/{tunnel_id}/response when
// delivering MCP results back to tunnel-service.
type TunnelResponsePayload struct {
	RequestID       string              `json:"request_id"`
	Channel         string              `json:"channel,omitempty"`
	JSONResponse    json.RawMessage     `json:"resp_json,omitempty"`
	ResponseHeaders http.Header         `json:"resp_headers,omitempty"`
	ResponseCode    int                 `json:"resp_code,omitempty"`
	ResponseType    ResponsePayloadType `json:"resp_type,omitempty"`
}

// BaseRawPolledCommand contains fields common to all polled command payloads.
// It is embedded by concrete raw command structs for reuse and to keep JSON
// field names stable.
type BaseRawPolledCommand struct {
	RequestID string `json:"request_id"`
	// ShardToken is an opaque value generated by tunnel-service to associate
	// this command with the backend shard or worker responsible for handling
	// its lifecycle. Clients MUST treat this value as opaque and MUST echo
	// it back when posting the response via the HTTP header
	// `X-Tunnel-Shard-Token`. The JSON body of the response MUST NOT contain
	// this token.
	ShardToken string `json:"shard_token"`
	// CommandType is a discriminator for the command payload type.
	CommandType CommandType `json:"command_type"`
	Channel     string      `json:"channel,omitempty"`
	CreatedAt   time.Time   `json:"created_at"`
	Headers     http.Header `json:"headers"`
}

// RawJSONRPCPolledCommand represents a single JSON object returned by
// GET /v1/tunnel/{tunnel_id}/poll before it is converted into the strongly typed
// controlplane.PolledCommand interface.
type RawJSONRPCPolledCommand struct {
	BaseRawPolledCommand
	JSONRPC json.RawMessage `json:"jsonrpc"`
}

// Rely on default json marshal/unmarshal for time.Time fields.

// RawOauthDiscoveryPolledCommand represents an OAuth discovery style command.
// It extends the base fields and may include discovery-specific attributes.
type RawOauthDiscoveryPolledCommand struct {
	BaseRawPolledCommand
}

// RawSessionTerminationPolledCommand represents an explicit Streamable HTTP session close.
type RawSessionTerminationPolledCommand struct {
	BaseRawPolledCommand
}

// Rely on default json marshal/unmarshal for time.Time fields.

// PolledCommandEnvelope is the top-level container returned by
// GET /v1/tunnel/{tunnel_id}/poll that groups pending requests for a tunnel.
type PolledCommandEnvelope struct {
	Commands []json.RawMessage `json:"commands"`
}
