package setting

import (
	"fmt"
	"log"
	"regexp"
	"strconv"
	"strings"
	"system-altrak/internal/middleware"
	"system-altrak/pkg/utils"

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

type Handler struct {
	service SettingService
}

var settingsHexColorPattern = regexp.MustCompile(`^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$`)

func normalizeSettingValue(value string) string {
	return strings.TrimSpace(value)
}

func isValidBooleanSettingValue(value string) bool {
	switch strings.ToLower(normalizeSettingValue(value)) {
	case "true", "false", "1", "0", "yes", "no", "on", "off", "enabled", "disabled":
		return true
	default:
		return false
	}
}

func isValidHexColor(value string) bool {
	return settingsHexColorPattern.MatchString(normalizeSettingValue(value))
}

func isValidNumberingFormat(value string) bool {
	trimmed := normalizeSettingValue(value)
	return trimmed != "" && strings.Contains(trimmed, "{INC}")
}

func isAllowedSettingValue(value string, allowedValues []string) bool {
	normalized := strings.ToLower(normalizeSettingValue(value))
	for _, allowed := range allowedValues {
		if normalized == allowed {
			return true
		}
	}
	return false
}

func settingLabel(key string) string {
	switch key {
	case "company_name":
		return "Company Name"
	case "branch_name":
		return "Branch / Regional"
	case "company_address":
		return "Full Address"
	case "document_header_title":
		return "Document Header Title"
	case "branding_primary_color":
		return "Primary Color (HEX)"
	case "branding_secondary_color":
		return "Secondary Color (HEX)"
	case "isf_format":
		return "ISF Format"
	case "isf_reset":
		return "ISF Reset Sequence"
	case "iom_format":
		return "IOM Memo Format"
	case "iom_start":
		return "Sequence Start From"
	case "cp_format":
		return "Customer Profile Format"
	case "cp_reset":
		return "Customer Profile Reset"
	case "ui_visual_transitions":
		return "Visual Transitions"
	case "ui_dynamic_sidebar":
		return "Dynamic Sidebar"
	case "security_mfa_enabled":
		return "Multifactor Auth"
	case "security_auto_logout":
		return "Auto Logout"
	default:
		return key
	}
}

func validateSettingsPayload(body map[string]string) error {
	for key, value := range body {
		trimmed := normalizeSettingValue(value)
		body[key] = trimmed

		switch key {
		case "company_name", "branch_name", "company_address", "document_header_title":
			if trimmed == "" {
				return fmt.Errorf("%s cannot be empty", settingLabel(key))
			}
		case "branding_primary_color", "branding_secondary_color":
			if trimmed == "" {
				return fmt.Errorf("%s cannot be empty", settingLabel(key))
			}
			if !isValidHexColor(trimmed) {
				return fmt.Errorf("%s must use a valid HEX color (#RGB or #RRGGBB)", settingLabel(key))
			}
		case "isf_format", "iom_format", "cp_format":
			if !isValidNumberingFormat(trimmed) {
				return fmt.Errorf("%s must be filled and contain {INC}", settingLabel(key))
			}
		case "isf_reset":
			if !isAllowedSettingValue(trimmed, []string{"yearly", "monthly"}) {
				return fmt.Errorf("%s must be yearly or monthly", settingLabel(key))
			}
		case "iom_start":
			parsedStart, err := strconv.Atoi(trimmed)
			if err != nil || parsedStart <= 0 {
				return fmt.Errorf("%s must be a positive integer", settingLabel(key))
			}
		case "cp_reset":
			if !isAllowedSettingValue(trimmed, []string{"global", "yearly", "monthly"}) {
				return fmt.Errorf("%s must be global, yearly, or monthly", settingLabel(key))
			}
		case "ui_visual_transitions", "ui_dynamic_sidebar", "security_mfa_enabled", "security_auto_logout":
			if !isValidBooleanSettingValue(trimmed) {
				return fmt.Errorf("%s must be a boolean value", settingLabel(key))
			}
		}
	}

	return nil
}

func NewHandler(s SettingService) *Handler {
	return &Handler{service: s}
}

func (h *Handler) GetSettings(c *fiber.Ctx) error {
	list, err := h.service.List()
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to load system settings")
	}

	settingsMap := make(map[string]string)
	for _, s := range list {
		settingsMap[s.Key] = s.Value
	}

	return utils.SuccessResponse(c, "Settings retrieved", settingsMap)
}

func (h *Handler) UpdateSettings(c *fiber.Ctx) error {
	log.Println("[Settings] Incoming UpdateSettings request")
	var body map[string]string
	if err := c.BodyParser(&body); err != nil {
		log.Printf("[Settings] BodyParser error: %v", err)
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid request body")
	}

	raw := make(map[string]interface{}, len(body))
	for k, v := range body {
		raw[k] = v
	}
	sanitizedRaw := middleware.SanitizeJSON(raw)

	sanitizedBody := make(map[string]string, len(sanitizedRaw))
	for k, v := range sanitizedRaw {
		s, ok := v.(string)
		if !ok {
			continue
		}
		sanitizedBody[k] = strings.TrimSpace(s)
	}
	body = sanitizedBody

	// Validate that body is not empty
	if len(body) == 0 {
		log.Println("[Settings] Empty body received")
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "No settings provided")
	}

	if err := validateSettingsPayload(body); err != nil {
		log.Printf("[Settings] Validation error: %v", err)
		return utils.ErrorResponse(c, fiber.StatusBadRequest, err.Error())
	}

	log.Printf("[Settings] Saving %d parameters", len(body))
	for k, v := range body {
		if err := h.service.Set(k, v); err != nil {
			log.Printf("[Settings] Failed to save %s: %v", k, err)
			return utils.InternalErrorResponse(c, "Failed to save setting: "+k)
		}
	}

	log.Println("[Settings] All parameters saved successfully")
	return utils.SuccessResponse(c, "System configuration updated successfully", nil)
}

func (h *Handler) GetPermissions(c *fiber.Ctx) error {
	perms, err := h.service.ListPermissions()
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to load permissions")
	}
	return utils.SuccessResponse(c, "Permissions retrieved", perms)
}

func (h *Handler) UpdatePermission(c *fiber.Ctx) error {
	var body struct {
		Role      string `json:"role"`
		Module    string `json:"module"`
		CanView   bool   `json:"can_view"`
		CanCreate bool   `json:"can_create"`
		CanEdit   bool   `json:"can_edit"`
		CanDelete bool   `json:"can_delete"`
		CanExport bool   `json:"can_export"`
	}

	if err := c.BodyParser(&body); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid request body")
	}

	if body.Role == "" || body.Module == "" {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Role and Module are required")
	}

	err := h.service.UpdatePermission(body.Role, body.Module, body.CanView, body.CanCreate, body.CanEdit, body.CanDelete, body.CanExport)
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to update permission")
	}

	return utils.SuccessResponse(c, "Permission updated successfully", nil)
}
func (h *Handler) GetStats(c *fiber.Ctx) error {
	stats, err := h.service.GetStats()
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to load system stats")
	}
	return utils.SuccessResponse(c, "Stats retrieved", stats)
}

func (h *Handler) OptimizeDB(c *fiber.Ctx) error {
	log.Println("[Settings] Incoming OptimizeDB request")
	err := h.service.OptimizeDB()
	if err != nil {
		log.Printf("[Settings] Failed to optimize database: %v", err)
		return utils.InternalErrorResponse(c, "Gagal menjalankan optimasi database")
	}
	log.Println("[Settings] Database optimized successfully")
	return utils.SuccessResponse(c, "Optimasi database berhasil diselesaikan", nil)
}

