package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type Config struct {
	AppEnv          string `json:"app_env"`
	ListenAddr     string `json:"listen_addr"`
	ProjectRoot    string `json:"project_root"`
	DataDir        string `json:"data_dir"`
	InternalToken  string `json:"-"`
	RealAutomation bool   `json:"real_automation"`
	RealChat       bool   `json:"real_chat"`
	RealPayment    bool   `json:"real_payment"`
}

type Response struct {
	OK        bool        `json:"ok"`
	Service   string      `json:"service"`
	Timestamp string      `json:"timestamp"`
	Message   string      `json:"message,omitempty"`
	Data      interface{} `json:"data,omitempty"`
}

func main() {
	cfg := loadConfig()

	mux := http.NewServeMux()

	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		writeJSON(w, http.StatusOK, Response{
			OK:        true,
			Service:   "gerenciador-go-worker",
			Timestamp: time.Now().Format(time.RFC3339),
			Message:   "Go worker ativo",
			Data: map[string]interface{}{
				"app_env":          cfg.AppEnv,
				"real_automation": cfg.RealAutomation,
				"real_chat":       cfg.RealChat,
				"real_payment":    cfg.RealPayment,
			},
		})
	})

	mux.HandleFunc("/info", withAuth(cfg, func(w http.ResponseWriter, r *http.Request) {
		writeJSON(w, http.StatusOK, Response{
			OK:        true,
			Service:   "gerenciador-go-worker",
			Timestamp: time.Now().Format(time.RFC3339),
			Message:   "Configuração carregada",
			Data: map[string]interface{}{
				"project_root": cfg.ProjectRoot,
				"data_dir":     cfg.DataDir,
				"data_exists":   dirExists(cfg.DataDir),
			},
		})
	}))

	mux.HandleFunc("/sync/vendas", withAuth(cfg, dryRunHandler(cfg, "sync_vendas")))
	mux.HandleFunc("/sync/perguntas", withAuth(cfg, dryRunHandler(cfg, "sync_perguntas")))
	mux.HandleFunc("/sync/chats", withAuth(cfg, dryRunHandler(cfg, "sync_chats")))

	log.Printf("gerenciador-go-worker iniciado em %s | env=%s | data=%s", cfg.ListenAddr, cfg.AppEnv, cfg.DataDir)

	if err := http.ListenAndServe(cfg.ListenAddr, mux); err != nil {
		log.Fatal(err)
	}
}

func loadConfig() Config {
	projectRoot := env("PROJECT_ROOT", "..")
	absRoot, err := filepath.Abs(projectRoot)
	if err == nil {
		projectRoot = absRoot
	}

	cfg := Config{
		AppEnv:          env("APP_ENV", "testing"),
		ListenAddr:      env("GO_WORKER_ADDR", "127.0.0.1:8787"),
		ProjectRoot:     projectRoot,
		DataDir:         env("DATA_DIR", filepath.Join(projectRoot, "data")),
		InternalToken:   env("GO_WORKER_TOKEN", "troque-este-token"),
		RealAutomation: parseBool(env("AUTOMACOES_REAIS", "false")),
		RealChat:       parseBool(env("ENVIAR_CHAT_REAL", "false")),
		RealPayment:    parseBool(env("GERAR_BOLETO_REAL", "false")),
	}

	return cfg
}

func dryRunHandler(cfg Config, jobName string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost && r.Method != http.MethodGet {
			writeJSON(w, http.StatusMethodNotAllowed, Response{
				OK:        false,
				Service:   "gerenciador-go-worker",
				Timestamp: time.Now().Format(time.RFC3339),
				Message:   "Método não permitido",
			})
			return
		}

		// Primeira fase: modo seguro. Não envia chat, não gera boleto e não altera dados reais.
		result := map[string]interface{}{
			"job":             jobName,
			"mode":            "dry-run",
			"project_root":    cfg.ProjectRoot,
			"data_dir":        cfg.DataDir,
			"data_exists":     dirExists(cfg.DataDir),
			"real_automation": cfg.RealAutomation,
			"real_chat":       cfg.RealChat,
			"real_payment":    cfg.RealPayment,
			"note":            "Estrutura inicial pronta. Esta rota ainda não executa ações reais.",
		}

		writeJSON(w, http.StatusOK, Response{
			OK:        true,
			Service:   "gerenciador-go-worker",
			Timestamp: time.Now().Format(time.RFC3339),
			Message:   "Worker Go respondeu com segurança",
			Data:      result,
		})
	}
}

func withAuth(cfg Config, next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		token := strings.TrimSpace(r.Header.Get("X-Go-Worker-Token"))
		if token == "" {
			token = strings.TrimSpace(r.URL.Query().Get("token"))
		}

		if cfg.InternalToken == "" || cfg.InternalToken == "troque-este-token" {
			writeJSON(w, http.StatusForbidden, Response{
				OK:        false,
				Service:   "gerenciador-go-worker",
				Timestamp: time.Now().Format(time.RFC3339),
				Message:   "Defina GO_WORKER_TOKEN antes de usar rotas internas.",
			})
			return
		}

		if token != cfg.InternalToken {
			writeJSON(w, http.StatusUnauthorized, Response{
				OK:        false,
				Service:   "gerenciador-go-worker",
				Timestamp: time.Now().Format(time.RFC3339),
				Message:   "Token interno inválido.",
			})
			return
		}

		next(w, r)
	}
}

func writeJSON(w http.ResponseWriter, status int, payload Response) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(status)
	if err := json.NewEncoder(w).Encode(payload); err != nil {
		fmt.Fprintln(w, `{"ok":false,"message":"erro ao gerar json"}`)
	}
}

func env(key, fallback string) string {
	value := strings.TrimSpace(os.Getenv(key))
	if value == "" {
		return fallback
	}
	return value
}

func parseBool(value string) bool {
	switch strings.ToLower(strings.TrimSpace(value)) {
	case "1", "true", "sim", "yes", "on":
		return true
	default:
		return false
	}
}

func dirExists(path string) bool {
	info, err := os.Stat(path)
	return err == nil && info.IsDir()
}
