package server

import (
	"net/http"

	"gophergate/internal/db"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

func (s *Server) handleGetUsers(c *gin.Context) {
	var users []db.User
	err := s.database.Select(&users, "SELECT id, username, display_name, role, must_change_password, created_at FROM users")
	if err != nil {
		c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error()))
		return
	}
	c.JSON(http.StatusOK, SuccessResponse(users))
}

type CreateUserRequest struct {
	Username    string  `json:"username" binding:"required"`
	Password    string  `json:"password" binding:"required"`
	DisplayName *string `json:"display_name"`
	Role        *string `json:"role"`
}

func (s *Server) handleCreateUser(c *gin.Context) {
	var req CreateUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, ErrorResponse("Invalid request"))
		return
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 12)
	if err != nil {
		c.JSON(http.StatusInternalServerError, ErrorResponse("Failed to hash password"))
		return
	}

	role := "viewer"
	if req.Role != nil {
		role = *req.Role
	}

	_, err = s.database.Exec("INSERT INTO users (username, password_hash, display_name, role, must_change_password) VALUES (?, ?, ?, ?, 1)",
		req.Username, string(hash), req.DisplayName, role)
	if err != nil {
		c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error()))
		return
	}

	c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "User created"}))
}

type UpdateUserRequest struct {
	DisplayName        *string `json:"display_name"`
	Role               *string `json:"role"`
	Password           *string `json:"password"`
	MustChangePassword *bool   `json:"must_change_password"`
}

func (s *Server) handleUpdateUser(c *gin.Context) {
	id := c.Param("id")
	var req UpdateUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, ErrorResponse("Invalid request"))
		return
	}

	if req.DisplayName != nil {
		s.database.Exec("UPDATE users SET display_name = ? WHERE id = ?", req.DisplayName, id)
	}
	if req.Role != nil {
		s.database.Exec("UPDATE users SET role = ? WHERE id = ?", req.Role, id)
	}
	if req.MustChangePassword != nil {
		s.database.Exec("UPDATE users SET must_change_password = ? WHERE id = ?", req.MustChangePassword, id)
	}
	if req.Password != nil {
		hash, _ := bcrypt.GenerateFromPassword([]byte(*req.Password), 12)
		s.database.Exec("UPDATE users SET password_hash = ? WHERE id = ?", string(hash), id)
	}

	c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "User updated"}))
}

func (s *Server) handleDeleteUser(c *gin.Context) {
	id := c.Param("id")

	session, _ := c.Get("session")
	if sess, ok := session.(*Session); ok {
		var username string
		s.database.Get(&username, "SELECT username FROM users WHERE id = ?", id)
		if username == sess.Username {
			c.JSON(http.StatusBadRequest, ErrorResponse("Cannot delete your own account"))
			return
		}
	}

	_, err := s.database.Exec("DELETE FROM users WHERE id = ?", id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error()))
		return
	}

	c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "User deleted"}))
}
