package main

import (
	"net/http"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

func profileHandler(w http.ResponseWriter, r *http.Request) {
	configMu.RLock()
	mfaEnabled := config.MFASecret != ""
	configMu.RUnlock()

	data := struct {
		MFAEnabled bool
	}{
		MFAEnabled: mfaEnabled,
	}
	renderTemplate(w, r, "profile.html", data)
}

func dashboardHandler(w http.ResponseWriter, r *http.Request) {
	renderTemplate(w, r, "dashboard.html", nil)
}

func urlListsHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		action := r.FormValue("action")
		url := sanitizeInput(r.FormValue("url"))
		indexStr := r.FormValue("index")

		configMu.RLock()
		urlFileList := config.URLFileList
		configMu.RUnlock()

		urls, err := readLines(urlFileList)
		if err != nil {
			http.Error(w, "Error reading URL list", http.StatusInternalServerError)
			return
		}

		switch action {
		case "add":
			if isValidURL(url) {
				urls = append(urls, url)
			}
		case "remove":
			index, _ := strconv.Atoi(indexStr)
			if index >= 0 && index < len(urls) {
				urls = append(urls[:index], urls[index+1:]...)
			}
		case "toggle":
			// Assume enabled/disabled by commenting out with #
			index, _ := strconv.Atoi(indexStr)
			if index >= 0 && index < len(urls) {
				if strings.HasPrefix(urls[index], "#") {
					urls[index] = strings.TrimPrefix(urls[index], "#")
				} else {
					urls[index] = "#" + urls[index]
				}
			}
		}

		writeLines(urlFileList, urls)
		http.Redirect(w, r, "/urllists", http.StatusSeeOther)
		return
	}

	configMu.RLock()
	urlFileList := config.URLFileList
	defaultURLs := config.DefaultURLs
	configMu.RUnlock()

	urls, _ := readLines(urlFileList)
	if len(urls) == 0 {
		writeLines(urlFileList, defaultURLs)
		urls = defaultURLs
	}

	data := struct {
		URLs []string
	}{
		URLs: urls,
	}
	renderTemplate(w, r, "urllists.html", data)
}

func domainsHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		action := r.FormValue("action")
		domain := sanitizeInput(r.FormValue("domain"))

		configMu.RLock()
		blocklistFile := config.BlocklistFile
		configMu.RUnlock()

		domains, err := readLines(blocklistFile)
		if err != nil {
			http.Error(w, "Error reading domains", http.StatusInternalServerError)
			return
		}

		switch action {
		case "add":
			if isValidDomain(domain) {
				domains = append(domains, domain)
				sort.Strings(domains)
			}
		case "remove":
			for i, d := range domains {
				if d == domain {
					domains = append(domains[:i], domains[i+1:]...)
					break
				}
			}
		}

		writeLines(blocklistFile, domains)
		http.Redirect(w, r, "/domains", http.StatusSeeOther)
		return
	}

	configMu.RLock()
	blocklistFile := config.BlocklistFile
	configMu.RUnlock()

	query := r.URL.Query().Get("query")
	domains, _ := readLines(blocklistFile)

	var filtered []string
	if query != "" {
		query = strings.ReplaceAll(query, "*", ".*")
		re, err := regexp.Compile("(?i)" + query)
		if err == nil {
			for _, d := range domains {
				if re.MatchString(d) {
					filtered = append(filtered, d)
				}
			}
		}
	} else {
		filtered = domains
	}

	data := struct {
		Domains []string
		Query   string
	}{
		Domains: filtered,
		Query:   query,
	}
	renderTemplate(w, r, "domains.html", data)
}

func applyHandler(w http.ResponseWriter, r *http.Request) {
	userInitiatedMu.Lock()
	userInitiated = true
	userInitiatedMu.Unlock()

	updateBlocklist(1) // Force

	userInitiatedMu.Lock()
	userInitiated = false
	userInitiatedMu.Unlock()

	http.Redirect(w, r, "/", http.StatusSeeOther)
}

func logsHandler(w http.ResponseWriter, r *http.Request) {
	// For simplicity, assume logs are in stdout, or implement file logging
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Logs placeholder"))
}
