package services

import (
	"bytes"
	"context"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

// SuperUserConfig 超级用户配置
type SuperUserConfig struct {
	Username     string `json:"username"`
	PasswordHash string `json:"password_hash"`
}

// AuthConfig 认证配置
type AuthConfig struct {
	SuperUsers []SuperUserConfig `json:"super_users"`
}

var (
	authConfig     *AuthConfig
	authConfigOnce sync.Once
)

// loadAuthConfig 加载认证配置
func loadAuthConfig() *AuthConfig {
	authConfigOnce.Do(func() {
		// 默认配置（"080500"的MD5 hash值）
		defaultHash := "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" // 这是占位符，实际会计算
		// 计算"080500"的实际hash值
		defaultHash = getPasswordHash("080500")

		authConfig = &AuthConfig{
			SuperUsers: []SuperUserConfig{
				{
					Username:     "super",
					PasswordHash: defaultHash,
				},
			},
		}

		// 尝试从配置文件加载
		configPath := getConfigPath()
		data, err := os.ReadFile(configPath)
		if err != nil {
			LogWarnf("无法读取配置文件 %s，使用默认配置: %v", configPath, err)
			LogInfof("默认超级用户: super, 密码hash: %s (对应密码: 080500)", defaultHash)
			return
		}

		var config AuthConfig
		if err := json.Unmarshal(data, &config); err != nil {
			LogErrorf("解析配置文件失败: %v", err)
			return
		}

		// 验证配置
		if len(config.SuperUsers) == 0 {
			LogWarn("配置文件中没有超级用户，使用默认配置")
			return
		}

		// 检查配置中的hash值，如果是占位符则使用默认值
		for i := range config.SuperUsers {
			hash := config.SuperUsers[i].PasswordHash
			// 检查是否为占位符（包含说明文字或长度不足32位）
			if strings.Contains(hash, "将此处替换") ||
				strings.Contains(hash, "请将此处替换") ||
				strings.Contains(hash, "计算") ||
				strings.Contains(hash, "MD5") ||
				len(hash) < 32 {
				config.SuperUsers[i].PasswordHash = defaultHash
				LogWarnf("检测到占位符hash值，已替换为默认hash: %s (对应密码: 080500)", defaultHash)
			}
		}

		authConfig = &config
		LogInfof("成功加载认证配置，共 %d 个超级用户", len(authConfig.SuperUsers))
		for i, user := range authConfig.SuperUsers {
			LogDebugf("超级用户 %d: 用户名=%s, hash=%s", i+1, user.Username, user.PasswordHash)
		}
	})
	return authConfig
}

// getConfigPath 获取配置文件路径
func getConfigPath() string {
	// 优先使用可执行文件目录下的config.json
	exePath, err := os.Executable()
	if err == nil {
		exeDir := filepath.Dir(exePath)
		configPath := filepath.Join(exeDir, "config.json")
		if _, err := os.Stat(configPath); err == nil {
			return configPath
		}
	}

	// 其次使用当前目录下的config.json
	if _, err := os.Stat("config.json"); err == nil {
		return "config.json"
	}

	// 最后使用wails目录下的config.json
	return "wails/config.json"
}

// AuthService 认证服务
type AuthService struct {
	baseURL string
	client  *http.Client
}

// NewAuthService 创建认证服务实例
func NewAuthService() *AuthService {
	return &AuthService{
		baseURL: "https://admin.xiangbing.vip",
		client: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

// LoginRequest 登录请求
type LoginRequest struct {
	Username   string `json:"Username"`
	Password   string `json:"Password"`
	Platform   string `json:"Platform"`
	PcName     string `json:"PcName"`
	PcUserName string `json:"PcUserName"`
	Ips        string `json:"Ips"`
}

// LoginResponse 登录响应
type LoginResponse struct {
	Code int         `json:"Code"`
	Msg  string      `json:"Msg"`
	Data interface{} `json:"Data"`
}

// getPasswordHash 计算密码的MD5 hash值
func getPasswordHash(password string) string {
	hash := md5.Sum([]byte(password))
	return hex.EncodeToString(hash[:])
}

// checkSuperUser 检查是否为超级用户
func checkSuperUser(username, password string) bool {
	config := loadAuthConfig()

	// 计算输入密码的hash值
	inputPasswordHash := getPasswordHash(password)

	// 遍历配置中的超级用户
	for _, superUser := range config.SuperUsers {
		if superUser.Username == username {
			LogDebugf("超级用户检查 - 用户名: %s, 输入密码hash: %s, 期望hash: %s",
				username, inputPasswordHash, superUser.PasswordHash)

			if inputPasswordHash == superUser.PasswordHash {
				LogInfo("超级用户验证成功")
				return true
			}
		}
	}

	return false
}

// Login 用户登录
func (s *AuthService) Login(ctx context.Context, username, password string) (*LoginResponse, error) {
	startTime := time.Now()
	LogDebugf("Login 开始 - 用户名: %s", username)

	// 检查是否为超级用户
	if checkSuperUser(username, password) {
		LogInfo("检测到超级用户登录，跳过API调用")
		duration := time.Since(startTime)
		LogInfof("超级用户登录成功 - 用户名: %s, 耗时: %v", username, duration)

		return &LoginResponse{
			Code: 200,
			Msg:  "登录成功",
			Data: map[string]interface{}{
				"username": "super",
				"isSuper":  true,
			},
		}, nil
	}

	// 获取机器信息
	pcMachineName, _ := os.Hostname()
	pcUserName := os.Getenv("USERNAME")
	if pcUserName == "" {
		pcUserName = os.Getenv("USER")
	}

	// 获取 IP 地址
	var ips string
	addrs, err := net.InterfaceAddrs()
	if err == nil {
		for _, addr := range addrs {
			if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
				if ipnet.IP.To4() != nil {
					ips = ipnet.IP.String()
					break
				}
			}
		}
	}

	LogDebugf("机器信息 - 主机名: %s, 用户名: %s, IP: %s", pcMachineName, pcUserName, ips)

	reqData := LoginRequest{
		Username:   username,
		Password:   password,
		Platform:   "pc",
		PcName:     pcMachineName,
		PcUserName: pcUserName,
		Ips:        ips,
	}

	jsonData, err := json.Marshal(reqData)
	if err != nil {
		LogErrorf("序列化请求数据失败: %v", err)
		return nil, fmt.Errorf("序列化请求数据失败: %v", err)
	}

	url := s.baseURL + "/api/base/login"
	LogDebugf("发送登录请求 - URL: %s, 请求数据: %s", url, string(jsonData))

	req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		LogErrorf("创建请求失败: %v", err)
		return nil, fmt.Errorf("创建请求失败: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")

	resp, err := s.client.Do(req)
	if err != nil {
		LogErrorf("请求失败: %v", err)
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	LogDebugf("收到响应 - 状态码: %d, 状态: %s", resp.StatusCode, resp.Status)

	var loginResp LoginResponse
	if err := json.NewDecoder(resp.Body).Decode(&loginResp); err != nil {
		LogErrorf("解析响应失败: %v", err)
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	duration := time.Since(startTime)
	LogInfof("Login 完成 - 用户名: %s, 响应码: %d, 消息: %s, 耗时: %v",
		username, loginResp.Code, loginResp.Msg, duration)

	return &loginResp, nil
}
