package main

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"regexp"
	"sync"
	"time"
)

type Monitor struct {
	name      string
	url       string
	http_code int
	pattern   string
	timeout   time.Duration
	// TLS TODO
}

type CheckResult struct {
	name      string
	status    bool
	http_code int
	duration  time.Duration
	//message   string
}

type Worklist struct {
	name     string
	monitors []Monitor
}

var http_client = &http.Client{
	Timeout: 5000 * time.Millisecond,
}

func GetWorklist() Worklist {

	var wl Worklist
	wl.name = "Test"
	wl.monitors = append(wl.monitors, Monitor{
		name:      "monitor1",
		url:       "https://www.cavaliba.com/",
		http_code: 200,
		pattern:   "cavaliba",
		timeout:   time.Duration(500) * time.Millisecond,
	})
	wl.monitors = append(wl.monitors, Monitor{
		name:      "monitor2",
		url:       "https://www.cavaliba.com/download/",
		http_code: 200,
		pattern:   "Directory",
		timeout:   time.Duration(500) * time.Millisecond,
	})
	wl.monitors = append(wl.monitors, Monitor{
		name:      "monitor2",
		url:       "https://www.apache.org/",
		http_code: 200,
		pattern:   "Community",
		timeout:   time.Duration(500) * time.Millisecond,
	})
	return wl

}

// check a single Monitor
func Check(monitor Monitor) CheckResult {

	var result CheckResult

	result.name = monitor.name
	result.status = false

	timeout := monitor.timeout
	ctx, cancel := context.WithTimeout(context.Background(),
		timeout)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx,
		http.MethodGet,
		monitor.url,
		nil)
	if err != nil {
		return result
	}

	start := time.Now()

	resp, err := http_client.Do(req)
	if err != nil {
		return result
	}
	defer resp.Body.Close()

	result.duration = time.Since(start)

	//expected_status := http.StatusOK
	result.http_code = resp.StatusCode
	if resp.StatusCode != monitor.http_code {
		return result
	}

	//fmt.Println(resp.Header.Get("Content-Type"))

	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		//log.Println(err)
		return result
	}
	bodyString := string(bodyBytes)

	//provided := "cavaliba"
	pattern, _ := regexp.Compile(monitor.pattern)
	if pattern.MatchString(bodyString) {
		result.status = true
	}

	return result
}

func main() {
	fmt.Println("Start cavmonitor")

	// client := &http.Client{
	// 	Timeout: 5000 * time.Millisecond,
	// }

	// monitor := Monitor{
	// 	name:      "monitor1",
	// 	url:       "https://www.cavaliba.com/",
	// 	http_code: 200,
	// 	pattern:   "cavaliba",
	// 	timeout:   time.Duration(200) * time.Millisecond,
	// }

	worklist := GetWorklist()
	fmt.Println(worklist)

	start := time.Now()
	wg := sync.WaitGroup{}
	wg.Add(len(worklist.monitors))

	for i, monitor := range worklist.monitors {

		go func() {
			//ch <- fmt.Sprintf("%s: %d", url, res.StatusCode)
			defer wg.Done()
			fmt.Println(i, monitor)
			result := Check(monitor)
			fmt.Println("Result:", result.status)
		}()

	}

	wg.Wait()
	duration := time.Since(start)
	fmt.Println("Done - duration = ", duration)
	// result := Check(monitor)
	// fmt.Println("Monitor: ", monitor)
	// fmt.Println("Result:", result)
	// fmt.Println("Status:", result.status)
	// fmt.Println("HTTP Code:", result.http_code)
	// fmt.Println("Duration: ", result.duration)

}
