package service

import (
	"ai_xhs/config"
	"ai_xhs/database"
	"ai_xhs/models"
	"ai_xhs/utils"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
)

type AuthService struct{}

func NewAuthService() *AuthService {
	return &AuthService{}
}

// 微信手机号响应
type WxPhoneResponse struct {
	PhoneInfo struct {
		PhoneNumber     string `json:"phoneNumber"`
		PurePhoneNumber string `json:"purePhoneNumber"`
		CountryCode     string `json:"countryCode"`
	} `json:"phone_info"`
	ErrCode int    `json:"errcode"`
	ErrMsg  string `json:"errmsg"`
}

// 微信登录响应
type WxLoginResponse struct {
	OpenID     string `json:"openid"`
	SessionKey string `json:"session_key"`
	UnionID    string `json:"unionid"`
	ErrCode    int    `json:"errcode"`
	ErrMsg     string `json:"errmsg"`
}

// WechatLogin 微信小程序登录
func (s *AuthService) WechatLogin(code string, phone string, phoneCode string) (string, *models.User, error) {
	// 1. 调用微信API验证code
	// 注意：需要在配置文件中添加小程序的AppID和AppSecret
	appID := config.AppConfig.Wechat.AppID
	appSecret := config.AppConfig.Wechat.AppSecret

	// 调试日志：打印配置信息
	log.Printf("[微信登录] AppID: %s, AppSecret: %s (长度:%d)", appID, appSecret, len(appSecret))

	// 如果没有配置微信AppID，使用手机号登录逻辑
	if appID == "" || appSecret == "" {
		if phone == "" {
			// 没有配置微信且没有手机号，使用默认员工ID=1
			return s.loginByEmployeeID(1)
		}
		// 使用手机号登录
		return s.PhoneLogin(phone)
	}

	// 调用微信API
	url := fmt.Sprintf(
		"https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
		appID, appSecret, code,
	)

	// 调试日志：打印请求URL（隐藏密钥）
	log.Printf("[微信登录] 请求URL: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=***&js_code=%s&grant_type=authorization_code", appID, code)

	resp, err := http.Get(url)
	if err != nil {
		return "", nil, fmt.Errorf("调用微信API失败: %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", nil, fmt.Errorf("读取响应失败: %v", err)
	}

	// 调试日志：打印微信返回的原始响应
	log.Printf("[微信登录] 微信API响应: %s", string(body))

	var wxResp WxLoginResponse
	if err := json.Unmarshal(body, &wxResp); err != nil {
		return "", nil, fmt.Errorf("解析响应失败: %v", err)
	}

	if wxResp.ErrCode != 0 {
		return "", nil, fmt.Errorf("微信登录失败: %s", wxResp.ErrMsg)
	}

	// 1.5 如果有 phoneCode，调用微信API获取手机号
	if phoneCode != "" {
		accessTokenURL := fmt.Sprintf(
			"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
			appID, appSecret,
		)

		// 获取 access_token
		accessTokenResp, err := http.Get(accessTokenURL)
		if err != nil {
			log.Printf("获取access_token失败: %v", err)
		} else {
			defer accessTokenResp.Body.Close()
			accessTokenBody, _ := io.ReadAll(accessTokenResp.Body)

			var tokenResult struct {
				AccessToken string `json:"access_token"`
				ErrCode     int    `json:"errcode"`
				ErrMsg      string `json:"errmsg"`
			}

			if err := json.Unmarshal(accessTokenBody, &tokenResult); err == nil && tokenResult.AccessToken != "" {
				// 获取手机号
				phoneURL := fmt.Sprintf(
					"https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s",
					tokenResult.AccessToken,
				)

				phoneReqBody := map[string]string{"code": phoneCode}
				phoneReqJSON, _ := json.Marshal(phoneReqBody)

				phoneResp, err := http.Post(phoneURL, "application/json", bytes.NewBuffer(phoneReqJSON))
				if err == nil {
					defer phoneResp.Body.Close()
					phoneBody, _ := io.ReadAll(phoneResp.Body)

					var phoneResult WxPhoneResponse
					if err := json.Unmarshal(phoneBody, &phoneResult); err == nil && phoneResult.ErrCode == 0 {
						// 获取手机号成功，覆盖 phone 参数
						phone = phoneResult.PhoneInfo.PurePhoneNumber
						log.Printf("[微信登录] 获取手机号成功: %s", phone)
					} else {
						log.Printf("[微信登录] 获取手机号失败: %s", string(phoneBody))
					}
				}
			}
		}
	}

	// 2. 根据OpenID查找或创建员工
	var employee models.User

	// 优先通过OpenID查找（注意：使用IS NOT NULL过滤空值）
	result := database.DB.Where("wechat_openid = ? AND wechat_openid IS NOT NULL", wxResp.OpenID).First(&employee)

	if result.Error != nil {
		// OpenID不存在，需要绑定OpenID
		if phone == "" {
			return "", nil, errors.New("首次登录请提供手机号")
		}

		// 通过手机号查找员工
		result = database.DB.Where("phone = ? AND status = ?", phone, "active").First(&employee)
		if result.Error != nil {
			return "", nil, errors.New("员工不存在，请联系管理员添加")
		}

		// 绑定OpenID和UnionID（使用指针）
		employee.WechatOpenID = &wxResp.OpenID
		if wxResp.UnionID != "" {
			employee.WechatUnionID = &wxResp.UnionID
		}
		database.DB.Save(&employee)
	}

	// 3. 生成JWT token
	token, err := utils.GenerateToken(employee.ID)
	if err != nil {
		return "", nil, fmt.Errorf("生成token失败: %v", err)
	}

	return token, &employee, nil
}

// PhoneLogin 手机号登录（用于测试或无微信配置时）
func (s *AuthService) PhoneLogin(phone string) (string, *models.User, error) {
	var employee models.User

	// 查找员工
	result := database.DB.Where("phone = ? AND status = ?", phone, "active").First(&employee)
	if result.Error != nil {
		return "", nil, errors.New("员工不存在或已被禁用")
	}

	// 生成token
	token, err := utils.GenerateToken(employee.ID)
	if err != nil {
		return "", nil, fmt.Errorf("生成token失败: %v", err)
	}

	return token, &employee, nil
}

// loginByEmployeeID 通过员工ID登录（内部方法）
func (s *AuthService) loginByEmployeeID(employeeID int) (string, *models.User, error) {
	var employee models.User

	result := database.DB.Where("id = ? AND status = ?", employeeID, "active").First(&employee)
	if result.Error != nil {
		return "", nil, errors.New("员工不存在或已被禁用")
	}

	// 生成token
	token, err := utils.GenerateToken(employee.ID)
	if err != nil {
		return "", nil, fmt.Errorf("生成token失败: %v", err)
	}

	return token, &employee, nil
}
