package main

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

type config struct {
	APIURL     string
	ProductKey string
	LicenseKey string
	ServerIP   string
}

type validateResponse struct {
	Status  string `json:"status"`
	Valid   bool   `json:"valid"`
	Message string `json:"message"`
	Data    struct {
		ProductKey string `json:"product_key"`
		LicenseKey string `json:"license_key"`
		IP         string `json:"ip"`
		ExpiresAt  string `json:"expires_at"`
		Expired    bool   `json:"expired"`
	} `json:"data"`
}

func main() {
	cfg, err := loadConfig("/etc/cpanelv3internal/license.env")
	if err != nil {
		fmt.Println("config error:", err)
		os.Exit(1)
	}

	if cfg.ServerIP == "" {
		cfg.ServerIP = detectIP()
	}

	if cfg.ServerIP == "" {
		fmt.Println("server ip is required")
		os.Exit(1)
	}

	result, err := validate(cfg)
	if err != nil {
		fmt.Println("license check failed:", err)
		os.Exit(1)
	}

	fmt.Printf("license check ok: %s expires at %s\n", result.Data.ProductKey, result.Data.ExpiresAt)
}

func loadConfig(path string) (config, error) {
	raw, err := os.ReadFile(path)
	if err != nil {
		return config{}, err
	}

	cfg := config{
		APIURL:     "https://zwa7f.com/api/client/licenses/validate",
		ProductKey: "cpanelv3internal",
	}

	for _, line := range strings.Split(string(raw), "\n") {
		line = strings.TrimSpace(line)
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}

		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			continue
		}

		key := strings.TrimSpace(parts[0])
		value := strings.Trim(strings.TrimSpace(parts[1]), "\"'")

		switch key {
		case "API_URL":
			cfg.APIURL = value
		case "PRODUCT_KEY":
			cfg.ProductKey = value
		case "LICENSE_KEY":
			cfg.LicenseKey = value
		case "SERVER_IP":
			cfg.ServerIP = value
		}
	}

	return cfg, nil
}

func detectIP() string {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return ""
	}

	for _, addr := range addrs {
		ipNet, ok := addr.(*net.IPNet)
		if !ok || ipNet.IP.IsLoopback() {
			continue
		}

		if ip := ipNet.IP.To4(); ip != nil {
			return ip.String()
		}
	}

	return ""
}

func validate(cfg config) (*validateResponse, error) {
	values := url.Values{}
	values.Set("product_key", cfg.ProductKey)
	values.Set("ip", cfg.ServerIP)
	if cfg.LicenseKey != "" {
		values.Set("license_key", cfg.LicenseKey)
	}

	client := http.Client{Timeout: 20 * time.Second}
	resp, err := client.Get(cfg.APIURL + "?" + values.Encode())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result validateResponse
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	if !result.Valid {
		if result.Message == "" {
			result.Message = "invalid license"
		}
		return &result, fmt.Errorf("%s", result.Message)
	}

	return &result, nil
}
