package main

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"html/template"
	"log"
	"math"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var (
	store   *Store
	tpl     map[string]*template.Template
	baseDir string
	dataDir string

	sessMu   sync.RWMutex
	sessions = map[string]time.Time{} // token -> son geçerlilik
)

// Kategoriler sabittir; admin ürün eklerken bunlardan seçer.
var categories = []struct{ Slug, Name string }{
	{"akulu-araba", "Akülü Arabalar"},
	{"akulu-jip", "Akülü Jipler"},
	{"akulu-motor", "Akülü Motorlar"},
	{"engelli-araci", "Engelli Araçları"},
}

func catName(slug string) string {
	for _, c := range categories {
		if c.Slug == slug {
			return c.Name
		}
	}
	return slug
}

func main() {
	baseDir = "."
	if _, err := os.Stat(filepath.Join(baseDir, "web", "templates", "base.html")); err != nil {
		exe, _ := os.Executable()
		baseDir = filepath.Dir(exe)
	}
	dataDir = filepath.Join(baseDir, "data")
	os.MkdirAll(filepath.Join(dataDir, "uploads"), 0755)

	var err error
	store, err = NewStore(filepath.Join(dataDir, "db.json"))
	if err != nil {
		log.Fatal(err)
	}
	seedIfEmpty()
	fillDefaults()
	parseTemplates()

	mux := http.NewServeMux()

	mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.Dir(filepath.Join(baseDir, "web", "static")))))
	mux.Handle("GET /uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir(filepath.Join(dataDir, "uploads")))))

	// genel sayfalar
	mux.HandleFunc("GET /{$}", handleHome)
	mux.HandleFunc("GET /urunler", handleProducts)
	mux.HandleFunc("GET /urun/{id}", handleProduct)
	mux.HandleFunc("GET /urun/{id}/{slug}", handleProduct)
	mux.HandleFunc("GET /satin-al", handleBuy)
	mux.HandleFunc("POST /satin-al", handleBuyPost)
	mux.HandleFunc("GET /hakkimizda", handleAbout)
	mux.HandleFunc("GET /iletisim", handleContact)
	mux.HandleFunc("POST /iletisim", handleContactPost)
	mux.HandleFunc("POST /odeme-bildir", handlePaymentClaim)

	// admin
	mux.HandleFunc("GET /admin", func(w http.ResponseWriter, r *http.Request) {
		if isAdmin(r) {
			http.Redirect(w, r, "/admin/panel", http.StatusFound)
		} else {
			http.Redirect(w, r, "/admin/giris", http.StatusFound)
		}
	})
	mux.HandleFunc("GET /admin/giris", handleAdminLogin)
	mux.HandleFunc("POST /admin/giris", handleAdminLoginPost)
	mux.HandleFunc("GET /admin/cikis", handleAdminLogout)

	mux.HandleFunc("GET /admin/panel", requireAdmin(handleAdminDashboard))
	mux.HandleFunc("GET /admin/urunler", requireAdmin(handleAdminProducts))
	mux.HandleFunc("GET /admin/urun/yeni", requireAdmin(handleAdminProductNew))
	mux.HandleFunc("POST /admin/urun/yeni", requireAdmin(handleAdminProductSave))
	mux.HandleFunc("GET /admin/urun/{id}", requireAdmin(handleAdminProductEdit))
	mux.HandleFunc("POST /admin/urun/{id}", requireAdmin(handleAdminProductSave))
	mux.HandleFunc("POST /admin/urun/{id}/sil", requireAdmin(handleAdminProductDelete))
	mux.HandleFunc("POST /admin/urun/{id}/stok", requireAdmin(handleAdminProductToggleStock))
	mux.HandleFunc("POST /admin/urun/{id}/onecikan", requireAdmin(handleAdminProductToggleFeatured))
	mux.HandleFunc("GET /admin/siparisler", requireAdmin(handleAdminOrders))
	mux.HandleFunc("POST /admin/siparis/{id}/durum", requireAdmin(handleAdminOrderStatus))
	mux.HandleFunc("POST /admin/siparis/{id}/sil", requireAdmin(handleAdminOrderDelete))
	mux.HandleFunc("GET /admin/mesajlar", requireAdmin(handleAdminMessages))
	mux.HandleFunc("POST /admin/mesaj/{id}/okundu", requireAdmin(handleAdminMessageRead))
	mux.HandleFunc("POST /admin/mesaj/{id}/sil", requireAdmin(handleAdminMessageDelete))
	mux.HandleFunc("GET /admin/kampanya", requireAdmin(handleAdminCampaign))
	mux.HandleFunc("POST /admin/kampanya/uygula", requireAdmin(handleAdminCampaignApply))
	mux.HandleFunc("POST /admin/kampanya/kaldir", requireAdmin(handleAdminCampaignRemove))
	mux.HandleFunc("POST /admin/kilit", requireAdmin(handleAdminToggleLock))
	mux.HandleFunc("GET /admin/ayarlar", requireAdmin(handleAdminSettings))
	mux.HandleFunc("POST /admin/ayarlar/genel", requireAdmin(handleAdminSettingsGeneral))
	mux.HandleFunc("POST /admin/ayarlar/vitrin", requireAdmin(handleAdminSettingsShowcase))
	mux.HandleFunc("POST /admin/ayarlar/telegram", requireAdmin(handleAdminSettingsTelegram))
	mux.HandleFunc("POST /admin/ayarlar/telegram/test", requireAdmin(handleAdminTelegramTest))
	mux.HandleFunc("POST /admin/ayarlar/telefonlar", requireAdmin(handleAdminSettingsPhones))
	mux.HandleFunc("POST /admin/ayarlar/iban", requireAdmin(handleAdminSettingsIBAN))
	mux.HandleFunc("POST /admin/ayarlar/sifre", requireAdmin(handleAdminSettingsPassword))

	port := os.Getenv("PORT")
	if port == "" {
		port = "8095"
	}
	log.Println("akulu ->  http://localhost:" + port)
	log.Fatal(http.ListenAndServe(":"+port, mux))
}

// fillDefaults eski kurulumlarda yeni eklenen ayar alanlarını doldurur.
func fillDefaults() {
	s := store.Settings()
	if s.HeroTitle != "" {
		return
	}
	store.UpdateSettings(func(st *Settings) {
		st.PromoTopbar = "Türkiye geneli <strong>ÜCRETSİZ KARGO</strong>"
		st.HeroChip = "Sezon Kampanyası"
		st.HeroTitle = "Akülü araçlarda <em>ücretsiz kargo</em> + 2 yıl garanti"
		st.HeroSub = "CE sertifikalı akülü arabalar, jipler, motosikletler ve engelli araçları — havale/EFT ile güvenli ödeme, 24 saatte kargoda."
	})
}

// ---------- Şablonlar ----------

func telHref(s string) string {
	var b strings.Builder
	for _, r := range s {
		if r >= '0' && r <= '9' || r == '+' {
			b.WriteRune(r)
		}
	}
	n := b.String()
	if strings.HasPrefix(n, "0") {
		n = "+90" + n[1:]
	}
	return "tel:" + n
}

func waHref(s string) string {
	var b strings.Builder
	for _, r := range s {
		if r >= '0' && r <= '9' {
			b.WriteRune(r)
		}
	}
	n := b.String()
	if strings.HasPrefix(n, "0") {
		n = "90" + n[1:]
	}
	return "https://wa.me/" + n
}

func money(n int) string {
	s := fmt.Sprintf("%d", n)
	var out []byte
	for i, c := range []byte(s) {
		if i > 0 && (len(s)-i)%3 == 0 {
			out = append(out, '.')
		}
		out = append(out, c)
	}
	return string(out)
}

var statusNames = map[string]string{
	"yeni": "Yeni", "onaylandi": "Onaylandı", "kargoda": "Kargoda",
	"tamamlandi": "Tamamlandı", "iptal": "İptal",
}

func parseTemplates() {
	funcs := template.FuncMap{
		"money":   money,
		"discount": func(old, cur int) int {
			if old <= cur || old == 0 {
				return 0
			}
			return int(math.Round(float64(old-cur) * 100 / float64(old)))
		},
		"tel": func(s string) template.URL { return template.URL(telHref(s)) },
		"wa":      waHref,
		"cat":     catName,
		"year":    func() int { return time.Now().Year() },
		"status":  func(s string) string { if n, ok := statusNames[s]; ok { return n }; return s },
		"nl2br":   func(s string) template.HTML { return template.HTML(strings.ReplaceAll(template.HTMLEscapeString(s), "\n", "<br>")) },
		"dt":      func(t time.Time) string { return t.Format("02.01.2006 15:04") },
		"safe":    func(s string) template.HTML { return template.HTML(s) },
		"brandParts": func(name string) [2]string {
			for _, suf := range []string{"Akü", "AKÜ", "akü"} {
				if strings.HasSuffix(name, suf) && len(name) > len(suf) {
					return [2]string{strings.TrimSuffix(name, suf), suf}
				}
			}
			return [2]string{name, ""}
		},
	}

	pages := map[string]struct{ base, file string }{
		"home":               {"base.html", "home.html"},
		"products":           {"base.html", "products.html"},
		"product":            {"base.html", "product.html"},
		"buy":                {"base.html", "buy.html"},
		"buy_ok":             {"base.html", "buy_ok.html"},
		"about":              {"base.html", "about.html"},
		"contact":            {"base.html", "contact.html"},
		"admin_login":        {"", "admin_login.html"},
		"admin_dashboard":    {"admin_base.html", "admin_dashboard.html"},
		"admin_products":     {"admin_base.html", "admin_products.html"},
		"admin_product_edit": {"admin_base.html", "admin_product_edit.html"},
		"admin_orders":       {"admin_base.html", "admin_orders.html"},
		"admin_kampanya":     {"admin_base.html", "admin_kampanya.html"},
		"admin_messages":     {"admin_base.html", "admin_messages.html"},
		"admin_settings":     {"admin_base.html", "admin_settings.html"},
	}

	tdir := filepath.Join(baseDir, "web", "templates")
	tpl = map[string]*template.Template{}
	for name, p := range pages {
		files := []string{filepath.Join(tdir, p.file)}
		if p.base != "" {
			files = append([]string{filepath.Join(tdir, p.base)}, files...)
		}
		tpl[name] = template.Must(template.New(filepath.Base(files[0])).Funcs(funcs).ParseFiles(files...))
	}
}

func render(w http.ResponseWriter, name string, data map[string]any) {
	if data == nil {
		data = map[string]any{}
	}
	data["S"] = store.Settings()
	if _, ok := data["Query"]; !ok {
		data["Query"] = ""
	}
	t, ok := tpl[name]
	if !ok {
		http.Error(w, "şablon yok: "+name, 500)
		return
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := t.Execute(w, data); err != nil {
		log.Println("render:", name, err)
	}
}

// ---------- Oturum ----------

func newToken() string {
	b := make([]byte, 24)
	rand.Read(b)
	return hex.EncodeToString(b)
}

func hashPass(salt, pass string) string {
	h := sha256.Sum256([]byte(salt + ":" + pass))
	return hex.EncodeToString(h[:])
}

func isAdmin(r *http.Request) bool {
	c, err := r.Cookie("akulu_admin")
	if err != nil {
		return false
	}
	sessMu.RLock()
	exp, ok := sessions[c.Value]
	sessMu.RUnlock()
	return ok && exp.After(time.Now())
}

func requireAdmin(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if !isAdmin(r) {
			http.Redirect(w, r, "/admin/giris", http.StatusFound)
			return
		}
		next(w, r)
	}
}
