package telegram

import (
	
	
	

	
	

	
	
	
	
)

var (
	tdlibToTelegramMap     map[string]string
	tdlibToTelegramMapOnce sync.Once
)

// buildTDLibToTelegramMap builds reverse mapping from TDLib method names
// (e.g., "sendMessage") to Telegram API names (e.g., "messages.sendMessage").
func () map[string]string {
	tdlibToTelegramMapOnce.Do(func() {
		 := tg.NamesMap()
		tdlibToTelegramMap = make(map[string]string)

		// Build reverse mapping: for each entry in NamesMap that looks like a method request,
		// create mapping from TDLib name (without namespace) to full name
		for  := range  {
			// Only process method requests (they contain a dot and end with "Request" conceptually)
			// In NamesMap, request methods are stored as "namespace.methodName"
			if !strings.Contains(, ".") {
				continue
			}

			// Extract method name without namespace
			 := strings.SplitN(, ".", 2)
			if len() != 2 {
				continue
			}
			 := [1]

			// Skip result types and constructors (they don't have "Request" in their name pattern)
			// Request methods in NamesMap are like "messages.sendMessage", "auth.sendCode", etc.
			// We want to map "sendMessage" -> "messages.sendMessage"
			// Skip types that are clearly not methods (like "auth.authorization", "messages.messages")
			if strings.HasSuffix(, "TypeID") ||
				strings.HasSuffix(, "Class") {
				continue
			}

			// Check if the type ID corresponds to a Request type by checking the constructors map
			// Request types in NamesMap map to RequestTypeID constants
			// We'll include it in the mapping - if it's not a request, it will fail later during invocation
			// This is simpler than trying to detect all request types upfront
			tdlibToTelegramMap[] = 
		}
	})

	return tdlibToTelegramMap
}

// InvokeRawJSON invokes MTProto method using pure TDLib JSON format.
// It accepts JSON with @type field in TDLib format (e.g., "sendMessage")
// and returns JSON response in TDLib format.
//
// The JSON structure, keys and values exactly match TDLib standard JSON.
// For example, use "sendMessage" not "messages.sendMessage" in @type field.
func ( *Client) ( context.Context,  string) ( string,  error) {
	// Parse JSON to extract @type
	 := jx.DecodeStr()
	 := tdjson.Decoder{Decoder: }

	,  := .FindTypeID()
	if  != nil {
		return "", errors.Wrap(, "find @type field")
	}

	// Map TDLib method name to Telegram API name
	 := buildTDLibToTelegramMap()
	,  := []
	if ! {
		// Try direct lookup in case it's already in full format
		 := tg.NamesMap()
		if ,  := [];  {
			 = 
		} else {
			return "", errors.Errorf("unknown method: %q", )
		}
	}

	// Lookup type ID
	 := tg.NamesMap()
	,  := []
	if ! {
		return "", errors.Errorf("type not found: %q", )
	}

	// Create instance
	 := tg.TypesConstructorMap()
	,  := []
	if ! {
		return "", errors.Errorf("constructor not found for type: %q (id: 0x%x)", , )
	}

	 := ()
	if  == nil {
		return "", errors.Errorf("failed to create instance for type: %q", )
	}

	// Check if instance supports TDLib JSON decoding
	,  := .(tdjson.TDLibDecoder)
	if ! {
		return "", errors.Errorf("type %q does not support TDLib JSON decoding", )
	}

	// Decode JSON into instance (create new decoder for full decode)
	 := jx.DecodeStr()
	 := tdjson.Decoder{Decoder: }
	if  := .DecodeTDLibJSON();  != nil {
		return "", errors.Wrapf(, "decode TDLib JSON for %q", )
	}

	// Ensure instance implements bin.Encoder
	,  := .(bin.Encoder)
	if ! {
		return "", errors.Errorf("type %q does not implement bin.Encoder", )
	}

	// Invoke via existing Invoke method with a decoder that can handle any response type
	 := &rawJSONResponseDecoder{}
	if  := .Invoke(, , );  != nil {
		// Check if it's an RPC error and convert to TDLib JSON error format
		if ,  := tgerr.As();  {
			return encodeTDLibError(), nil
		}
		return "", errors.Wrap(, "invoke")
	}

	 := .result
	if  == nil {
		return "", errors.New("empty response")
	}

	// Encode response to TDLib JSON
	,  := .(tdjson.TDLibEncoder)
	if ! {
		return "", errors.Errorf("response type does not support TDLib JSON encoding")
	}

	var  jx.Writer
	 := tdjson.Encoder{Writer: &}
	if  := .EncodeTDLibJSON();  != nil {
		return "", errors.Wrap(, "encode response to TDLib JSON")
	}

	return .String(), nil
}

// rawJSONResponseDecoder is a decoder that can decode any response type
// and store it as bin.Object for later JSON encoding.
type rawJSONResponseDecoder struct {
	result bin.Object
}

func ( *rawJSONResponseDecoder) ( *bin.Buffer) error {
	// Peek at the type ID to determine what to decode
	,  := .PeekID()
	if  != nil {
		return errors.Wrap(, "peek response type ID")
	}

	// Use TypesConstructorMap to create appropriate instance
	 := tg.TypesConstructorMap()
	,  := []
	if ! {
		return errors.Errorf("unknown response type: 0x%x", )
	}

	 := ()
	if  == nil {
		return errors.Errorf("failed to create response instance for type: 0x%x", )
	}

	// Decode into instance
	,  := .(bin.Decoder)
	if ! {
		return errors.Errorf("response type does not implement bin.Decoder")
	}

	if  := .Decode();  != nil {
		return errors.Wrap(, "decode response")
	}

	// Store as bin.Object
	if ,  := .(bin.Object);  {
		.result = 
	} else {
		return errors.New("response is not a bin.Object")
	}

	return nil
}

// encodeTDLibError encodes tgerr.Error to TDLib JSON error format.
func ( *tgerr.Error) string {
	// TDLib error format: {"@type":"error","code":420,"message":"FLOOD_WAIT_3"}
	var  jx.Writer
	.ObjStart()
	.FieldStart("@type")
	.Str("error")
	.Comma()
	.FieldStart("code")
	.Int(.Code)
	.Comma()
	.FieldStart("message")
	.Str(.Message)
	.ObjEnd()
	return .String()
}