package main

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

type Config struct {
	UpdateURL           string `json:"update_url"`
	CheckIntervalSecs   int    `json:"check_interval_seconds"`
	IPCheckURL          string `json:"ip_check_url"`
}

func loadConfig(path string) (*Config, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var cfg Config
	err = json.Unmarshal(data, &cfg)
	if err != nil {
		return nil, err
	}
	return &cfg, nil
}

func getPublicIP(ipURL string) (string, error) {
	resp, err := http.Get(ipURL)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

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

	return strings.TrimSpace(string(body)), nil
}

func updateDDNS(url string) error {
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("failed, status code %d", resp.StatusCode)
	}
	return nil
}

func main() {
	cfg, err := loadConfig("config.json")
	if err != nil {
		fmt.Println("Failed to load config:", err)
		os.Exit(1)
	}

	//var lastIP string
	lastIP, err := getPublicIP(cfg.IPCheckURL)
	if err != nil {
		fmt.Println("Error getting intial public IP:", err)
		lastIP = ""
	} else {
		fmt.Println(time.Now(), "Starting with current IP:", lastIP)
	}

	ticker := time.NewTicker(time.Duration(cfg.CheckIntervalSecs) * time.Second)
	defer ticker.Stop()

	for {
		ip, err := getPublicIP(cfg.IPCheckURL)
		if err != nil {
			fmt.Println("Error getting public IP:", err)
		} else if ip != lastIP {
			fmt.Println(time.Now(), "IP changed to", ip)
			if err := updateDDNS(cfg.UpdateURL); err != nil {
				fmt.Println("Failed to update DDNS:", err)
			} else {
				fmt.Println(time.Now(), "DDNS updated successfully")
				lastIP = ip
			}
		} else {
			fmt.Println(time.Now(), "IP unchanged:", ip)
		}

		<-ticker.C
	}
}
