package api

import (
	"github.com/gofiber/fiber/v2"

	"fiko-ai/internal/audit"
	"fiko-ai/internal/protocol"
	"fiko-ai/internal/settings"
)

type settingsResponse struct {
	Model       string  `json:"model"`
	Temperature float64 `json:"temperature"`
	TopP        float64 `json:"topP"`
	MaxTokens   int     `json:"maxTokens"`
	ContextSize int     `json:"contextSize"`
	// ConfirmMode yazma/silme onay politikası (always|risky|missing|never).
	ConfirmMode string `json:"confirmMode"`
	// ConfirmModes geçerli modların listesi (ayar ekranındaki seçimi besler).
	ConfirmModes []string `json:"confirmModes"`
}

// settingsPayload, ayarları API gövdesine çevirir (GET ve PUT aynı yanıtı döner).
func settingsPayload(v settings.Values) settingsResponse {
	return settingsResponse{
		Model: v.Model, Temperature: v.Temperature, TopP: v.TopP,
		MaxTokens: v.MaxTokens, ContextSize: v.ContextSize,
		ConfirmMode: v.ConfirmMode, ConfirmModes: settings.ConfirmModeValues,
	}
}

// getSettings GET /api/settings — anlık ayarlar.
func (s *Server) getSettings(c *fiber.Ctx) error {
	if s.deps.Settings == nil {
		return fail(c, fiber.StatusServiceUnavailable, protocol.ErrCodeInternal, "ayarlar yapılandırılmamış")
	}
	return c.JSON(settingsPayload(s.deps.Settings.Get()))
}

// putSettings PUT /api/settings — kısmi güncelleme (verilmeyen alanlar korunur).
// Denetim kaydı alınır: kim, neyi değiştirdi (spec: her işlem audit log'a yazılmalı).
func (s *Server) putSettings(c *fiber.Ctx) error {
	if s.deps.Settings == nil {
		return fail(c, fiber.StatusServiceUnavailable, protocol.ErrCodeInternal, "ayarlar yapılandırılmamış")
	}
	var in settings.Patch
	if err := c.BodyParser(&in); err != nil {
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, "geçersiz istek gövdesi")
	}
	userID := s.currentUser(c)
	before := s.deps.Settings.Get()

	updated, err := s.deps.Settings.Update(in)
	if err != nil {
		s.auditFailure(userID, "settings.update", err.Error())
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, err.Error())
	}
	s.auditSuccess(userID, "settings.update", settingsAuditDetail(before, updated))

	return c.JSON(settingsPayload(updated))
}

// settingsAuditDetail değişikliği kısa ve okunur hale getirir (denetim kaydı şişmesin).
func settingsAuditDetail(before, after settings.Values) string {
	changed := make([]string, 0, 5)
	if before.Model != after.Model {
		changed = append(changed, "model="+after.Model)
	}
	if before.Temperature != after.Temperature {
		changed = append(changed, "temperature")
	}
	if before.TopP != after.TopP {
		changed = append(changed, "topP")
	}
	if before.MaxTokens != after.MaxTokens {
		changed = append(changed, "maxTokens")
	}
	if before.ContextSize != after.ContextSize {
		changed = append(changed, "contextSize")
	}
	if len(changed) == 0 {
		return "değişiklik yok"
	}
	out := ""
	for i, c := range changed {
		if i > 0 {
			out += ","
		}
		out += c
	}
	return out
}

// auditSuccess/auditFailure denetim kaydı yazar (logger yoksa sessizce geçilir).
func (s *Server) auditSuccess(userID, action, detail string) {
	if s.deps.Audit != nil {
		s.deps.Audit.Success(userID, "", action, audit.Sanitize(detail, 200))
	}
}

func (s *Server) auditFailure(userID, action, detail string) {
	if s.deps.Audit != nil {
		s.deps.Audit.Failure(userID, "", action, audit.Sanitize(detail, 200))
	}
}
