package api

import (
	"errors"
	"strings"

	"github.com/gofiber/fiber/v2"

	"fiko-ai/internal/persona"
	"fiko-ai/internal/protocol"
)

// Kullanıcı davranış profilleri (persona) — YÖNETİCİ UÇLARI.
//
// Konsept: yönetici "Proje Yöneticisi" gibi bir profil yazar ve kullanıcılara
// atar. Atanmış kullanıcıyla konuşulduğunda bu kurallar sistem istemine eklenir;
// yapay zekâ ona göre davranır.
//
// GÜVENLİK: Grup adminOnly ile korunur (yalnız yönetici). Profil metni modele
// GİRER; bu yüzden alan sınırları persona paketinde zorlanır ve profil güvenlik
// kurallarının üstüne yazamaz (bkz. prompt.Personas).
type personaInput struct {
	Name            string   `json:"name"`
	Role            string   `json:"role"`
	Instructions    string   `json:"instructions"`
	Notes           string   `json:"notes"`
	AssignedUserIDs []string `json:"assignedUserIds"`
}

type personasResponse struct {
	Items []persona.Profile `json:"items"`
	Count int               `json:"count"`
}

// personasAvailable, profil servisi yoksa 503 döner (özellik kapalı).
//
// Neden 404 değil? Yol kayıtlı; 404 "burada bir şey yok" der ve yönetici
// "profiller silinmiş" sanır. 503 "servis kapalı" der (knowledge deseni).
func (s *Server) personasAvailable(c *fiber.Ctx) error {
	if s.deps.Personas == nil {
		return fail(c, fiber.StatusServiceUnavailable, protocol.ErrCodeInternal,
			"kullanıcı profilleri kapalı")
	}
	return c.Next()
}

// failPersona, persona hatalarını HTTP durumuna çevirir.
//
// AYRIM: ErrNotFound 404, doğrulama hatası 400 (alan listesiyle), ErrForbidden
// 403. Diğer hatalar 500 — istemciye iç hata sızmaz.
func failPersona(c *fiber.Ctx, err error) error {
	switch {
	case err == nil:
		return nil
	case persona.IsValidation(err):
		var ve *persona.ValidationError
		if errors.As(err, &ve) {
			return c.Status(fiber.StatusBadRequest).JSON(errorBody{Error: apiError{
				Code: protocol.ErrCodeValidation, Message: "profil geçersiz", Fields: personaFields(ve.Errors),
			}})
		}
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, "geçersiz profil")
	case errors.Is(err, persona.ErrNotFound):
		return fail(c, fiber.StatusNotFound, protocol.ErrCodeNotFound, "profil bulunamadı")
	case errors.Is(err, persona.ErrForbidden):
		return fail(c, fiber.StatusForbidden, protocol.ErrCodePermissionDenied, "yetkisiz")
	default:
		return fail(c, fiber.StatusInternalServerError, protocol.ErrCodeInternal, "profil işlemi başarısız")
	}
}

// listPersonas GET /api/admin/personas — tüm profiller.
func (s *Server) listPersonas(c *fiber.Ctx) error {
	list, err := s.deps.Personas.List(c.UserContext())
	if err != nil {
		return failPersona(c, err)
	}
	if list == nil {
		list = []persona.Profile{}
	}
	return c.JSON(personasResponse{Items: list, Count: len(list)})
}

// createPersona POST /api/admin/personas — yeni profil.
func (s *Server) createPersona(c *fiber.Ctx) error {
	var in personaInput
	if len(c.Body()) == 0 {
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, "geçersiz istek gövdesi")
	}
	if err := c.BodyParser(&in); err != nil {
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, "geçersiz istek gövdesi")
	}
	p, err := s.deps.Personas.Create(c.UserContext(), persona.NewInput{
		Name: in.Name, Role: in.Role, Instructions: in.Instructions,
		Notes: in.Notes, AssignedUserIDs: in.AssignedUserIDs,
	})
	if err != nil {
		return failPersona(c, err)
	}
	s.log.Info("kullanıcı profili oluşturuldu",
		"profil", p.Name, "kullanici", len(p.AssignedUserIDs), "yonetici", s.currentUser(c))
	return c.Status(fiber.StatusCreated).JSON(p)
}

// updatePersona PUT /api/admin/personas/:id — profili düzenle.
func (s *Server) updatePersona(c *fiber.Ctx) error {
	// strings.Clone KULLANILIR: Fiber parametre değeri havuzdan gelir ve
	// handler bitince bozulur (bkz. notifications.go notu).
	id := strings.Clone(c.Params("id"))
	var in personaInput
	if len(c.Body()) == 0 {
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, "geçersiz istek gövdesi")
	}
	if err := c.BodyParser(&in); err != nil {
		return fail(c, fiber.StatusBadRequest, protocol.ErrCodeBadRequest, "geçersiz istek gövdesi")
	}
	p, err := s.deps.Personas.Update(c.UserContext(), id, persona.UpdateInput{
		Name: in.Name, Role: in.Role, Instructions: in.Instructions,
		Notes: in.Notes, AssignedUserIDs: in.AssignedUserIDs,
	})
	if err != nil {
		return failPersona(c, err)
	}
	s.log.Info("kullanıcı profili güncellendi",
		"profil", p.Name, "kullanici", len(p.AssignedUserIDs), "yonetici", s.currentUser(c))
	return c.JSON(p)
}

// deletePersona DELETE /api/admin/personas/:id — profili sil.
func (s *Server) deletePersona(c *fiber.Ctx) error {
	id := strings.Clone(c.Params("id"))
	if err := s.deps.Personas.Delete(c.UserContext(), id); err != nil {
		return failPersona(c, err)
	}
	s.log.Info("kullanıcı profili silindi", "profil", id, "yonetici", s.currentUser(c))
	return c.SendStatus(fiber.StatusNoContent)
}
