package blocker

import (
	"log"
	"strings"
	"sync"
	"time"
)

type Blocker struct {
	mu              sync.Mutex
	allowedKeywords []string
	running         bool
	stopChan        chan struct{}
	OnBlocked       func(procName string, title string)
	OnKill          func(procName string, title string)
}

var Instance = &Blocker{
	allowedKeywords: []string{"chrome", "idea64", "vscode", "wails", "simple_care", "client"},
	stopChan:        make(chan struct{}),
}

func parseKeywordList(keywords string) []string {
	keywords = strings.ReplaceAll(keywords, "\r\n", "\n")
	parts := strings.FieldsFunc(keywords, func(r rune) bool {
		return r == ',' || r == '\n' || r == ';' || r == '|'
	})
	seen := map[string]bool{}
	var list []string
	for _, p := range parts {
		trimmed := strings.TrimSpace(strings.ToLower(p))
		trimmed = strings.TrimSuffix(trimmed, ".exe")
		if trimmed == "" || seen[trimmed] {
			continue
		}
		seen[trimmed] = true
		list = append(list, trimmed)
	}
	return list
}

var keywordAliases = map[string][]string{
	"lark":   {"lark", "feishu", "larkshell", "larkhelper"},
	"feishu": {"lark", "feishu", "larkshell", "larkhelper"},
	"teams":  {"teams", "ms-teams", "msteams"},
	"zalo":   {"zalo", "zalopcb"},
}

func expandKeyword(kw string) []string {
	base := []string{kw}
	if aliases, ok := keywordAliases[kw]; ok {
		base = append(base, aliases...)
	}
	seen := map[string]bool{}
	var out []string
	for _, a := range base {
		a = strings.TrimSpace(strings.ToLower(a))
		if a != "" && !seen[a] {
			seen[a] = true
			out = append(out, a)
		}
	}
	return out
}

func matchesAllowedKeyword(kw, pNameLower, wTitleLower string) bool {
	for _, variant := range expandKeyword(kw) {
		if strings.Contains(pNameLower, variant) || strings.Contains(wTitleLower, variant) {
			return true
		}
	}
	return false
}

func (b *Blocker) SetKeywords(keywords string) {
	b.mu.Lock()
	b.allowedKeywords = parseKeywordList(keywords)
	b.mu.Unlock()
	log.Printf("[BLOCKER] Keywords updated: %v", b.allowedKeywords)
}

func (b *Blocker) Start() {
	b.mu.Lock()
	if b.running {
		b.mu.Unlock()
		return
	}
	b.running = true
	b.stopChan = make(chan struct{})
	b.mu.Unlock()

	go func() {
		ticker := time.NewTicker(3 * time.Second)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				b.checkAndKill()
			case <-b.stopChan:
				return
			}
		}
	}()
	log.Println("[BLOCKER] Application Blocker Daemon Started.")
}

func (b *Blocker) Stop() {
	b.mu.Lock()
	defer b.mu.Unlock()

	if !b.running {
		return
	}
	b.running = false
	close(b.stopChan)
	log.Println("[BLOCKER] Application Blocker Daemon Stopped.")
}
