package api

import (
	"fmt"
	"net/http"
	"time"

	"github.com/pulse-lets-go/internal/models"
	"github.com/pulse-lets-go/internal/util"
	"golang.org/x/crypto/bcrypt"
)

// handleGetUsers — GET /api/users — список пользователей.
func (a *API) handleGetUsers(w http.ResponseWriter, r *http.Request) {
	users, err := a.configManager.ReadUsers()
	if err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка чтения пользователей")
		return
	}

	// Не возвращаем хэши паролей
	type safeUser struct {
		ID        string          `json:"id"`
		Username  string          `json:"username"`
		Role      models.UserRole `json:"role"`
		CreatedAt time.Time       `json:"created_at"`
		UpdatedAt time.Time       `json:"updated_at"`
	}
	result := make([]safeUser, len(users))
	for i, u := range users {
		result[i] = safeUser{
			ID:        u.ID,
			Username:  u.Username,
			Role:      u.Role,
			CreatedAt: u.CreatedAt,
			UpdatedAt: u.UpdatedAt,
		}
	}

	writeJSON(w, http.StatusOK, result)
}

// handleCreateUser — POST /api/users — создание пользователя.
func (a *API) handleCreateUser(w http.ResponseWriter, r *http.Request) {
	var req models.CreateUserRequest
	if err := decodeJSON(r, &req); err != nil {
		writeError(w, http.StatusBadRequest, "некорректный JSON")
		return
	}

	if req.Username == "" || req.Password == "" {
		writeError(w, http.StatusBadRequest, "имя и пароль обязательны")
		return
	}
	if req.Role != models.RoleAdmin && req.Role != models.RoleViewer {
		writeError(w, http.StatusBadRequest, "роль должна быть admin или viewer")
		return
	}

	users, err := a.configManager.ReadUsers()
	if err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка чтения пользователей")
		return
	}

	// Проверка уникальности имени
	for _, u := range users {
		if u.Username == req.Username {
			writeError(w, http.StatusConflict, "пользователь с таким именем уже существует")
			return
		}
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка хеширования пароля")
		return
	}

	now := time.Now().UTC()
	user := models.User{
		ID:           generateID("user"),
		Username:     req.Username,
		PasswordHash: string(hash),
		Role:         req.Role,
		CreatedAt:    now,
		UpdatedAt:    now,
	}

	users = append(users, user)
	if err := a.configManager.SaveUsers(users); err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка сохранения пользователя")
		return
	}

	writeJSON(w, http.StatusCreated, map[string]string{
		"id":       user.ID,
		"username": user.Username,
		"role":     string(user.Role),
	})
}

// handleUpdateUser — PUT /api/users/{id} — обновление пользователя.
func (a *API) handleUpdateUser(w http.ResponseWriter, r *http.Request) {
	userID := r.PathValue("id")
	if userID == "" {
		writeError(w, http.StatusBadRequest, "не указан id пользователя")
		return
	}

	var req models.UpdateUserRequest
	if err := decodeJSON(r, &req); err != nil {
		writeError(w, http.StatusBadRequest, "некорректный JSON")
		return
	}

	users, err := a.configManager.ReadUsers()
	if err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка чтения пользователей")
		return
	}

	idx := findUserIndex(users, userID)
	if idx < 0 {
		writeError(w, http.StatusNotFound, "пользователь не найден")
		return
	}

	u := &users[idx]
	if req.Username != nil {
		// Проверка уникальности
		for i, other := range users {
			if other.Username == *req.Username && i != idx {
				writeError(w, http.StatusConflict, "пользователь с таким именем уже существует")
				return
			}
		}
		u.Username = *req.Username
	}
	if req.Password != nil {
		hash, _ := bcrypt.GenerateFromPassword([]byte(*req.Password), bcrypt.DefaultCost)
		u.PasswordHash = string(hash)
	}
	if req.Role != nil {
		if *req.Role != models.RoleAdmin && *req.Role != models.RoleViewer {
			writeError(w, http.StatusBadRequest, "роль должна быть admin или viewer")
			return
		}
		// Защита первичного администратора от понижения роли
		if userID == "user-01" && *req.Role != models.RoleAdmin {
			writeError(w, http.StatusConflict, "роль первичного администратора нельзя изменить")
			return
		}
		u.Role = *req.Role
	}
	u.UpdatedAt = time.Now().UTC()

	if err := a.configManager.SaveUsers(users); err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка сохранения пользователя")
		return
	}

	writeJSON(w, http.StatusOK, map[string]string{
		"id":       u.ID,
		"username": u.Username,
		"role":     string(u.Role),
	})
}

// handleDeleteUser — DELETE /api/users/{id} — удаление пользователя.
func (a *API) handleDeleteUser(w http.ResponseWriter, r *http.Request) {
	userID := r.PathValue("id")
	if userID == "" {
		writeError(w, http.StatusBadRequest, "не указан id пользователя")
		return
	}

	users, err := a.configManager.ReadUsers()
	if err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка чтения пользователей")
		return
	}

	idx := findUserIndex(users, userID)
	if idx < 0 {
		writeError(w, http.StatusNotFound, "пользователь не найден")
		return
	}

	// Защита первичного администратора от удаления
	if userID == "user-01" {
		writeError(w, http.StatusConflict, "первичного администратора нельзя удалить")
		return
	}

	// Не даём удалить последнего админа
	adminCount := 0
	for _, u := range users {
		if u.Role == models.RoleAdmin {
			adminCount++
		}
	}
	if users[idx].Role == models.RoleAdmin && adminCount <= 1 {
		writeError(w, http.StatusConflict, "нельзя удалить последнего администратора")
		return
	}

	users = append(users[:idx], users[idx+1:]...)
	if err := a.configManager.SaveUsers(users); err != nil {
		writeError(w, http.StatusInternalServerError, "ошибка сохранения пользователей")
		return
	}

	writeJSON(w, http.StatusNoContent, nil)
}

// findUserIndex находит индекс пользователя по ID.
func findUserIndex(users []models.User, id string) int {
	for i := range users {
		if users[i].ID == id {
			return i
		}
	}
	return -1
}

// generateID генерирует ID вида "prefix-XXXXX".
func generateID(prefix string) string {
	return fmt.Sprintf("%s-%s", prefix, util.RandomHex(6))
}
