package utils

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"time"
)

type WxSessionResult struct {
	OpenID     string `json:"openid"`
	SessionKey string `json:"session_key"`
	UnionID    string `json:"unionid"`
	ErrCode    int    `json:"errcode"`
	ErrMsg     string `json:"errmsg"`
}

// Code2Session exchanges mini-program login code for openid.
func Code2Session(code string) (*WxSessionResult, error) {
	appID := os.Getenv("WECHAT_APP_ID")
	secret := os.Getenv("WECHAT_APP_SECRET")
	if appID == "" {
		appID = "wx67e73fb3c9882dfc"
	}
	if secret == "" {
		return nil, fmt.Errorf("WECHAT_APP_SECRET is not configured")
	}

	q := url.Values{}
	q.Set("appid", appID)
	q.Set("secret", secret)
	q.Set("js_code", code)
	q.Set("grant_type", "authorization_code")

	endpoint := "https://api.weixin.qq.com/sns/jscode2session?" + q.Encode()
	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Get(endpoint)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var result WxSessionResult
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, err
	}
	if result.ErrCode != 0 || result.OpenID == "" {
		return nil, fmt.Errorf("jscode2session failed: %d %s", result.ErrCode, result.ErrMsg)
	}
	return &result, nil
}
