package main

import (
	"crypto/subtle"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

// ---------- Giriş / Çıkış ----------

func handleAdminLogin(w http.ResponseWriter, r *http.Request) {
	if isAdmin(r) {
		http.Redirect(w, r, "/admin/panel", http.StatusFound)
		return
	}
	render(w, "admin_login", map[string]any{"Hata": r.URL.Query().Get("hata") == "1"})
}

func handleAdminLoginPost(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	s := store.Settings()
	user := strings.TrimSpace(r.FormValue("user"))
	pass := r.FormValue("pass")
	if subtle.ConstantTimeCompare([]byte(user), []byte(s.AdminUser)) != 1 ||
		subtle.ConstantTimeCompare([]byte(hashPass(s.AdminSalt, pass)), []byte(s.AdminHash)) != 1 {
		http.Redirect(w, r, "/admin/giris?hata=1", http.StatusFound)
		return
	}
	tok := newToken()
	sessMu.Lock()
	sessions[tok] = time.Now().Add(12 * time.Hour)
	sessMu.Unlock()
	http.SetCookie(w, &http.Cookie{
		Name: "akulu_admin", Value: tok, Path: "/",
		HttpOnly: true, SameSite: http.SameSiteLaxMode,
		Expires: time.Now().Add(12 * time.Hour),
	})
	http.Redirect(w, r, "/admin/panel", http.StatusFound)
}

func handleAdminLogout(w http.ResponseWriter, r *http.Request) {
	if c, err := r.Cookie("akulu_admin"); err == nil {
		sessMu.Lock()
		delete(sessions, c.Value)
		sessMu.Unlock()
	}
	http.SetCookie(w, &http.Cookie{Name: "akulu_admin", Value: "", Path: "/", MaxAge: -1})
	http.Redirect(w, r, "/admin/giris", http.StatusFound)
}

// ---------- Panel ----------

func handleAdminDashboard(w http.ResponseWriter, r *http.Request) {
	all := store.Orders()
	orders := all
	if len(orders) > 6 {
		orders = orders[:6]
	}
	// tahmini ciro: iptal olmayan siparişlerin ürün fiyat toplamı
	revenue := 0
	statusCounts := map[string]int{}
	for _, o := range all {
		statusCounts[o.Status]++
		if o.Status != "iptal" {
			if p := store.ProductByID(o.ProductID); p != nil {
				revenue += p.Price
			}
		}
	}
	// okunmamış son mesajlar
	var unreadMsgs []*Message
	for _, m := range store.Messages() {
		if !m.Read && len(unreadMsgs) < 4 {
			unreadMsgs = append(unreadMsgs, m)
		}
	}
	render(w, "admin_dashboard", map[string]any{
		"Title":         "Panel",
		"Active":        "panel",
		"NumProducts":   store.CountProducts(),
		"NumNewOrders":  store.CountOrders("yeni"),
		"NumOrders":     store.CountOrders(""),
		"NumUnread":     store.CountUnread(),
		"NumNoImage":    store.CountNoImage(),
		"NumOutOfStock": store.CountOutOfStock(),
		"Revenue":       revenue,
		"StatusCounts":  statusCounts,
		"LastOrders":    orders,
		"UnreadMsgs":    unreadMsgs,
	})
}

// ---------- Ürünler ----------

func handleAdminProducts(w http.ResponseWriter, r *http.Request) {
	qs := r.URL.Query()
	q := qs.Get("q")
	cat := qs.Get("kategori")
	filtre := qs.Get("filtre") // "", stokta, tukenen, gorselsiz, onecikan

	prods := store.Products(cat, q)
	if filtre != "" {
		var out []*Product
		for _, p := range prods {
			switch filtre {
			case "stokta":
				if !p.InStock {
					continue
				}
			case "tukenen":
				if p.InStock {
					continue
				}
			case "gorselsiz":
				if p.Image != "" && !strings.Contains(p.Image, "placeholder") {
					continue
				}
			case "onecikan":
				if !p.Featured {
					continue
				}
			}
			out = append(out, p)
		}
		prods = out
	}
	render(w, "admin_products", map[string]any{
		"Title": "Ürünler", "Active": "urunler",
		"Products": prods, "Categories": categories,
		"Query": q, "ActiveCat": cat, "Filtre": filtre,
		"Total": store.CountProducts(), "NumNoImage": store.CountNoImage(),
	})
}

func handleAdminProductToggleStock(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	if p := store.ProductByID(id); p != nil {
		p.InStock = !p.InStock
		store.Save()
	}
	http.Redirect(w, r, refererOr(r, "/admin/urunler"), http.StatusFound)
}

func handleAdminProductToggleFeatured(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	if p := store.ProductByID(id); p != nil {
		p.Featured = !p.Featured
		store.Save()
	}
	http.Redirect(w, r, refererOr(r, "/admin/urunler"), http.StatusFound)
}

// refererOr filtreli listeye geri döndürür.
func refererOr(r *http.Request, fallback string) string {
	ref := r.Header.Get("Referer")
	if ref != "" && strings.Contains(ref, "/admin/") {
		return ref
	}
	return fallback
}

func handleAdminProductNew(w http.ResponseWriter, r *http.Request) {
	render(w, "admin_product_edit", map[string]any{
		"Title": "Yeni Ürün", "Active": "urunler",
		"P": &Product{InStock: true}, "New": true, "Categories": categories,
	})
}

func handleAdminProductEdit(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	p := store.ProductByID(id)
	if p == nil {
		http.NotFound(w, r)
		return
	}
	render(w, "admin_product_edit", map[string]any{
		"Title": "Ürün Düzenle", "Active": "urunler",
		"P": p, "Categories": categories,
	})
}

func slugify(s string) string {
	repl := strings.NewReplacer("ç", "c", "ğ", "g", "ı", "i", "ö", "o", "ş", "s", "ü", "u",
		"Ç", "c", "Ğ", "g", "İ", "i", "I", "i", "Ö", "o", "Ş", "s", "Ü", "u")
	s = strings.ToLower(repl.Replace(s))
	var b strings.Builder
	prev := false
	for _, r := range s {
		if r >= 'a' && r <= 'z' || r >= '0' && r <= '9' {
			b.WriteRune(r)
			prev = false
		} else if !prev && b.Len() > 0 {
			b.WriteRune('-')
			prev = true
		}
	}
	return strings.Trim(b.String(), "-")
}

func handleAdminProductSave(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(20 << 20)

	var p *Product
	isNew := r.PathValue("id") == ""
	if isNew {
		p = &Product{ID: store.NextIDVal(), CreatedAt: time.Now()}
	} else {
		id, _ := strconv.Atoi(r.PathValue("id"))
		p = store.ProductByID(id)
		if p == nil {
			http.NotFound(w, r)
			return
		}
	}

	p.Name = strings.TrimSpace(r.FormValue("name"))
	p.Slug = slugify(p.Name)
	p.Category = r.FormValue("category")
	p.Brand = strings.TrimSpace(r.FormValue("brand"))
	p.Voltage = strings.TrimSpace(r.FormValue("voltage"))
	p.Price, _ = strconv.Atoi(strings.TrimSpace(r.FormValue("price")))
	p.OldPrice, _ = strconv.Atoi(strings.TrimSpace(r.FormValue("old_price")))
	p.Short = strings.TrimSpace(r.FormValue("short"))
	p.Desc = strings.TrimSpace(r.FormValue("desc"))
	p.Battery = strings.TrimSpace(r.FormValue("battery"))
	p.Motor = strings.TrimSpace(r.FormValue("motor"))
	p.Speed = strings.TrimSpace(r.FormValue("speed"))
	p.MaxLoad = strings.TrimSpace(r.FormValue("max_load"))
	p.Age = strings.TrimSpace(r.FormValue("age"))
	p.Remote = r.FormValue("remote") == "1"
	p.InStock = r.FormValue("in_stock") == "1"
	p.Featured = r.FormValue("featured") == "1"

	p.Features = nil
	for _, line := range strings.Split(r.FormValue("features"), "\n") {
		if line = strings.TrimSpace(line); line != "" {
			p.Features = append(p.Features, line)
		}
	}

	// görseli kaldır (yer tutucuya dön)
	if r.FormValue("remove_image") == "1" {
		p.Image = "/static/img/placeholder.svg"
	}
	// görsel yükleme
	if f, fh, err := r.FormFile("image"); err == nil {
		defer f.Close()
		ext := strings.ToLower(filepath.Ext(fh.Filename))
		if ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".webp" || ext == ".svg" || ext == ".gif" {
			name := "p" + strconv.Itoa(p.ID) + "-" + newToken()[:8] + ext
			dst, err := os.Create(filepath.Join(dataDir, "uploads", name))
			if err == nil {
				io.Copy(dst, f)
				dst.Close()
				p.Image = "/uploads/" + name
			}
		}
	}
	if p.Image == "" {
		p.Image = "/static/img/placeholder.svg"
	}

	if isNew {
		store.AddProduct(p)
	} else {
		store.Save()
	}
	http.Redirect(w, r, "/admin/urunler", http.StatusFound)
}

func handleAdminProductDelete(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	store.DeleteProduct(id)
	http.Redirect(w, r, "/admin/urunler", http.StatusFound)
}

// ---------- Siparişler ----------

func handleAdminOrders(w http.ResponseWriter, r *http.Request) {
	qs := r.URL.Query()
	durum := qs.Get("durum")
	q := strings.ToLower(strings.TrimSpace(qs.Get("q")))

	all := store.Orders()
	statusCounts := map[string]int{}
	for _, o := range all {
		statusCounts[o.Status]++
	}
	var orders []*Order
	for _, o := range all {
		if durum != "" && o.Status != durum {
			continue
		}
		if q != "" && !strings.Contains(strings.ToLower(o.Name+" "+o.Phone+" "+o.Code+" "+o.ProductName), q) {
			continue
		}
		orders = append(orders, o)
	}
	render(w, "admin_orders", map[string]any{
		"Title": "Siparişler", "Active": "siparisler",
		"Orders": orders, "Durum": durum, "Query": qs.Get("q"),
		"StatusCounts": statusCounts, "Total": len(all),
	})
}

func handleAdminOrderStatus(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	id, _ := strconv.Atoi(r.PathValue("id"))
	st := r.FormValue("status")
	if _, ok := statusNames[st]; ok {
		if o := store.OrderByID(id); o != nil {
			old := o.Status
			o.Status = st
			store.Save()
			if st == "iptal" {
				tgSecret(tgAdminAction("SİPARİŞ İPTAL EDİLDİ", o))
			} else if old != st {
				tgSecret(tgAdminAction("Durum değişti → "+statusNames[st], o))
			}
		}
	}
	http.Redirect(w, r, refererOr(r, "/admin/siparisler"), http.StatusFound)
}

func handleAdminOrderDelete(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	if o := store.OrderByID(id); o != nil {
		tgSecret(tgAdminAction("SİPARİŞ SİLİNDİ", o))
	}
	store.DeleteOrder(id)
	http.Redirect(w, r, refererOr(r, "/admin/siparisler"), http.StatusFound)
}

// ---------- Kampanya / İndirim ----------

func handleAdminCampaign(w http.ResponseWriter, r *http.Request) {
	render(w, "admin_kampanya", map[string]any{
		"Title": "Kampanya / İndirim", "Active": "kampanya",
		"Categories": categories, "Brands": store.Brands(),
		"NumDiscounted": store.CountDiscounted(), "Total": store.CountProducts(),
		"OK": r.URL.Query().Get("ok"), "N": r.URL.Query().Get("n"),
	})
}

func parseScope(r *http.Request) (string, string) {
	scope := r.FormValue("kapsam") // all | kategori:slug | marka:ad
	if strings.HasPrefix(scope, "kategori:") {
		return "kategori", strings.TrimPrefix(scope, "kategori:")
	}
	if strings.HasPrefix(scope, "marka:") {
		return "marka", strings.TrimPrefix(scope, "marka:")
	}
	return "all", ""
}

func handleAdminCampaignApply(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	pct, _ := strconv.Atoi(r.FormValue("yuzde"))
	scope, val := parseScope(r)
	n := store.ApplyDiscount(scope, val, pct)
	http.Redirect(w, r, "/admin/kampanya?ok=uygulandi&n="+strconv.Itoa(n), http.StatusFound)
}

func handleAdminCampaignRemove(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	scope, val := parseScope(r)
	n := store.RemoveDiscount(scope, val)
	http.Redirect(w, r, "/admin/kampanya?ok=kaldirildi&n="+strconv.Itoa(n), http.StatusFound)
}

// ---------- Mesajlar ----------

func handleAdminMessages(w http.ResponseWriter, r *http.Request) {
	render(w, "admin_messages", map[string]any{
		"Title": "Mesajlar", "Active": "mesajlar",
		"Messages": store.Messages(),
	})
}

func handleAdminMessageRead(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	store.MarkMessageRead(id)
	http.Redirect(w, r, "/admin/mesajlar", http.StatusFound)
}

func handleAdminMessageDelete(w http.ResponseWriter, r *http.Request) {
	id, _ := strconv.Atoi(r.PathValue("id"))
	store.DeleteMessage(id)
	http.Redirect(w, r, "/admin/mesajlar", http.StatusFound)
}

// ---------- Ayarlar ----------

func handleAdminSettings(w http.ResponseWriter, r *http.Request) {
	render(w, "admin_settings", map[string]any{
		"Title": "Ayarlar", "Active": "ayarlar",
		"OK": r.URL.Query().Get("ok"),
	})
}

func handleAdminSettingsGeneral(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	store.UpdateSettings(func(st *Settings) {
		st.SiteName = strings.TrimSpace(r.FormValue("site_name"))
		st.Tagline = strings.TrimSpace(r.FormValue("tagline"))
		st.About = strings.TrimSpace(r.FormValue("about"))
		st.Email = strings.TrimSpace(r.FormValue("email"))
		st.Address = strings.TrimSpace(r.FormValue("address"))
		st.WorkHours = strings.TrimSpace(r.FormValue("work_hours"))
		st.Instagram = strings.TrimSpace(r.FormValue("instagram"))
		st.OrderNote = strings.TrimSpace(r.FormValue("order_note"))
	})
	http.Redirect(w, r, "/admin/ayarlar?ok=genel", http.StatusFound)
}

func handleAdminToggleLock(w http.ResponseWriter, r *http.Request) {
	store.UpdateSettings(func(st *Settings) { st.StoreLocked = !st.StoreLocked })
	http.Redirect(w, r, refererOr(r, "/admin/panel"), http.StatusFound)
}

func handleAdminSettingsTelegram(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	store.UpdateSettings(func(st *Settings) {
		st.PanelTGToken = strings.TrimSpace(r.FormValue("panel_tg_token"))
		st.PanelTGChat = strings.TrimSpace(r.FormValue("panel_tg_chat"))
		st.PanelTGEnabled = r.FormValue("panel_tg_enabled") == "1"
	})
	http.Redirect(w, r, "/admin/ayarlar?ok=telegram#telegram", http.StatusFound)
}

func handleAdminTelegramTest(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	s := store.Settings()
	// formda değer varsa onu kullan (kaydetmeden test edilebilsin)
	token := strings.TrimSpace(r.FormValue("panel_tg_token"))
	if token == "" {
		token = strings.TrimSpace(s.PanelTGToken)
	}
	chat := strings.TrimSpace(r.FormValue("panel_tg_chat"))
	if chat == "" {
		chat = strings.TrimSpace(s.PanelTGChat)
	}
	res := "test-bos"
	if token != "" && chat != "" {
		if err := tgSend(token, chat, "✅ "+s.SiteName+" — panel bildirim testi başarılı."); err != nil {
			res = "test-hata"
		} else {
			res = "test-ok"
		}
	}
	http.Redirect(w, r, "/admin/ayarlar?ok="+res+"#telegram", http.StatusFound)
}

func handleAdminSettingsShowcase(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	store.UpdateSettings(func(st *Settings) {
		st.PromoTopbar = strings.TrimSpace(r.FormValue("promo_topbar"))
		st.HeroChip = strings.TrimSpace(r.FormValue("hero_chip"))
		st.HeroTitle = strings.TrimSpace(r.FormValue("hero_title"))
		st.HeroSub = strings.TrimSpace(r.FormValue("hero_sub"))
	})
	http.Redirect(w, r, "/admin/ayarlar?ok=vitrin", http.StatusFound)
}

func handleAdminSettingsPhones(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	labels := r.Form["phone_label"]
	numbers := r.Form["phone_number"]
	visibles := r.Form["phone_visible"]
	var phones []Phone
	for i := range numbers {
		num := strings.TrimSpace(numbers[i])
		if num == "" {
			continue
		}
		label := ""
		if i < len(labels) {
			label = strings.TrimSpace(labels[i])
		}
		vis := i < len(visibles) && visibles[i] == "1"
		phones = append(phones, Phone{Label: label, Number: num, Visible: vis})
	}
	store.UpdateSettings(func(st *Settings) {
		st.Phones = phones
		st.WhatsApp = strings.TrimSpace(r.FormValue("whatsapp"))
		st.WhatsAppVisible = r.FormValue("whatsapp_visible") == "1"
	})
	http.Redirect(w, r, "/admin/ayarlar?ok=telefon", http.StatusFound)
}

func handleAdminSettingsIBAN(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	banks := r.Form["iban_bank"]
	holders := r.Form["iban_holder"]
	numbers := r.Form["iban_number"]
	visibles := r.Form["iban_visible"]
	var ibans []IBAN
	for i := range numbers {
		num := strings.TrimSpace(numbers[i])
		if num == "" {
			continue
		}
		bank, holder := "", ""
		if i < len(banks) {
			bank = strings.TrimSpace(banks[i])
		}
		if i < len(holders) {
			holder = strings.TrimSpace(holders[i])
		}
		vis := i < len(visibles) && visibles[i] == "1"
		ibans = append(ibans, IBAN{Bank: bank, Holder: holder, Number: num, Visible: vis})
	}
	store.UpdateSettings(func(st *Settings) { st.IBANs = ibans })
	http.Redirect(w, r, "/admin/ayarlar?ok=iban", http.StatusFound)
}

func handleAdminSettingsPassword(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	s := store.Settings()
	old := r.FormValue("old_pass")
	newp := r.FormValue("new_pass")
	if hashPass(s.AdminSalt, old) != s.AdminHash || len(newp) < 6 {
		http.Redirect(w, r, "/admin/ayarlar?ok=sifrehata", http.StatusFound)
		return
	}
	salt := newToken()
	store.UpdateSettings(func(st *Settings) {
		if u := strings.TrimSpace(r.FormValue("admin_user")); u != "" {
			st.AdminUser = u
		}
		st.AdminSalt = salt
		st.AdminHash = hashPass(salt, newp)
	})
	http.Redirect(w, r, "/admin/ayarlar?ok=sifre", http.StatusFound)
}
