package dashscope

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

// ---- 共享类型 ----

// ASRRequest DashScope ASR REST API 请求体。
type ASRRequest struct {
	Model      string     `json:"model"`
	Input      ASRInput   `json:"input"`
	Parameters ASRParams  `json:"parameters"`
}

// ASRInput 音频输入。
type ASRInput struct {
	Audio string `json:"audio"`
}

// ASRParams 识别参数。
type ASRParams struct {
	Format     string `json:"format,omitempty"`
	SampleRate int    `json:"sample_rate,omitempty"`
	Language   string `json:"language,omitempty"`
}

// ASRResponse DashScope ASR REST API 响应体。
type ASRResponse struct {
	Output struct {
		Text string `json:"text"`
	} `json:"output"`
	Usage struct {
		TotalTokens int `json:"total_tokens"`
	} `json:"usage"`
	RequestID string `json:"request_id"`
	Code      string `json:"code,omitempty"`
	Message   string `json:"message,omitempty"`
}

// ---- 共享客户端 ----

// RESTClient 封装 DashScope REST API 的 HTTP 通信。
type RESTClient struct {
	apiKey string
	client *http.Client
}

// NewRESTClient 创建 REST 客户端。
func NewRESTClient(apiKey string) *RESTClient {
	return &RESTClient{
		apiKey: apiKey,
		client: &http.Client{Timeout: 60 * time.Second},
	}
}

// IsAvailable 检查 API Key 是否已配置。
func (c *RESTClient) IsAvailable() bool {
	return c.apiKey != ""
}

// Transcribe 调用 DashScope ASR REST API 进行语音识别。
// audioData 应为 PCM 16kHz mono 格式。
func (c *RESTClient) Transcribe(ctx context.Context, model string, audioData []byte, format string, sampleRate int, language string) (string, error) {
	if !c.IsAvailable() {
		return "", fmt.Errorf("DashScope ASR API key not configured")
	}
	if language == "" || language == "auto" {
		language = "zh"
	}

	audioB64 := base64.StdEncoding.EncodeToString(audioData)

	reqBody := ASRRequest{
		Model: model,
		Input: ASRInput{
			Audio: fmt.Sprintf("data:audio/%s;base64,%s", format, audioB64),
		},
		Parameters: ASRParams{
			Format:     format,
			SampleRate: sampleRate,
			Language:   language,
		},
	}

	bodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return "", fmt.Errorf("marshal ASR request: %w", err)
	}

	url := "https://dashscope.aliyuncs.com/api/v1/services/audio/asr/asr"
	req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(bodyBytes))
	if err != nil {
		return "", fmt.Errorf("create ASR request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+c.apiKey)

	resp, err := c.client.Do(req)
	if err != nil {
		return "", fmt.Errorf("ASR request failed: %w", err)
	}
	defer resp.Body.Close()

	respBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("read ASR response: %w", err)
	}

	var asrResp ASRResponse
	if err := json.Unmarshal(respBytes, &asrResp); err != nil {
		return "", fmt.Errorf("parse ASR response: %w", err)
	}

	if asrResp.Code != "" && asrResp.Code != "0" {
		return "", fmt.Errorf("ASR error: %s (code=%s)", asrResp.Message, asrResp.Code)
	}

	return asrResp.Output.Text, nil
}
