package main

import (
	"cmp"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/sirrobot01/decypharr/internal/config"
	"net/http"
	"os"
	"strings"
	"time"
)

// HealthStatus represents the status of various components
type HealthStatus struct {
	QbitAPI       bool `json:"qbit_api"`
	WebUI         bool `json:"web_ui"`
	WebDAVService bool `json:"webdav_service"`
	OverallStatus bool `json:"overall_status"`
}

func main() {
	var configPath string
	flag.StringVar(&configPath, "config", "/data", "path to the data folder")
	flag.Parse()
	config.SetConfigPath(configPath)
	cfg := config.Get()
	// Get port from environment variable or use default
	port := getEnvOrDefault("QBIT_PORT", cfg.Port)
	webdavPath := ""
	for _, debrid := range cfg.Debrids {
		if debrid.UseWebDav {
			webdavPath = debrid.Name
		}
	}

	// Initialize status
	status := HealthStatus{
		QbitAPI:       false,
		WebUI:         false,
		WebDAVService: false,
		OverallStatus: false,
	}

	// Create a context with timeout for all HTTP requests
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	baseUrl := cmp.Or(cfg.URLBase, "/")
	if !strings.HasPrefix(baseUrl, "/") {
		baseUrl = "/" + baseUrl
	}

	// Check qBittorrent API
	if checkQbitAPI(ctx, baseUrl, port) {
		status.QbitAPI = true
	}

	// Check Web UI
	if checkWebUI(ctx, baseUrl, port) {
		status.WebUI = true
	}

	// Check WebDAV if enabled
	if webdavPath != "" {
		if checkWebDAV(ctx, baseUrl, port, webdavPath) {
			status.WebDAVService = true
		}
	} else {
		// If WebDAV is not enabled, consider it healthy
		status.WebDAVService = true
	}

	// Determine overall status
	// Consider the application healthy if core services are running
	status.OverallStatus = status.QbitAPI && status.WebUI
	if webdavPath != "" {
		status.OverallStatus = status.OverallStatus && status.WebDAVService
	}

	// Optional: output health status as JSON for logging
	if os.Getenv("DEBUG") == "true" {
		statusJSON, _ := json.MarshalIndent(status, "", "  ")
		fmt.Println(string(statusJSON))
	}

	// Exit with appropriate code
	if status.OverallStatus {
		os.Exit(0)
	} else {
		os.Exit(1)
	}
}

func getEnvOrDefault(key, defaultValue string) string {
	if value, exists := os.LookupEnv(key); exists {
		return value
	}
	return defaultValue
}

func checkQbitAPI(ctx context.Context, baseUrl, port string) bool {
	url := fmt.Sprintf("http://localhost:%s%sapi/v2/app/version", port, baseUrl)
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		return false
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return false
	}
	defer resp.Body.Close()

	return resp.StatusCode == http.StatusOK
}

func checkWebUI(ctx context.Context, baseUrl, port string) bool {
	req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%s%s", port, baseUrl), nil)
	if err != nil {
		return false
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return false
	}
	defer resp.Body.Close()

	return resp.StatusCode == http.StatusOK
}

func checkWebDAV(ctx context.Context, baseUrl, port, path string) bool {
	url := fmt.Sprintf("http://localhost:%s%swebdav/%s", port, baseUrl, path)
	req, err := http.NewRequestWithContext(ctx, "PROPFIND", url, nil)
	if err != nil {
		return false
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return false
	}
	defer resp.Body.Close()

	return resp.StatusCode == 207 || resp.StatusCode == http.StatusOK
}
