package controllers

import (
	configs "ares/config"
	database "ares/database/config"
	"ares/database/models"
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"

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

// GetHero godoc
// @Summary Get active hero/banner
// @Tags Hero
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Failure 404 {object} map[string]string
// @Router /api/v1/hero [get]
func GetHero(c fiber.Ctx) error {
	var heroes []models.Hero
	// Aktif olan tüm hero'ları getir
	if err := database.DB.Where("is_active = ?", true).Find(&heroes).Error; err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "database error"})
	}
	if len(heroes) == 0 {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "no active hero found"})
	}
	return c.JSON(heroes)
}

// GetHeroAll godoc
// @Summary Get all heroes
// @Description Returns all hero/banner records (no filter)
// @Tags Hero
// @Produce json
// @Success 200 {array} map[string]interface{}
// @Failure 404 {object} map[string]string
// @Router /api/v1/heroes [get]
func GetHeroAll(c fiber.Ctx) error {
	var heroes []models.Hero
	// Tüm hero'ları getir (filtre yok)
	if err := database.DB.Find(&heroes).Error; err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "database error"})
	}
	if len(heroes) == 0 {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "no hero found"})
	}
	return c.JSON(heroes)
}

func CreateHero(c fiber.Ctx) error {
	var hero models.Hero
	if err := c.Bind().Body(&hero); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
	}

	// Image upload
	file, err := c.FormFile("image")
	if err == nil {
		if _, err := os.Stat("./uploads/heroes"); os.IsNotExist(err) {
			os.MkdirAll("./uploads/heroes", 0755)
		}
		filename := fmt.Sprintf("%d_%s", time.Now().Unix(), file.Filename)
		filePath := filepath.Join("./uploads/heroes", filename)
		if err := c.SaveFile(file, filePath); err != nil {
			return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "failed to save image"})
		}
		hero.Image = "/uploads/heroes/" + filename
	}

	// Eğer sadece bir aktif hero olacaksa, diğerlerini pasife çekebiliriz
	//if hero.IsActive {
	//	database.DB.Model(&models.Hero{}).Where("is_active = ?", true).Update("is_active", false)
	//}

	if err := database.DB.Create(&hero).Error; err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "hero could not be created"})
	}

	return c.Status(http.StatusCreated).JSON(hero)
}

func UpdateHero(c fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid id"})
	}

	var hero models.Hero
	if err := database.DB.First(&hero, id).Error; err != nil {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "hero not found"})
	}

	// Log raw request body (works for JSON). For multipart/form-data, also log form values.
	//log.Printf("Raw request body: %s\n", string(c.Body()))
	//log.Printf("Form title: %s, is_active: %s\n", c.FormValue("title"), c.FormValue("is_active"))

	var updateData models.Hero
	if err := c.Bind().Body(&updateData); err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
	}
	//log.Printf("Received update data: %+v\n", updateData) // Debug log
	// Image upload
	file, err := c.FormFile("image")
	if err == nil {
		if _, err := os.Stat("./uploads/heroes"); os.IsNotExist(err) {
			os.MkdirAll("./uploads/heroes", 0755)
		}
		filename := fmt.Sprintf("%d_%s", time.Now().Unix(), file.Filename)
		filePath := filepath.Join("./uploads/heroes", filename)
		if err := c.SaveFile(file, filePath); err != nil {
			return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "failed to save image"})
		}
		updateData.Image = "/uploads/heroes/" + filename
	}

	// Eğer bu hero aktif yapılıyorsa diğerlerini pasife çek
	//if updateData.IsActive {
	//	database.DB.Model(&models.Hero{}).Where("id != ?", id).Where("is_active = ?", true).Update("is_active", false)
	//}

	// Handle is_active coming from multipart/form-data: parse and update explicitly
	if v := c.FormValue("is_active"); v != "" {
		if parsed, err := strconv.ParseBool(v); err == nil {
			// Ensure boolean field is updated even if it's false (zero value)
			if err := database.DB.Model(&hero).Update("is_active", parsed).Error; err != nil {
				return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "hero could not be updated"})
			}
			// reflect into updateData for consistency
			updateData.IsActive = parsed
		} else {
			configs.Logger.Sugar().Warnf("invalid is_active value: %s", v)
		}
	}

	if err := database.DB.Model(&hero).Updates(updateData).Error; err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "hero could not be updated"})
	}

	return c.JSON(hero)
}

func DeleteHero(c fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid id"})
	}

	var hero models.Hero
	if err := database.DB.First(&hero, id).Error; err != nil {
		return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "hero not found"})
	}

	if err := database.DB.Delete(&hero).Error; err != nil {
		return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "hero could not be deleted"})
	}

	return c.JSON(fiber.Map{"message": "hero deleted successfully"})
}
