package douyin

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

const (
	// PhoneNumberURL Douyin get phone number interface address
	PhoneNumberURL = "https://developer.toutiao.com/api/apps/v1/number_get/bind/"
)

// PhoneNumberRequest request parameters
type PhoneNumberRequest struct {
	AppID string `json:"app_id"` // Note: specific parameter name might vary, but usually it's app_id or appid. Docs say `app_id` for some v1 interfaces.
	Code  string `json:"code"`
}

// PhoneNumberResponse response
type PhoneNumberResponse struct {
	ErrNo   int    `json:"err_no"`
	ErrTips string `json:"err_tips"`
	Data    struct {
		PhoneNumber string `json:"phone_number"`
	} `json:"data"`
}

// GetPhoneNumber calls Douyin interface to get user phone number
func GetPhoneNumber(ctx context.Context, accessToken, appID, code string) (string, error) {
	if accessToken == "" || code == "" {
		return "", fmt.Errorf("missing parameters")
	}

	// Note: Verify the correct endpoint and parameters.
	// Commonly for `v1/number_get/bind/`, it might expect `encryptedData`?
	// But `tt.getPhoneNumber` provides `code`.
	// Let's assume the modern Code-based API which is often similar to `number_get/bind` but with `code`.
	// Check if we need to call `https://developer.toutiao.com/api/apps/v1/user/get_phone_number_v1` instead?
	// Or `https://developer.open-douyin.com/api/apps/v1/img/get_phone_number_v1`?
	// Since I cannot verify the exact URL visually, I will stick to the one I hypothesized or the most "standard" one found in similar Go SDKs.
	// Actually, let's try to assume it's `POST /api/apps/v2/jscode2session` style but for phone.

	// A common variation for "get phone number by code" in Douyin is sending `code` and `app_id` to an endpoint.
	// Let's go with the one stated in many online resources for "Douyin Mini Program Get Phone Number".

	reqBody := map[string]string{
		"app_id": appID,
		"code":   code,
	}

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

	httpClient := &http.Client{Timeout: 10 * time.Second}
	// The URL might need `access_token` in query param or header?
	// Most `v1` Douyin APIs require `access_token` in header or query. We will put in header `access-token`.

	req, err := http.NewRequestWithContext(ctx, "POST", PhoneNumberURL, strings.NewReader(string(jsonBody)))
	if err != nil {
		return "", fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	// Some docs say `access-token` in header
	req.Header.Set("access-token", accessToken)

	resp, err := httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("failed to request Douyin interface: %w", err)
	}
	defer resp.Body.Close()

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

	var result PhoneNumberResponse
	if err := json.Unmarshal(body, &result); err != nil {
		return "", fmt.Errorf("failed to parse response: %w, body: %s", err, string(body))
	}

	if result.ErrNo != 0 {
		return "", fmt.Errorf("failed to get phone number: %s (code: %d)", result.ErrTips, result.ErrNo)
	}

	return result.Data.PhoneNumber, nil
}
