package controllers

import (
	dbConfig "ares/database/config"
	"ares/database/models"
	utils "ares/pkg/utis"
	"ares/services"
	"math"
	"strconv"

	"github.com/gofiber/fiber/v3"
)

// AdminContentProducts renders the products partial
func AdminContentProducts(c fiber.Ctx) error {
	page, _ := strconv.Atoi(c.Query("page", "1"))
	limit := 20
	offset := (page - 1) * limit
	search := c.Query("search", "")
	showDeleted := c.Query("deleted") == "true"

	var products []models.Product
	var total int64

	query := dbConfig.DB.Model(&models.Product{})
	if showDeleted {
		query = query.Unscoped().Where("deleted_at IS NOT NULL")
	}
	if search != "" {
		query = query.Where("title LIKE ? OR slug LIKE ?", "%"+search+"%", "%"+search+"%")
	}
	query.Count(&total)
	query.Preload("Categories").Preload("Tags").Order("created_at desc").Limit(limit).Offset(offset).Find(&products)

	imageMap := make(map[uint]string)
	for _, p := range products {
		if p.Images != "" {
			imgs := parseImagesField(p.Images)
			if len(imgs) > 0 {
				imageMap[p.ID] = imgs[0]
			}
		}
	}

	totalPages := int(math.Ceil(float64(total) / float64(limit)))

	data := fiber.Map{
		"Products":    products,
		"ImageMap":    imageMap,
		"Page":        page,
		"TotalPages":  totalPages,
		"NextPage":    page + 1,
		"PrevPage":    page - 1,
		"Search":      search,
		"ShowDeleted": showDeleted,
	}

	if c.Get("HX-Request") == "true" {
		return c.Render("admin/partials/products", data)
	}
	return c.Render("admin/partials/products", data, "admin/layout")
}

// AdminProductNew renders create form
func AdminProductNew(c fiber.Ctx) error {
	var cats []models.ProductCategory
	var tags []models.ProductTag
	dbConfig.DB.Order("title asc").Find(&cats)
	dbConfig.DB.Order("name asc").Find(&tags)
	return c.Render("admin/pages/product_form", fiber.Map{"IsEdit": false, "Categories": cats, "Tags": tags, "FirstImage": ""}, "admin/layout")
}

// AdminProductCreate handles creation
func AdminProductCreate(c fiber.Ctx) error {
	title := c.FormValue("title")
	if title == "" {
		return c.Redirect().To("/admin/content/products?error=Başlık+gerekli")
	}
	product := models.Product{Title: title}
	product.Content = c.FormValue("content")

	// Slug handling
	rawSlug := c.FormValue("slug")
	if rawSlug == "" {
		rawSlug = utils.Slugify(product.Title)
	} else {
		rawSlug = utils.Slugify(rawSlug)
	}
	attempt := rawSlug
	i := 1
	for {
		var existing models.Product
		err := dbConfig.DB.Unscoped().Where("slug = ?", attempt).First(&existing).Error
		if err != nil {
			break
		}
		attempt = rawSlug + "-" + strconv.Itoa(i)
		i++
	}
	product.Slug = attempt

	// Image Upload
	priceStr := c.FormValue("price")
	price, _ := strconv.ParseFloat(priceStr, 64)
	width, _ := strconv.Atoi(c.FormValue("width"))
	height, _ := strconv.Atoi(c.FormValue("height"))
	quality, _ := strconv.Atoi(c.FormValue("quality"))
	format := c.FormValue("format")
	if format == "" {
		format = "avif"
	}
	// DB fields
	product.Price = price
	product.Format = format
	product.Width = width
	product.Height = height
	product.Quality = quality

	// Use processAndSaveImage for main product image (for simplicity we store 1 image mapped as JSON array or just single string per parseImagesField)
	imagePath, err := services.ProcessAndSaveImage(c, "image", services.ImageOptions{
		Width:   width,
		Height:  height,
		Quality: quality,
		Format:  format,
		Folder:  "products",
	})
	if err == nil && imagePath != "" {
		// Tek resim olarak string kaydet
		product.Images = imagePath
	}

	if err := dbConfig.DB.Create(&product).Error; err != nil {
		return c.Redirect().To("/admin/content/products?error=Oluşturma+başarısız")
	}

	// Handline Relations (Categories & Tags)
	form, err := c.MultipartForm()

	if err == nil && form != nil {
		catIDs := form.Value["categories"]
		for _, catIDStr := range catIDs {
			catID, _ := strconv.Atoi(catIDStr)
			if catID > 0 {
				var cat models.ProductCategory
				if err := dbConfig.DB.First(&cat, catID).Error; err == nil {
					dbConfig.DB.Model(&product).Association("Categories").Append(&cat)
				}
			}
		}

		tagIDs := form.Value["tags"]
		for _, tagIDStr := range tagIDs {
			tagID, _ := strconv.Atoi(tagIDStr)
			if tagID > 0 {
				var tag models.ProductTag
				if err := dbConfig.DB.First(&tag, tagID).Error; err == nil {
					dbConfig.DB.Model(&product).Association("Tags").Append(&tag)
				}
			}
		}
	} else {
		// if form data is not multipart, try basic FormValue array
		// Though Fiber usually parses multiple values when we get them explicitly or we can just parse the body
	}

	return c.Redirect().To("/admin/content/products?success=Ürün+oluşturuldu")
}

// AdminProductEdit renders the edit hero form
func AdminProductEdit(c fiber.Ctx) error {
	id := c.Params("id")
	var product models.Product
	if err := dbConfig.DB.Preload("Categories").Preload("Tags").First(&product, id).Error; err != nil {
		return c.Status(fiber.StatusNotFound).SendString("Ürün bulunamadı")
	}

	var cats []models.ProductCategory
	var tags []models.ProductTag
	dbConfig.DB.Order("title asc").Find(&cats)
	dbConfig.DB.Order("name asc").Find(&tags)

	firstImage := ""
	if product.Images != "" {
		imgs := parseImagesField(product.Images)
		if len(imgs) > 0 {
			firstImage = imgs[0]
		}
	}

	return c.Render("admin/pages/product_form", fiber.Map{
		"IsEdit":     true,
		"Product":    product,
		"Categories": cats,
		"Tags":       tags,
		"FirstImage": firstImage,
	}, "admin/layout")
}

// AdminProductUpdate handles product update
func AdminProductUpdate(c fiber.Ctx) error {
	id := c.Params("id")
	var product models.Product
	if err := dbConfig.DB.First(&product, id).Error; err != nil {
		return c.Redirect().To("/admin/content/products?error=Ürün+bulunamadı")
	}

	product.Title = c.FormValue("title")
	product.Content = c.FormValue("content")

	// Slug update
	rawSlug := c.FormValue("slug")
	if rawSlug != "" && rawSlug != product.Slug {
		rawSlug = utils.Slugify(rawSlug)
		attempt := rawSlug
		i := 1
		for {
			var existing models.Product
			err := dbConfig.DB.Unscoped().Where("slug = ? AND id != ?", attempt, product.ID).First(&existing).Error
			if err != nil {
				break
			}
			attempt = rawSlug + "-" + strconv.Itoa(i)
			i++
		}
		product.Slug = attempt
	}

	// Image Upload
	priceStr := c.FormValue("price")
	price, _ := strconv.ParseFloat(priceStr, 64)
	width, _ := strconv.Atoi(c.FormValue("width"))
	height, _ := strconv.Atoi(c.FormValue("height"))
	quality, _ := strconv.Atoi(c.FormValue("quality"))
	format := c.FormValue("format")
	if format == "" {
		format = "avif"
	}
	// DB fields
	product.Price = price
	product.Format = format
	product.Width = width
	product.Height = height
	product.Quality = quality

	imagePath, err := services.ProcessAndSaveImage(c, "image", services.ImageOptions{
		Width:   width,
		Height:  height,
		Quality: quality,
		Format:  format,
		Folder:  "products",
	})
	if err == nil && imagePath != "" {
		product.Images = imagePath
	}

	if err := dbConfig.DB.Save(&product).Error; err != nil {
		return c.Redirect().To("/admin/content/products?error=Güncelleme+başarısız")
	}

	// Handline Relations (Categories & Tags)
	dbConfig.DB.Model(&product).Association("Categories").Clear()
	dbConfig.DB.Model(&product).Association("Tags").Clear()

	form, err := c.MultipartForm()

	if err == nil && form != nil {
		catIDs := form.Value["categories"]
		for _, catIDStr := range catIDs {
			catID, _ := strconv.Atoi(catIDStr)
			if catID > 0 {
				var cat models.ProductCategory
				if err := dbConfig.DB.First(&cat, catID).Error; err == nil {
					dbConfig.DB.Model(&product).Association("Categories").Append(&cat)
				}
			}
		}

		tagIDs := form.Value["tags"]
		for _, tagIDStr := range tagIDs {
			tagID, _ := strconv.Atoi(tagIDStr)
			if tagID > 0 {
				var tag models.ProductTag
				if err := dbConfig.DB.First(&tag, tagID).Error; err == nil {
					dbConfig.DB.Model(&product).Association("Tags").Append(&tag)
				}
			}
		}
	}

	return c.Redirect().To("/admin/content/products?success=Ürün+güncellendi")
}

// AdminProductDelete handles soft delete
func AdminProductDelete(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Delete(&models.Product{}, id).Error; err != nil {
		return c.Redirect().To("/admin/content/products?error=Silme+hatası")
	}
	return c.Redirect().To("/admin/content/products?success=Ürün+silindi")
}

// AdminProductRestore handles restore
func AdminProductRestore(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Unscoped().Model(&models.Product{}).Where("id = ?", id).Update("deleted_at", nil).Error; err != nil {
		return c.Redirect().To("/admin/content/products?error=Geri+yükleme+hatası")
	}
	return c.Redirect().To("/admin/content/products?deleted=true&success=Ürün+geri+yüklendi")
}

// --- ProductCategory Management ---

func AdminContentProductCategories(c fiber.Ctx) error {
	var categories []models.ProductCategory
	showDeleted := c.Query("deleted") == "true"
	query := dbConfig.DB.Model(&models.ProductCategory{})
	if showDeleted {
		query = query.Unscoped().Where("deleted_at IS NOT NULL")
	}
	query.Preload("Parent").Order("title asc").Find(&categories)

	data := fiber.Map{
		"Categories":  categories,
		"ShowDeleted": showDeleted,
	}

	if c.Get("HX-Request") == "true" {
		return c.Render("admin/partials/product_categories", data)
	}
	return c.Render("admin/partials/product_categories", data, "admin/layout")
}

func AdminProductCategoryNew(c fiber.Ctx) error {
	var parents []models.ProductCategory
	dbConfig.DB.Order("title asc").Find(&parents)
	return c.Render("admin/pages/product_category_form", fiber.Map{
		"IsEdit":  false,
		"Parents": parents,
	}, "admin/layout")
}

func AdminProductCategoryCreate(c fiber.Ctx) error {
	cat := new(models.ProductCategory)
	if err := c.Bind().Body(cat); err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Geçersiz+istek")
	}

	if cat.Title == "" {
		return c.Redirect().To("/admin/content/product-categories?error=Başlık+zorunlu")
	}

	rawSlug := c.FormValue("slug")
	if rawSlug == "" {
		rawSlug = utils.Slugify(cat.Title)
	} else {
		rawSlug = utils.Slugify(rawSlug)
	}

	attempt := rawSlug
	i := 1
	for {
		var existing models.ProductCategory
		err := dbConfig.DB.Unscoped().Where("slug = ?", attempt).First(&existing).Error
		if err != nil {
			break
		}
		attempt = rawSlug + "-" + strconv.Itoa(i)
		i++
	}
	cat.Slug = attempt

	// Handle ParentID
	parentIDStr := c.FormValue("parent_id")
	if parentIDStr != "" {
		if pid, err := strconv.ParseUint(parentIDStr, 10, 32); err == nil && pid > 0 {
			pidUint := uint(pid)
			cat.ParentID = &pidUint
		}
	} else {
		cat.ParentID = nil
	}

	if err := dbConfig.DB.Create(cat).Error; err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Oluşturma+başarısız")
	}
	return c.Redirect().To("/admin/content/product-categories?success=Kategori+oluşturuldu")
}

func AdminProductCategoryEdit(c fiber.Ctx) error {
	id := c.Params("id")
	var cat models.ProductCategory
	if err := dbConfig.DB.First(&cat, id).Error; err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Kategori+bulunamadı")
	}

	var parents []models.ProductCategory
	dbConfig.DB.Where("id != ?", id).Order("title asc").Find(&parents)

	return c.Render("admin/pages/product_category_form", fiber.Map{
		"IsEdit":   true,
		"Category": cat,
		"Parents":  parents,
	}, "admin/layout")
}

func AdminProductCategoryUpdate(c fiber.Ctx) error {
	id := c.Params("id")
	var cat models.ProductCategory
	if err := dbConfig.DB.First(&cat, id).Error; err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Kategori+bulunamadı")
	}

	cat.Title = c.FormValue("title")
	cat.Description = c.FormValue("description")
	cat.Keywords = c.FormValue("keywords")

	rawSlug := c.FormValue("slug")
	if rawSlug != "" && rawSlug != cat.Slug {
		rawSlug = utils.Slugify(rawSlug)
		attempt := rawSlug
		i := 1
		for {
			var existing models.ProductCategory
			err := dbConfig.DB.Unscoped().Where("slug = ? AND id != ?", attempt, cat.ID).First(&existing).Error
			if err != nil {
				break
			}
			attempt = rawSlug + "-" + strconv.Itoa(i)
			i++
		}
		cat.Slug = attempt
	}

	parentIDStr := c.FormValue("parent_id")
	if parentIDStr != "" {
		if pid, err := strconv.ParseUint(parentIDStr, 10, 32); err == nil && pid > 0 {
			pidUint := uint(pid)
			if pidUint != cat.ID {
				cat.ParentID = &pidUint
			}
		}
	} else {
		cat.ParentID = nil
	}

	if err := dbConfig.DB.Save(&cat).Error; err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Güncelleme+başarısız")
	}
	return c.Redirect().To("/admin/content/product-categories?success=Kategori+güncellendi")
}

func AdminProductCategoryDelete(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Delete(&models.ProductCategory{}, id).Error; err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Silme+başarısız")
	}
	return c.Redirect().To("/admin/content/product-categories?success=Kategori+silindi")
}

func AdminProductCategoryRestore(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Unscoped().Model(&models.ProductCategory{}).Where("id = ?", id).Update("deleted_at", nil).Error; err != nil {
		return c.Redirect().To("/admin/content/product-categories?error=Geri+yükleme+başarısız")
	}
	return c.Redirect().To("/admin/content/product-categories?deleted=true&success=Kategori+geri+yüklendi")
}

// --- ProductTag Management ---

func AdminContentProductTags(c fiber.Ctx) error {
	var tags []models.ProductTag
	showDeleted := c.Query("deleted") == "true"
	query := dbConfig.DB.Model(&models.ProductTag{})
	if showDeleted {
		query = query.Unscoped().Where("deleted_at IS NOT NULL")
	}
	query.Order("name asc").Find(&tags)

	data := fiber.Map{
		"Tags":        tags,
		"ShowDeleted": showDeleted,
	}

	if c.Get("HX-Request") == "true" {
		return c.Render("admin/partials/product_tags", data)
	}
	return c.Render("admin/partials/product_tags", data, "admin/layout")
}

func AdminProductTagNew(c fiber.Ctx) error {
	return c.Render("admin/pages/product_tag_form", fiber.Map{
		"IsEdit": false,
	}, "admin/layout")
}

func AdminProductTagCreate(c fiber.Ctx) error {
	tag := new(models.ProductTag)
	if err := c.Bind().Body(tag); err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Geçersiz+istek")
	}
	if tag.Name == "" {
		return c.Redirect().To("/admin/content/product-tags?error=İsim+zorunlu")
	}
	if err := dbConfig.DB.Create(tag).Error; err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Oluşturma+başarısız")
	}
	return c.Redirect().To("/admin/content/product-tags?success=Etiket+oluşturuldu")
}

func AdminProductTagEdit(c fiber.Ctx) error {
	id := c.Params("id")
	var tag models.ProductTag
	if err := dbConfig.DB.First(&tag, id).Error; err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Etiket+bulunamadı")
	}
	return c.Render("admin/pages/product_tag_form", fiber.Map{
		"IsEdit": true,
		"Tag":    tag,
	}, "admin/layout")
}

func AdminProductTagUpdate(c fiber.Ctx) error {
	id := c.Params("id")
	var tag models.ProductTag
	if err := dbConfig.DB.First(&tag, id).Error; err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Etiket+bulunamadı")
	}

	tag.Name = c.FormValue("name")

	if err := dbConfig.DB.Save(&tag).Error; err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Güncelleme+başarısız")
	}
	return c.Redirect().To("/admin/content/product-tags?success=Etiket+güncellendi")
}

func AdminProductTagDelete(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Delete(&models.ProductTag{}, id).Error; err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Silme+başarısız")
	}
	return c.Redirect().To("/admin/content/product-tags?success=Etiket+silindi")
}

func AdminProductTagRestore(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Unscoped().Model(&models.ProductTag{}).Where("id = ?", id).Update("deleted_at", nil).Error; err != nil {
		return c.Redirect().To("/admin/content/product-tags?error=Geri+yükleme+başarısız")
	}
	return c.Redirect().To("/admin/content/product-tags?deleted=true&success=Etiket+geri+yüklendi")
}

// AdminContentProductComments handles rendering the Product Comments list in the admin panel
func AdminContentProductComments(c fiber.Ctx) error {
	var comments []models.ProductComment

	// Preload the User and Product for display (Wait, user and product relationships are missing in model temporarily)
	// We'll just list them out manually
	query := dbConfig.DB.Model(&models.ProductComment{})

	// Optional filtering by specific product via query string
	productID := c.Query("product_id")
	if productID != "" {
		if pid, err := strconv.Atoi(productID); err == nil {
			query = query.Where("product_id = ?", pid)
		}
	}

	query.Order("created_at desc").Find(&comments)

	data := fiber.Map{
		"ProductComments": comments,
		"ProductID":       productID,
	}

	if c.Get("HX-Request") == "true" {
		return c.Render("admin/partials/product_comments", data)
	}

	return c.Render("admin/partials/product_comments", data, "admin/layout")
}

// AdminProductCommentDelete handles hard deleting a product comment
func AdminProductCommentDelete(c fiber.Ctx) error {
	id := c.Params("id")
	if err := dbConfig.DB.Unscoped().Where("id = ?", id).Delete(&models.ProductComment{}).Error; err != nil {
		return c.Redirect().To("/admin/content/product-comments?error=Yorum+silinemedi")
	}

	return c.Redirect().To("/admin/content/product-comments?deleted=true&success=Yorum+silindi")
}

// AdminContentProductCategoryViews handles rendering the Product Category Views list
func AdminContentProductCategoryViews(c fiber.Ctx) error {
	var views []models.ProductCategoryView

	query := dbConfig.DB.Model(&models.ProductCategoryView{})

	// Filter by Category ID
	categoryID := c.Query("category_id")
	if categoryID != "" {
		if cid, err := strconv.Atoi(categoryID); err == nil {
			query = query.Where("category_id = ?", cid)
		}
	}

	query.Order("created_at desc").Find(&views)

	data := fiber.Map{
		"Views":      views,
		"CategoryID": categoryID,
	}

	if c.Get("HX-Request") == "true" {
		return c.Render("admin/partials/product_category_views", data)
	}

	return c.Render("admin/partials/product_category_views", data, "admin/layout")
}
