diff --git a/cmd/main.go b/cmd/main.go
index 16adb89..8c204fa 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -46,7 +46,7 @@ var (
 	ko          = koanf.New(".")
 	frontendDir = "frontend/dist"
 	ctx         = context.Background()
-	buildString string
+	buildString = ""
 )
 
 // App is the global app context which is passed and injected in the http handlers.
@@ -103,7 +103,7 @@ func main() {
 		os.Exit(0)
 	}
 
-	log.Printf("Build: %s", buildString)
+	colorlog.Green("Build: %s", buildString)
 
 	// Installer.
 	if ko.Bool("install") {
@@ -132,9 +132,12 @@ func main() {
 	loadSettings(settings)
 
 	var (
+		autoAssignInterval          = ko.MustDuration("autoassigner.interval")
+		unsnoozeInterval            = ko.MustDuration("conversation.unsnooze_interval")
 		automationWrk               = ko.MustInt("automation.worker_count")
-		messageDispatchWrk          = ko.MustInt("message.dispatch_workers")
-		messageDispatchScanInterval = ko.MustDuration("message.dispatch_scan_interval")
+		messageOutgoingQWorkers     = ko.MustDuration("message.outgoing_queue_workers")
+		messageIncomingQWorkers     = ko.MustDuration("message.incoming_queue_workers")
+		messageOutgoingScanInterval = ko.MustDuration("message.message_outoing_scan_interval")
 		lo                          = initLogger("libredesk")
 		wsHub                       = ws.NewHub()
 		rdb                         = initRedis()
@@ -157,34 +160,17 @@ func main() {
 		autoassigner                = initAutoAssigner(team, user, conversation)
 	)
 
-	// Set store.
 	automation.SetConversationStore(conversation)
-
-	// Start inbox receivers.
 	startInboxes(ctx, inbox, conversation)
 
-	// Start evaluating automation rules.
 	go automation.Run(ctx, automationWrk)
-
-	// Start conversation auto assigner.
-	go autoassigner.Run(ctx)
-
-	// Start processing incoming and outgoing messages.
-	go conversation.Run(ctx, messageDispatchWrk, messageDispatchScanInterval)
-
-	// Run the unsnoozer.
-	go conversation.RunUnsnoozer(ctx)
-
-	// Start notifier.
+	go autoassigner.Run(ctx, autoAssignInterval)
+	go conversation.Run(ctx, messageIncomingQWorkers, messageOutgoingQWorkers, messageOutgoingScanInterval)
+	go conversation.RunUnsnoozer(ctx, unsnoozeInterval)
+	go media.DeleteUnlinkedMedia(ctx)
 	go notifier.Run(ctx)
-
-	// Start SLA monitor.
 	go sla.Run(ctx)
 
-	// Purge unlinked message media.
-	go media.DeleteUnlinkedMessageMedia(ctx)
-
-	// Init the app
 	var app = &App{
 		lo:            lo,
 		fs:            fs,
@@ -215,17 +201,12 @@ func main() {
 		ai:            initAI(db),
 	}
 
-	// Init fastglue and set app in ctx.
 	g := fastglue.NewGlue()
-
-	// Set the app in context.
 	g.SetContext(app)
-
-	// Init HTTP handlers.
 	initHandlers(g, wsHub)
 
 	s := &fasthttp.Server{
-		Name:                 "libredesk",
+		Name:                 "LibreDesk",
 		ReadTimeout:          ko.MustDuration("app.server.read_timeout"),
 		WriteTimeout:         ko.MustDuration("app.server.write_timeout"),
 		MaxRequestBodySize:   ko.MustInt("app.server.max_body_size"),
@@ -239,16 +220,14 @@ func main() {
 		}
 	}()
 
-	colorlog.Green("🚀 server listening on %s %s", ko.String("app.server.address"), ko.String("app.server.socket"))
+	colorlog.Green("🚀 listening on %s %s", ko.String("app.server.address"), ko.String("app.server.socket"))
 
 	// Wait for shutdown signal.
 	<-ctx.Done()
 	colorlog.Red("Shutting down the server. Please wait....")
-	// Shutdown HTTP server.
 	s.Shutdown()
 	colorlog.Red("Server shutdown complete.")
 	colorlog.Red("Shutting down services. Please wait....")
-	// Shutdown services.
 	inbox.Close()
 	colorlog.Red("Inbox shutdown complete.")
 	automation.Close()
diff --git a/frontend/src/components/sidebar/Sidebar.vue b/frontend/src/components/sidebar/Sidebar.vue
index 0c352e2..fbb219e 100644
--- a/frontend/src/components/sidebar/Sidebar.vue
+++ b/frontend/src/components/sidebar/Sidebar.vue
@@ -33,6 +33,12 @@ import {
   Search,
   MessageCircle
 } from 'lucide-vue-next'
+import {
+  DropdownMenu,
+  DropdownMenuContent,
+  DropdownMenuItem,
+  DropdownMenuTrigger,
+} from '@/components/ui/dropdown-menu'
 import { computed } from 'vue'
 import { useUserStore } from '@/stores/user'
 import { useConversationStore } from '@/stores/conversation'
diff --git a/frontend/src/views/UserLoginView.vue b/frontend/src/views/UserLoginView.vue
index 137be0a..01415ca 100644
--- a/frontend/src/views/UserLoginView.vue
+++ b/frontend/src/views/UserLoginView.vue
@@ -63,12 +63,12 @@
 
               
                 
-                  
-                  
+                   -->
                 
                 
                   Forgot password?
diff --git a/internal/autoassigner/autoassigner.go b/internal/autoassigner/autoassigner.go
index a934f73..44913f9 100644
--- a/internal/autoassigner/autoassigner.go
+++ b/internal/autoassigner/autoassigner.go
@@ -4,13 +4,13 @@ package autoassigner
 import (
 	"context"
 	"errors"
+	"fmt"
 	"strconv"
 	"sync"
 	"time"
 
-	"github.com/abhinavxd/libredesk/internal/conversation"
 	"github.com/abhinavxd/libredesk/internal/conversation/models"
-	"github.com/abhinavxd/libredesk/internal/team"
+	tmodels "github.com/abhinavxd/libredesk/internal/team/models"
 	umodels "github.com/abhinavxd/libredesk/internal/user/models"
 	"github.com/mr-karan/balance"
 	"github.com/zerodha/logf"
@@ -24,6 +24,16 @@ const (
 	AssignmentTypeRoundRobin = "Round robin"
 )
 
+type conversationStore interface {
+	GetUnassignedConversations() ([]models.Conversation, error)
+	UpdateConversationUserAssignee(conversationUUID string, userID int, user umodels.User) error
+}
+
+type teamStore interface {
+	GetAll() ([]tmodels.Team, error)
+	GetMembers(teamID int) ([]umodels.User, error)
+}
+
 // Engine represents a manager for assigning unassigned conversations
 // to team agents in a round-robin pattern.
 type Engine struct {
@@ -32,23 +42,23 @@ type Engine struct {
 	// Mutex to protect the balancer map
 	balanceMu sync.Mutex
 
-	systemUser          umodels.User
-	conversationManager *conversation.Manager
-	teamManager         *team.Manager
-	lo                  *logf.Logger
-	closed              bool
-	closedMu            sync.Mutex
-	wg                  sync.WaitGroup
+	systemUser        umodels.User
+	conversationStore conversationStore
+	teamStore         teamStore
+	lo                *logf.Logger
+	closed            bool
+	closedMu          sync.Mutex
+	wg                sync.WaitGroup
 }
 
 // New initializes a new Engine instance, set up with the provided team manager,
 // conversation manager, and logger.
-func New(teamManager *team.Manager, conversationManager *conversation.Manager, systemUser umodels.User, lo *logf.Logger) (*Engine, error) {
+func New(teamStore teamStore, conversationStore conversationStore, systemUser umodels.User, lo *logf.Logger) (*Engine, error) {
 	var e = Engine{
-		conversationManager: conversationManager,
-		teamManager:         teamManager,
-		systemUser:          systemUser,
-		lo:                  lo,
+		conversationStore: conversationStore,
+		teamStore:         teamStore,
+		systemUser:        systemUser,
+		lo:                lo,
 	}
 	balancer, err := e.populateTeamBalancer()
 	if err != nil {
@@ -60,8 +70,8 @@ func New(teamManager *team.Manager, conversationManager *conversation.Manager, s
 
 // Run initiates the conversation assignment process and is to be invoked as a goroutine.
 // This function continuously assigns unassigned conversations to agents at regular intervals.
-func (e *Engine) Run(ctx context.Context) {
-	ticker := time.NewTicker(60 * time.Second)
+func (e *Engine) Run(ctx context.Context, autoAssignInterval time.Duration) {
+	ticker := time.NewTicker(autoAssignInterval)
 	defer ticker.Stop()
 
 	e.wg.Add(1)
@@ -78,6 +88,9 @@ func (e *Engine) Run(ctx context.Context) {
 			if closed {
 				return
 			}
+			if err := e.reloadBalancer(); err != nil {
+				e.lo.Error("error reloading balancer", "error", err)
+			}
 			if err := e.assignConversations(); err != nil {
 				e.lo.Error("error assigning conversations", "error", err)
 			}
@@ -97,14 +110,14 @@ func (e *Engine) Close() {
 	e.wg.Wait()
 }
 
-// RefreshBalancer updates the round-robin balancer with the latest user and team data.
-func (e *Engine) RefreshBalancer() error {
+// reloadBalancer updates the round-robin balancer with the latest user and team data.
+func (e *Engine) reloadBalancer() error {
 	e.balanceMu.Lock()
 	defer e.balanceMu.Unlock()
 
 	balancer, err := e.populateTeamBalancer()
 	if err != nil {
-		e.lo.Error("Error updating team balancer pool", "error", err)
+		e.lo.Error("error updating team balancer pool", "error", err)
 		return err
 	}
 	e.roundRobinBalancer = balancer
@@ -114,10 +127,9 @@ func (e *Engine) RefreshBalancer() error {
 // populateTeamBalancer populates the team balancer pool with the team members.
 func (e *Engine) populateTeamBalancer() (map[int]*balance.Balance, error) {
 	var (
-		balancer = make(map[int]*balance.Balance)
+		balancer   = make(map[int]*balance.Balance)
+		teams, err = e.teamStore.GetAll()
 	)
-
-	teams, err := e.teamManager.GetAll()
 	if err != nil {
 		return nil, err
 	}
@@ -127,12 +139,12 @@ func (e *Engine) populateTeamBalancer() (map[int]*balance.Balance, error) {
 			continue
 		}
 
-		users, err := e.teamManager.GetMembers(team.ID)
+		users, err := e.teamStore.GetMembers(team.ID)
 		if err != nil {
 			return nil, err
 		}
 
-		// Add the users to team balancer pool.
+		// Add users to team's balancer pool.
 		for _, user := range users {
 			if _, ok := balancer[team.ID]; !ok {
 				balancer[team.ID] = balance.NewBalance()
@@ -146,30 +158,35 @@ func (e *Engine) populateTeamBalancer() (map[int]*balance.Balance, error) {
 // assignConversations function fetches conversations that have been assigned to teams but not to any individual user,
 // and then proceeds to assign them to team members based on a round-robin strategy.
 func (e *Engine) assignConversations() error {
-	unassigned, err := e.conversationManager.GetUnassignedConversations()
+	unassignedConversations, err := e.conversationStore.GetUnassignedConversations()
 	if err != nil {
-		return err
+		return fmt.Errorf("fetching unassigned conversations: %w", err)
 	}
 
-	e.lo.Debug("found unassigned conversations", "count", len(unassigned))
+	if len(unassignedConversations) > 0 {
+		e.lo.Debug("found unassigned conversations", "count", len(unassignedConversations))
+	}
 
-	for _, conversation := range unassigned {
+	for _, conversation := range unassignedConversations {
 		// Get user from the pool.
 		userIDStr, err := e.getUserFromPool(conversation)
 		if err != nil {
-			e.lo.Error("error fetching user from balancer pool", "error", err)
+			e.lo.Error("error fetching user from balancer pool", "conversation_uuid", conversation.UUID, "error", err)
 			continue
 		}
 
 		// Convert to int.
 		userID, err := strconv.Atoi(userIDStr)
 		if err != nil {
-			e.lo.Error("error converting user id from string to int", "error", err)
+			e.lo.Error("error converting user id from string to int", "user_id", userIDStr, "error", err)
 			continue
 		}
 
 		// Assign conversation.
-		e.conversationManager.UpdateConversationUserAssignee(conversation.UUID, userID, e.systemUser)
+		if err := e.conversationStore.UpdateConversationUserAssignee(conversation.UUID, userID, e.systemUser); err != nil {
+			e.lo.Error("error assigning conversation", "conversation_uuid", conversation.UUID, "error", err)
+			continue
+		}
 	}
 	return nil
 }
diff --git a/internal/conversation/conversation.go b/internal/conversation/conversation.go
index 16238c8..81e1d69 100644
--- a/internal/conversation/conversation.go
+++ b/internal/conversation/conversation.go
@@ -1,4 +1,4 @@
-// Package conversation provides functionality to manage conversations in the system.
+// Package conversation manages conversations and messages.
 package conversation
 
 import (
@@ -163,7 +163,6 @@ type queries struct {
 	// Conversation queries.
 	GetLatestReceivedMessageSourceID   *sqlx.Stmt `query:"get-latest-received-message-source-id"`
 	GetToAddress                       *sqlx.Stmt `query:"get-to-address"`
-	GetConversationID                  *sqlx.Stmt `query:"get-conversation-id"`
 	GetConversationUUID                *sqlx.Stmt `query:"get-conversation-uuid"`
 	GetConversation                    *sqlx.Stmt `query:"get-conversation"`
 	GetConversationsCreatedAfter       *sqlx.Stmt `query:"get-conversations-created-after"`
@@ -177,8 +176,7 @@ type queries struct {
 	UpdateConversationPriority         *sqlx.Stmt `query:"update-conversation-priority"`
 	UpdateConversationStatus           *sqlx.Stmt `query:"update-conversation-status"`
 	UpdateConversationLastMessage      *sqlx.Stmt `query:"update-conversation-last-message"`
-	UpdateConversationMeta             *sqlx.Stmt `query:"update-conversation-meta"`
-	InsertConverstionParticipant       *sqlx.Stmt `query:"insert-conversation-participant"`
+	InsertConversationParticipant      *sqlx.Stmt `query:"insert-conversation-participant"`
 	InsertConversation                 *sqlx.Stmt `query:"insert-conversation"`
 	UpsertConversationTags             *sqlx.Stmt `query:"upsert-conversation-tags"`
 	UnassignOpenConversations          *sqlx.Stmt `query:"unassign-open-conversations"`
@@ -269,19 +267,6 @@ func (c *Manager) GetUnassignedConversations() ([]models.Conversation, error) {
 	return conv, nil
 }
 
-// GetConversationID retrieves the ID of a conversation by its UUID.
-func (c *Manager) GetConversationID(uuid string) (int, error) {
-	var id int
-	if err := c.q.GetConversationID.QueryRow(uuid).Scan(&id); err != nil {
-		if err == sql.ErrNoRows {
-			return id, err
-		}
-		c.lo.Error("fetching conversation from DB", "error", err)
-		return id, err
-	}
-	return id, nil
-}
-
 // GetConversationUUID retrieves the UUID of a conversation by its ID.
 func (c *Manager) GetConversationUUID(id int) (string, error) {
 	var uuid string
@@ -353,20 +338,6 @@ func (c *Manager) GetConversations(userID int, listType, order, orderBy, filters
 	return conversations, nil
 }
 
-// UpdateConversationMeta updates the metadata of a conversation.
-func (c *Manager) UpdateConversationMeta(conversationID int, conversationUUID string, meta map[string]string) error {
-	metaJSON, err := json.Marshal(meta)
-	if err != nil {
-		c.lo.Error("error marshalling conversation meta", "meta", meta, "error", err)
-		return err
-	}
-	if _, err := c.q.UpdateConversationMeta.Exec(conversationID, conversationUUID, metaJSON); err != nil {
-		c.lo.Error("error updating conversation meta", "error", "error")
-		return err
-	}
-	return nil
-}
-
 // UpdateConversationLastMessage updates the last message details for a conversation.
 func (c *Manager) UpdateConversationLastMessage(convesationID int, conversationUUID, lastMessage string, lastMessageAt time.Time) error {
 	if _, err := c.q.UpdateConversationLastMessage.Exec(convesationID, conversationUUID, lastMessage, lastMessageAt); err != nil {
@@ -403,7 +374,7 @@ func (c *Manager) UpdateConversationUserAssignee(uuid string, assigneeID int, ac
 	}
 
 	// Send email to assignee.
-	if err := c.SendAssignedConversationEmail([]int{assigneeID}, conversation.Subject.String, uuid); err != nil {
+	if err := c.SendAssignedConversationEmail([]int{assigneeID}, conversation); err != nil {
 		c.lo.Error("error sending assigned conversation email", "error", err)
 	}
 
@@ -638,14 +609,13 @@ func (c *Manager) makeConversationsListQuery(userID int, baseQuery, listType, or
 	// Build the paginated query.
 	query, qArgs, err := dbutil.BuildPaginatedQuery(baseQuery, qArgs, dbutil.PaginationOptions{
 		Order:    order,
-		OrderBy:  "",
+		OrderBy:  orderBy,
 		Page:     page,
 		PageSize: pageSize,
 	}, filtersJSON, dbutil.AllowedFields{
 		"conversations":         ConversationsListAllowedFilterFields,
 		"conversation_statuses": ConversationStatusesFilterFields,
 	})
-	fmt.Println("Query: ", query)
 	if err != nil {
 		c.lo.Error("error preparing query", "error", err)
 		return "", nil, err
@@ -674,16 +644,27 @@ func (m *Manager) GetLatestReceivedMessageSourceID(conversationID int) (string,
 }
 
 // SendAssignedConversationEmail sends a email for an assigned conversation to the passed user ids.
-func (m *Manager) SendAssignedConversationEmail(userIDs []int, subject, conversationUUID string) error {
+func (m *Manager) SendAssignedConversationEmail(userIDs []int, conversation models.Conversation) error {
+	agent, err := m.userStore.Get(userIDs[0])
+	if err != nil {
+		m.lo.Error("error fetching agent", "error", err)
+		return fmt.Errorf("fetching agent: %w", err)
+	}
+
 	content, subject, err := m.template.RenderNamedTemplate(template.TmplConversationAssigned,
 		map[string]interface{}{
 			"conversation": map[string]string{
-				"subject": subject,
-				"uuid":    conversationUUID,
+				"subject":          conversation.Subject.String,
+				"uuid":             conversation.UUID,
+				"reference_number": conversation.ReferenceNumber,
+				"priority":         conversation.Priority.String,
+			},
+			"agent": map[string]string{
+				"full_name": agent.FullName(),
 			},
 		})
 	if err != nil {
-		m.lo.Error("error rendering template", "template", template.TmplConversationAssigned, "conversation_uuid", conversationUUID, "error", err)
+		m.lo.Error("error rendering template", "template", template.TmplConversationAssigned, "conversation_uuid", conversation.UUID, "error", err)
 		return fmt.Errorf("rendering template: %w", err)
 	}
 	nm := notifier.Message{
@@ -784,7 +765,7 @@ func (m *Manager) ApplyAction(action amodels.RuleAction, conversation models.Con
 
 // addConversationParticipant adds a user as participant to a conversation.
 func (c *Manager) addConversationParticipant(userID int, conversationUUID string) error {
-	if _, err := c.q.InsertConverstionParticipant.Exec(userID, conversationUUID); err != nil {
+	if _, err := c.q.InsertConversationParticipant.Exec(userID, conversationUUID); err != nil {
 		if !dbutil.IsUniqueViolationError(err) {
 			c.lo.Error("error adding conversation participant", "user_id", userID, "conversation_uuid", conversationUUID, "error", err)
 			return fmt.Errorf("adding conversation participant: %w", err)
diff --git a/internal/conversation/message.go b/internal/conversation/message.go
index fcbc4b8..fcfbc3c 100644
--- a/internal/conversation/message.go
+++ b/internal/conversation/message.go
@@ -49,25 +49,24 @@ const (
 
 // Run starts a pool of worker goroutines to handle message dispatching via inbox's channel and processes incoming messages. It scans for
 // pending outgoing messages at the specified read interval and pushes them to the outgoing queue.
-func (m *Manager) Run(ctx context.Context, dispatchConcurrency int, scanInterval time.Duration) {
+func (m *Manager) Run(ctx context.Context, incomingQWorkers, outgoingQWorkers, scanInterval time.Duration) {
 	dbScanner := time.NewTicker(scanInterval)
 	defer dbScanner.Stop()
 
-	// Spawn a worker goroutine pool to dispatch messages.
-	for range dispatchConcurrency {
+	for range outgoingQWorkers {
 		m.wg.Add(1)
 		go func() {
 			defer m.wg.Done()
 			m.MessageDispatchWorker(ctx)
 		}()
 	}
-
-	// Spawn a goroutine to process incoming messages.
-	m.wg.Add(1)
-	go func() {
-		defer m.wg.Done()
-		m.IncomingMessageWorker(ctx)
-	}()
+	for range incomingQWorkers {
+		m.wg.Add(1)
+		go func() {
+			defer m.wg.Done()
+			m.IncomingMessageWorker(ctx)
+		}()
+	}
 
 	// Scan pending outgoing messages and send them.
 	for {
diff --git a/internal/conversation/queries.sql b/internal/conversation/queries.sql
index 363d716..00bf086 100644
--- a/internal/conversation/queries.sql
+++ b/internal/conversation/queries.sql
@@ -11,36 +11,40 @@ RETURNING id, uuid;
 
 -- name: get-conversations
 SELECT
-    COUNT(*) OVER() AS total,
-    conversations.created_at,
-    conversations.updated_at,
-    conversations.uuid,
-    conversations.assignee_last_seen_at,
-    users.first_name as "contact.first_name",
-    users.last_name as "contact.last_name",
-    users.avatar_url as "contact.avatar_url",
-    inboxes.channel as inbox_channel,
-    inboxes.name as inbox_name,
-    conversations.sla_policy_id,
-    conversations.first_reply_at,
-    conversations.resolved_at,
-    conversations.subject,
-    conversations.last_message,
-    conversations.last_message_at,
-    conversations.next_sla_deadline_at,
-    conversations.priority_id,
-    (
-        SELECT COUNT(*)
-        FROM conversation_messages m
-        WHERE m.conversation_id = conversations.id AND m.created_at > conversations.assignee_last_seen_at
-    ) AS unread_message_count,
-    conversation_statuses.name as status,
-    conversation_priorities.name as priority
+COUNT(*) OVER() as total,
+conversations.created_at,
+conversations.updated_at,
+conversations.uuid,
+conversations.assignee_last_seen_at,
+users.first_name as "contact.first_name",
+users.last_name as "contact.last_name",
+users.avatar_url as "contact.avatar_url", 
+inboxes.channel as inbox_channel,
+inboxes.name as inbox_name,
+conversations.sla_policy_id,
+conversations.first_reply_at,
+conversations.resolved_at,
+conversations.subject,
+conversations.last_message,
+conversations.last_message_at,
+conversations.next_sla_deadline_at,
+conversations.priority_id,
+(
+  SELECT CASE WHEN COUNT(*) > 9 THEN 10 ELSE COUNT(*) END
+  FROM (
+    SELECT 1 FROM conversation_messages 
+    WHERE conversation_id = conversations.id 
+      AND created_at > conversations.assignee_last_seen_at
+    LIMIT 10
+  ) t
+) as unread_message_count,
+conversation_statuses.name as status,
+conversation_priorities.name as priority
 FROM conversations
-    JOIN users ON conversations.contact_id = users.id
-    JOIN inboxes ON conversations.inbox_id = inboxes.id
-    LEFT JOIN conversation_statuses ON conversations.status_id = conversation_statuses.id
-    LEFT JOIN conversation_priorities ON conversations.priority_id = conversation_priorities.id
+JOIN users ON contact_id = users.id
+JOIN inboxes ON inbox_id = inboxes.id  
+LEFT JOIN conversation_statuses ON status_id = conversation_statuses.id
+LEFT JOIN conversation_priorities ON priority_id = conversation_priorities.id
 WHERE 1=1 %s
 
 -- name: get-conversation
@@ -115,9 +119,6 @@ LEFT JOIN conversation_statuses s ON c.status_id = s.id
 LEFT JOIN conversation_priorities p ON c.priority_id = p.id
 WHERE c.created_at > $1;
 
--- name: get-conversation-id
-SELECT id from conversations where uuid = $1;
-
 -- name: get-conversation-uuid
 SELECT uuid from conversations where id = $1;
 
@@ -169,10 +170,11 @@ SET assignee_last_seen_at = now(),
     updated_at = now()
 WHERE uuid = $1;
 
--- name: update-conversation-meta
-UPDATE conversations 
-SET meta = meta || $3, updated_at = now()
-WHERE CASE WHEN $1 > 0 THEN id = $1 ELSE uuid = $2 END;
+-- name: update-conversation-last-message
+UPDATE conversations SET last_message = $3, last_message_at = $4 WHERE CASE 
+    WHEN $1 > 0 THEN id = $1
+    ELSE uuid = $2
+END
 
 -- name: get-conversation-participants
 SELECT users.id as id, first_name, last_name, avatar_url 
@@ -183,12 +185,6 @@ WHERE conversation_id =
     SELECT id FROM conversations WHERE uuid = $1
 );
 
--- name: update-conversation-last-message
-UPDATE conversations SET last_message = $3, last_message_at = $4 WHERE CASE 
-    WHEN $1 > 0 THEN id = $1
-    ELSE uuid = $2
-END
-
 -- name: insert-conversation-participant
 INSERT INTO conversation_participants
 (user_id, conversation_id)
@@ -196,30 +192,14 @@ VALUES($1, (SELECT id FROM conversations WHERE uuid = $2));
 
 -- name: get-unassigned-conversations
 SELECT
+    c.created_at,
     c.updated_at,
     c.uuid,
-    c.assignee_last_seen_at,
     c.assigned_team_id,
     inb.channel as inbox_channel,
-    inb.name as inbox_name,
-    ct.first_name,
-    ct.last_name,
-    ct.avatar_url,
-    c.subject,
-    c.last_message,
-    c.last_message_at,
-    (
-        SELECT COUNT(*)
-        FROM conversation_messages m
-        WHERE m.conversation_id = c.id AND m.created_at > c.assignee_last_seen_at
-    ) AS unread_message_count,
-    s.name as status,
-    p.name as priority
+    inb.name as inbox_name
 FROM conversations c
-    JOIN users ct ON c.contact_id = ct.id
     JOIN inboxes inb ON c.inbox_id = inb.id 
-    LEFT JOIN conversation_statuses s ON c.status_id = s.id
-    LEFT JOIN conversation_priorities p ON c.priority_id = p.id
 WHERE assigned_user_id IS NULL AND assigned_team_id IS NOT NULL;
 
 -- name: get-dashboard-counts
@@ -231,7 +211,7 @@ SELECT json_build_object(
 )
 FROM conversations c
 INNER JOIN conversation_statuses s ON c.status_id = s.id
-WHERE s.name = 'Open' AND 1=1 %s;
+WHERE s.name not in ('Resolved', 'Closed') AND 1=1 %s;
 
 -- name: get-dashboard-charts
 WITH new_conversations AS (
@@ -405,46 +385,36 @@ GROUP BY
 ORDER BY m.created_at;
 
 -- name: get-messages
-WITH conversation_id AS (
-    SELECT id
-    FROM conversations
-    WHERE uuid = $1
-    LIMIT 1
-),
-attachments AS (
-    SELECT 
-        model_id as message_id,
-        json_agg(
-            json_build_object(
-                'name', filename,
-                'content_type', content_type,
-                'uuid', uuid,
-                'size', size,
-                'content_id', content_id,
-                'disposition', disposition
-            ) ORDER BY filename
-        ) AS attachment_details
-    FROM media
-    WHERE model_type = 'messages'
-    GROUP BY message_id
-)
 SELECT
-    COUNT(*) OVER() AS total,
-    m.created_at,
-    m.updated_at,
-    m.status,
-    m.type,
-    m.content,
-    m.uuid,
-    m.private,
-    m.sender_id,
-    m.sender_type,
-    m.meta,
-    COALESCE(a.attachment_details, '[]'::json) AS attachments
+   COUNT(*) OVER() AS total,
+   m.created_at,
+   m.updated_at,
+   m.status,
+   m.type, 
+   m.content,
+   m.uuid,
+   m.private,
+   m.sender_id,
+   m.sender_type,
+   m.meta,
+   COALESCE(
+     (SELECT json_agg(
+       json_build_object(
+         'name', filename,
+         'content_type', content_type, 
+         'uuid', uuid,
+         'size', size,
+         'content_id', content_id,
+         'disposition', disposition
+       ) ORDER BY filename
+     ) FROM media 
+     WHERE model_type = 'messages' AND model_id = m.id),
+   '[]'::json) AS attachments
 FROM conversation_messages m
-LEFT JOIN attachments a ON a.message_id = m.id
-WHERE m.conversation_id = (SELECT id FROM conversation_id) ORDER BY m.created_at DESC
-%s
+WHERE m.conversation_id = (
+   SELECT id FROM conversations WHERE uuid = $1 LIMIT 1
+)
+ORDER BY m.created_at DESC %s
 
 -- name: insert-message
 WITH conversation_id AS (
diff --git a/internal/conversation/unsnoozer.go b/internal/conversation/unsnoozer.go
index 90246e4..97d2b2e 100644
--- a/internal/conversation/unsnoozer.go
+++ b/internal/conversation/unsnoozer.go
@@ -7,8 +7,8 @@ import (
 )
 
 // RunUnsnoozer runs the conversation unsnoozer.
-func (c *Manager) RunUnsnoozer(ctx context.Context) {
-	ticker := time.NewTicker(5 * time.Minute)
+func (c *Manager) RunUnsnoozer(ctx context.Context, unsnoozeInterval time.Duration) {
+	ticker := time.NewTicker(unsnoozeInterval)
 	defer ticker.Stop()
 	for {
 		select {
diff --git a/internal/inbox/inbox.go b/internal/inbox/inbox.go
index 3000f2b..0af0b57 100644
--- a/internal/inbox/inbox.go
+++ b/internal/inbox/inbox.go
@@ -162,7 +162,7 @@ func (m *Manager) GetAll() ([]imodels.Inbox, error) {
 
 // Create creates an inbox in the DB.
 func (m *Manager) Create(inbox imodels.Inbox) error {
-	if _, err := m.queries.InsertInbox.Exec(inbox.Channel, inbox.Config, inbox.Name, inbox.From); err != nil {
+	if _, err := m.queries.InsertInbox.Exec(inbox.Channel, inbox.Config, inbox.Name, inbox.From, inbox.CSATEnabled); err != nil {
 		m.lo.Error("error creating inbox", "error", err)
 		return envelope.NewError(envelope.GeneralError, "Error creating inbox", nil)
 	}
@@ -300,7 +300,7 @@ func (m *Manager) Update(id int, inbox imodels.Inbox) error {
 		inbox.Config = updatedConfig
 	}
 
-	if _, err := m.queries.Update.Exec(id, inbox.Channel, inbox.Config, inbox.Name, inbox.From); err != nil {
+	if _, err := m.queries.Update.Exec(id, inbox.Channel, inbox.Config, inbox.Name, inbox.From, inbox.CSATEnabled); err != nil {
 		m.lo.Error("error updating inbox", "error", err)
 		return envelope.NewError(envelope.GeneralError, "Error updating inbox", nil)
 	}
diff --git a/internal/inbox/queries.sql b/internal/inbox/queries.sql
index a11f635..d541f6e 100644
--- a/internal/inbox/queries.sql
+++ b/internal/inbox/queries.sql
@@ -6,15 +6,15 @@ SELECT id, name, channel, disabled, updated_at from inboxes where deleted_at is
 
 -- name: insert-inbox
 INSERT INTO inboxes
-(channel, config, "name", "from")
-VALUES($1, $2, $3, $4);
+(channel, config, "name", "from", csat_enabled)
+VALUES($1, $2, $3, $4, $5)
 
 -- name: get-inbox
 SELECT * from inboxes where id = $1 and deleted_at is NULL;
 
 -- name: update
 UPDATE inboxes
-set channel = $2, config = $3, "name" = $4, "from" = $5, updated_at = now()
+set channel = $2, config = $3, "name" = $4, "from" = $5, csat_enabled = $6, updated_at = now()
 where id = $1 and deleted_at is NULL;
 
 -- name: soft-delete
diff --git a/internal/media/media.go b/internal/media/media.go
index 1b15119..3cd6a01 100644
--- a/internal/media/media.go
+++ b/internal/media/media.go
@@ -197,14 +197,14 @@ func (m *Manager) DeleteByUUID(uuid string) error {
 	return nil
 }
 
-// DeleteUnlinkedMessageMedia is a blocking function that periodically deletes media files that are not linked to any conversation message.
-func (m *Manager) DeleteUnlinkedMessageMedia(ctx context.Context) {
+// DeleteUnlinkedMedia is a blocking function that periodically deletes media files that are not linked to any conversation message.
+func (m *Manager) DeleteUnlinkedMedia(ctx context.Context) {
 	m.deleteUnlinkedMessageMedia()
 	for {
 		select {
 		case <-ctx.Done():
 			return
-		case <-time.After(24 * time.Hour):
+		case <-time.After(2 * time.Hour):
 			m.lo.Info("deleting unlinked message media")
 			if err := m.deleteUnlinkedMessageMedia(); err != nil {
 				m.lo.Error("error deleting unlinked media", "error", err)