package log

import (
	"fmt"
	"os"
	"sync"
	"time"
)

type Visual struct {
	mu sync.Mutex
}

var Padrao = &Visual{}

func (l *Visual) Linha(msg string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	ts := time.Now().Format("15:04:05")
	_, _ = fmt.Fprintf(os.Stdout, "[%s] %s\n", ts, msg)
}

func (l *Visual) InicioExecucao(id string, totalFeeds, workers int, turbo, forcar bool, fuso string) {
	mode := "normal"
	if turbo {
		mode = "turbo"
	}
	politica := "incremental (1x/dia por feed)"
	if forcar {
		politica = "forçada (todos os feeds)"
	}
	l.Linha(fmt.Sprintf("▶ EXECUÇÃO #%s — %d feeds · %d workers · %s · %s · fuso %s", id, totalFeeds, workers, mode, politica, fuso))
}

func (l *Visual) Apagados(n int, dir string) {
	l.Linha(fmt.Sprintf("🗑 Apagados %d arquivos em %s/", n, dir))
}

func (l *Visual) FeedInicio(idx, total, idConfig int, hash, portal string, idMaster int) {
	h := hash
	if len(h) > 12 {
		h = h[:12] + "..."
	}
	l.Linha(fmt.Sprintf("▶ Feed %d/%d · id=%d · hash=%s · %s · master %d", idx, total, idConfig, h, portal, idMaster))
}

func (l *Visual) ImoveisProgresso(idConfig, feito, total int, detalhe string) {
	l.Linha(fmt.Sprintf("   #%d · imóveis %d/%d · %s", idConfig, feito, total, detalhe))
}

func (l *Visual) FeedOK(idConfig int, hash string, tamanhoMB float64, url string) {
	l.Linha(fmt.Sprintf("   #%d · gravado %.2f MB · %s/%s.xml", idConfig, tamanhoMB, url, hash))
}

func (l *Visual) FeedIgnorado(idx, total, idConfig int, hash, motivo string) {
	h := hash
	if len(h) > 12 {
		h = h[:12] + "..."
	}
	l.Linha(fmt.Sprintf("⊘ Feed %d/%d · id=%d · hash=%s · ignorado (%s)", idx, total, idConfig, h, motivo))
}

func (l *Visual) FeedErro(idx, total, idConfig int, err error) {
	l.Linha(fmt.Sprintf("✗ Feed %d/%d · id=%d · ERRO: %v", idx, total, idConfig, err))
}

func (l *Visual) ReconexaoMySQL() {
	l.Linha("↻ reconectado MySQL")
}

func (l *Visual) OrfaosRemovidos(n int, dir string) {
	l.Linha(fmt.Sprintf("🧹 Removidos %d XML órfãos em %s/ (sem feed ativo no banco)", n, dir))
}

func (l *Visual) Fim(gerados, erros, ignorados, orfaos int, duracao time.Duration) {
	msg := fmt.Sprintf("■ FIM — gerados: %d · erros: %d · ignorados: %d", gerados, erros, ignorados)
	if orfaos > 0 {
		msg += fmt.Sprintf(" · órfãos removidos: %d", orfaos)
	}
	msg += " · " + duracao.Round(time.Second).String()
	l.Linha(msg)
}
