package http

import (
	"encoding/json"
	"net/http"

	"github.com/example/storage-appliance/internal/auth"
	"github.com/go-chi/chi/v5"
)

// UsersHandler shows the users management page
func (a *App) UsersHandler(w http.ResponseWriter, r *http.Request) {
	data := templateData(r, map[string]interface{}{
		"Title": "User Management",
	})
	if err := templates.ExecuteTemplate(w, "users", data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HXUsersHandler returns HTMX partial for users list
func (a *App) HXUsersHandler(w http.ResponseWriter, r *http.Request) {
	rbacStore := auth.NewRBACStore(a.DB)

	// Get all users (simplified - in production, you'd want pagination)
	rows, err := a.DB.QueryContext(r.Context(), `SELECT id, username, created_at FROM users ORDER BY username`)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type UserWithRoles struct {
		ID        string
		Username  string
		CreatedAt string
		Roles     []auth.Role
	}

	var users []UserWithRoles
	for rows.Next() {
		var u UserWithRoles
		if err := rows.Scan(&u.ID, &u.Username, &u.CreatedAt); err != nil {
			continue
		}
		roles, _ := rbacStore.GetUserRoles(r.Context(), u.ID)
		u.Roles = roles
		users = append(users, u)
	}

	data := map[string]interface{}{
		"Users": users,
	}
	if err := templates.ExecuteTemplate(w, "hx_users", data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// CreateUserHandler creates a new user
func (a *App) CreateUserHandler(w http.ResponseWriter, r *http.Request) {
	username := r.FormValue("username")
	password := r.FormValue("password")

	if username == "" || password == "" {
		http.Error(w, "username and password required", http.StatusBadRequest)
		return
	}

	userStore := auth.NewUserStore(a.DB)
	_, err := userStore.CreateUser(r.Context(), username, password)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Return HTMX partial or redirect
	if r.Header.Get("HX-Request") == "true" {
		w.Header().Set("HX-Refresh", "true")
		w.WriteHeader(http.StatusOK)
	} else {
		http.Redirect(w, r, "/admin/users", http.StatusFound)
	}
}

// DeleteUserHandler deletes a user
func (a *App) DeleteUserHandler(w http.ResponseWriter, r *http.Request) {
	userID := chi.URLParam(r, "id")

	_, err := a.DB.ExecContext(r.Context(), `DELETE FROM users WHERE id = ?`, userID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if r.Header.Get("HX-Request") == "true" {
		w.Header().Set("HX-Refresh", "true")
		w.WriteHeader(http.StatusOK)
	} else {
		http.Redirect(w, r, "/admin/users", http.StatusFound)
	}
}

// UpdateUserRolesHandler updates roles for a user
func (a *App) UpdateUserRolesHandler(w http.ResponseWriter, r *http.Request) {
	userID := chi.URLParam(r, "id")

	var req struct {
		RoleIDs []string `json:"role_ids"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "invalid request", http.StatusBadRequest)
		return
	}

	rbacStore := auth.NewRBACStore(a.DB)

	// Get current roles
	currentRoles, _ := rbacStore.GetUserRoles(r.Context(), userID)
	
	// Remove all current roles
	for _, role := range currentRoles {
		rbacStore.RemoveRoleFromUser(r.Context(), userID, role.ID)
	}

	// Add new roles
	for _, roleID := range req.RoleIDs {
		rbacStore.AssignRoleToUser(r.Context(), userID, roleID)
	}

	if r.Header.Get("HX-Request") == "true" {
		w.Header().Set("HX-Refresh", "true")
		w.WriteHeader(http.StatusOK)
	} else {
		http.Redirect(w, r, "/admin/users", http.StatusFound)
	}
}

// RolesHandler shows the roles management page
func (a *App) RolesHandler(w http.ResponseWriter, r *http.Request) {
	data := templateData(r, map[string]interface{}{
		"Title": "Role Management",
	})
	if err := templates.ExecuteTemplate(w, "roles", data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// HXRolesHandler returns HTMX partial for roles list
func (a *App) HXRolesHandler(w http.ResponseWriter, r *http.Request) {
	rbacStore := auth.NewRBACStore(a.DB)

	roles, err := rbacStore.GetAllRoles(r.Context())
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	type RoleWithPermissions struct {
		auth.Role
		Permissions []auth.Permission
	}

	var rolesWithPerms []RoleWithPermissions
	for _, role := range roles {
		rwp := RoleWithPermissions{Role: role}
		perms, _ := rbacStore.GetRolePermissions(r.Context(), role.ID)
		rwp.Permissions = perms
		rolesWithPerms = append(rolesWithPerms, rwp)
	}

	data := map[string]interface{}{
		"Roles": rolesWithPerms,
	}
	if err := templates.ExecuteTemplate(w, "hx_roles", data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// CreateRoleHandler creates a new role
func (a *App) CreateRoleHandler(w http.ResponseWriter, r *http.Request) {
	name := r.FormValue("name")
	description := r.FormValue("description")

	if name == "" {
		http.Error(w, "name required", http.StatusBadRequest)
		return
	}

	roleID := name // Using name as ID for simplicity
	_, err := a.DB.ExecContext(r.Context(), 
		`INSERT INTO roles (id, name, description) VALUES (?, ?, ?)`,
		roleID, name, description)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if r.Header.Get("HX-Request") == "true" {
		w.Header().Set("HX-Refresh", "true")
		w.WriteHeader(http.StatusOK)
	} else {
		http.Redirect(w, r, "/admin/roles", http.StatusFound)
	}
}

// DeleteRoleHandler deletes a role
func (a *App) DeleteRoleHandler(w http.ResponseWriter, r *http.Request) {
	roleID := chi.URLParam(r, "id")

	_, err := a.DB.ExecContext(r.Context(), `DELETE FROM roles WHERE id = ?`, roleID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if r.Header.Get("HX-Request") == "true" {
		w.Header().Set("HX-Refresh", "true")
		w.WriteHeader(http.StatusOK)
	} else {
		http.Redirect(w, r, "/admin/roles", http.StatusFound)
	}
}

// UpdateRolePermissionsHandler updates permissions for a role
func (a *App) UpdateRolePermissionsHandler(w http.ResponseWriter, r *http.Request) {
	roleID := chi.URLParam(r, "id")

	var req struct {
		PermissionIDs []string `json:"permission_ids"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "invalid request", http.StatusBadRequest)
		return
	}

	rbacStore := auth.NewRBACStore(a.DB)

	// Get current permissions
	currentPerms, _ := rbacStore.GetRolePermissions(r.Context(), roleID)
	
	// Remove all current permissions
	for _, perm := range currentPerms {
		rbacStore.RemovePermissionFromRole(r.Context(), roleID, perm.ID)
	}

	// Add new permissions
	for _, permID := range req.PermissionIDs {
		rbacStore.AssignPermissionToRole(r.Context(), roleID, permID)
	}

	if r.Header.Get("HX-Request") == "true" {
		w.Header().Set("HX-Refresh", "true")
		w.WriteHeader(http.StatusOK)
	} else {
		http.Redirect(w, r, "/admin/roles", http.StatusFound)
	}
}

