package service

import (
	"context"
	"fmt"
	"log"
	"time"

	"eslogad-be/internal/appcontext"
	"eslogad-be/internal/constant"
	"eslogad-be/internal/contract"
	"eslogad-be/internal/entities"
	"eslogad-be/internal/processor"
	"eslogad-be/internal/repository"
	"eslogad-be/internal/transformer"

	"github.com/google/uuid"
)

const (
	DefaultIncomingLetterID = "ESLI"
)

type LetterProcessor interface {
	CreateIncomingLetter(ctx context.Context, req *contract.CreateIncomingLetterRequest) (*contract.IncomingLetterResponse, error)
	GetIncomingLetterByID(ctx context.Context, id uuid.UUID) (*contract.IncomingLetterResponse, error)
	ListIncomingLetters(ctx context.Context, filter repository.ListIncomingLettersFilter, page, limit int) ([]entities.LetterIncoming, int64, error)
	GetLetterUnreadCounts(ctx context.Context) (*contract.LetterUnreadCountResponse, error)
	MarkIncomingLetterAsRead(ctx context.Context, letterID uuid.UUID) (*contract.MarkLetterReadResponse, error)
	MarkOutgoingLetterAsRead(ctx context.Context, letterID uuid.UUID) (*contract.MarkLetterReadResponse, error)
	UpdateIncomingLetter(ctx context.Context, id uuid.UUID, req *contract.UpdateIncomingLetterRequest) (*contract.IncomingLetterResponse, error)
	SoftDeleteIncomingLetter(ctx context.Context, id uuid.UUID) error
	BulkArchiveIncomingLetters(ctx context.Context, letterIDs []uuid.UUID) (int64, error)
	BulkArchiveIncomingLettersForUser(ctx context.Context, letterIDs []uuid.UUID, userID uuid.UUID) (int64, error)

	// Batch loading methods
	GetBatchAttachments(ctx context.Context, letterIDs []uuid.UUID) (map[uuid.UUID][]entities.LetterIncomingAttachment, error)
	GetBatchPriorities(ctx context.Context, priorityIDs []uuid.UUID) (map[uuid.UUID]*entities.Priority, error)
	GetBatchInstitutions(ctx context.Context, institutionIDs []uuid.UUID) (map[uuid.UUID]*entities.Institution, error)
	GetBatchRecipientsByUser(ctx context.Context, letterIDs []uuid.UUID, userID uuid.UUID) (map[uuid.UUID]*entities.LetterIncomingRecipient, error)
	CountUnreadByUser(ctx context.Context, userID uuid.UUID) (int, error)

	CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error)
	GetEnhancedDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListEnhancedDispositionsResponse, error)

	CreateDiscussion(ctx context.Context, letterID uuid.UUID, req *contract.CreateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error)
	UpdateDiscussion(ctx context.Context, letterID uuid.UUID, discussionID uuid.UUID, req *contract.UpdateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, string, error)

	GetDepartmentDispositionStatus(ctx context.Context, req *contract.GetDepartmentDispositionStatusRequest) (*contract.ListDepartmentDispositionStatusResponse, error)
	UpdateDispositionStatus(ctx context.Context, req *contract.UpdateDispositionStatusRequest) (*contract.DepartmentDispositionStatusResponse, error)

	GetLetterCTA(ctx context.Context, letterID uuid.UUID, departmentID uuid.UUID) (*contract.LetterCTAResponse, error)
}

type LetterServiceImpl struct {
	processor                  LetterProcessor
	txManager                  *repository.TxManager
	numberGenerator            NumberGenerator
	recipientProcessor         RecipientProcessor
	activityLogger             ActivityLogger
	letterDispositionProcessor LetterDispositionProcessor
	notificationProcessor      processor.NotificationProcessor
	activityProcessor          ActivityLogger
}

type NumberGenerator interface {
	GenerateNumber(ctx context.Context, prefixKey, sequenceKey, defaultPrefix string) (string, error)
}

type RecipientProcessor interface {
	CreateDefaultRecipients(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingRecipient, error)
	CreateRecipients(ctx context.Context, letterID uuid.UUID, departmentIDs []uuid.UUID) ([]entities.LetterIncomingRecipient, error)
	CreateSingleRecipient(ctx context.Context, recipient *entities.LetterIncomingRecipient) error
}

type ActivityLogger interface {
	LogLetterCreated(ctx context.Context, letterID uuid.UUID, userID uuid.UUID, letterNumber string) error
	LogAttachmentUploaded(ctx context.Context, letterID uuid.UUID, userID uuid.UUID, fileName string, fileType string) error
	LogLetterDispositionStatusUpdate(ctx context.Context, letterID uuid.UUID, userID uuid.UUID, status string) error
}

type LetterDispositionProcessor interface {
	CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error)
}

func NewLetterService(
	processor LetterProcessor,
	txManager *repository.TxManager,
	numberGenerator NumberGenerator,
	recipientProcessor RecipientProcessor,
	activityLogger ActivityLogger,
	letterDispositionProcessor LetterDispositionProcessor,
	notificationProcessor processor.NotificationProcessor,
	activityProc ActivityLogger,
) *LetterServiceImpl {
	return &LetterServiceImpl{
		processor:                  processor,
		txManager:                  txManager,
		numberGenerator:            numberGenerator,
		recipientProcessor:         recipientProcessor,
		activityLogger:             activityLogger,
		letterDispositionProcessor: letterDispositionProcessor,
		notificationProcessor:      notificationProcessor,
		activityProcessor:          activityProc,
	}
}

func (s *LetterServiceImpl) CreateIncomingLetter(ctx context.Context, req *contract.CreateIncomingLetterRequest) (*contract.IncomingLetterResponse, error) {
	var result *contract.IncomingLetterResponse
	var recipients []entities.LetterIncomingRecipient

	err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
		letterNumber, err := s.generateLetterNumber(txCtx)
		if err != nil {
			return err
		}
		req.LetterNumber = letterNumber

		result, err = s.processor.CreateIncomingLetter(txCtx, req)
		if err != nil {
			return err
		}

		recipients, err = s.createDefaultRecipients(txCtx, result.ID)
		if err != nil {
			return err
		}

		if err := s.createDispositionsForRecipients(txCtx, result.ID, recipients); err != nil {
			return err
		}

		s.logLetterCreation(txCtx, result.ID, letterNumber)

		return nil
	})

	if err != nil {
		return nil, err
	}

	if s.notificationProcessor != nil && len(recipients) > 0 {
		go s.sendLetterNotifications(context.Background(), result, recipients)
	}

	return result, nil
}

func (s *LetterServiceImpl) generateLetterNumber(ctx context.Context) (string, error) {
	return s.numberGenerator.GenerateNumber(
		ctx,
		contract.SettingIncomingLetterPrefix,
		contract.SettingIncomingLetterSequence,
		DefaultIncomingLetterID,
	)
}

func (s *LetterServiceImpl) createDefaultRecipients(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingRecipient, error) {
	return s.recipientProcessor.CreateDefaultRecipients(ctx, letterID)
}

func (s *LetterServiceImpl) createDispositionsForRecipients(ctx context.Context, letterID uuid.UUID, recipients []entities.LetterIncomingRecipient) error {
	if len(recipients) == 0 || s.letterDispositionProcessor == nil {
		return nil
	}

	departmentIDs := s.extractUniqueDepartmentIDs(recipients)
	if len(departmentIDs) == 0 {
		return nil
	}

	systemDeptID := constant.SystemDepartmentID
	systemUserID := constant.SystemUserID

	dispositionReq := &contract.CreateLetterDispositionRequest{
		FromDepartment:  systemDeptID,
		LetterID:        letterID,
		ToDepartmentIDs: departmentIDs,
		Notes:           nil,
		CreatedBy:       systemUserID,
	}

	_, err := s.letterDispositionProcessor.CreateDispositions(ctx, dispositionReq)
	return err
}

func (s *LetterServiceImpl) extractUniqueDepartmentIDs(recipients []entities.LetterIncomingRecipient) []uuid.UUID {
	deptMap := make(map[uuid.UUID]bool)
	var departmentIDs []uuid.UUID

	for _, recipient := range recipients {
		if recipient.RecipientDepartmentID != nil && !deptMap[*recipient.RecipientDepartmentID] {
			deptMap[*recipient.RecipientDepartmentID] = true
			departmentIDs = append(departmentIDs, *recipient.RecipientDepartmentID)
		}
	}

	return departmentIDs
}

func (s *LetterServiceImpl) logLetterCreation(ctx context.Context, letterID uuid.UUID, letterNumber string) {
	if s.activityLogger == nil {
		return
	}

	userID := appcontext.FromGinContext(ctx).UserID
	err := s.activityLogger.LogLetterCreated(ctx, letterID, userID, letterNumber)
	if err != nil {
		// Log error but don't fail the operation
	}
}

func (s *LetterServiceImpl) addCreatorAsRecipient(ctx context.Context, letterID uuid.UUID, creatorID uuid.UUID) (*entities.LetterIncomingRecipient, error) {
	// Check if creator is already a recipient (to avoid duplicates)
	existingRecipients, err := s.processor.GetBatchRecipientsByUser(ctx, []uuid.UUID{letterID}, creatorID)
	if err != nil {
		return nil, err
	}

	// If creator is already a recipient, skip
	if _, exists := existingRecipients[letterID]; exists {
		return nil, nil
	}

	// Create recipient entry for the creator
	recipient := entities.LetterIncomingRecipient{
		ID:              uuid.New(),
		LetterID:        letterID,
		RecipientUserID: &creatorID,
		Status:          entities.RecipientStatusNew,
		CreatedAt:       time.Now(),
	}

	// Save the recipient
	if err := s.recipientProcessor.CreateSingleRecipient(ctx, &recipient); err != nil {
		// Failed to add creator as recipient
		return nil, err
	}

	return &recipient, nil
}

func (s *LetterServiceImpl) sendLetterNotifications(ctx context.Context, letter *contract.IncomingLetterResponse, recipients []entities.LetterIncomingRecipient) {
	for _, recipient := range recipients {
		if recipient.Status != "completed" {
			err := s.notificationProcessor.SendIncomingLetterNotification(
				ctx,
				letter.ID,
				*recipient.RecipientUserID,
				"Surat Masuk",
				fmt.Sprintf("%s: %s", letter.SenderInstitution.Name, letter.Subject))

			if err != nil {
				// Failed to send notification, continue anyway
			}
		}
	}
}

func (s *LetterServiceImpl) sendDispositionNotifications(ctx context.Context, letterID uuid.UUID, recipients []entities.LetterIncomingRecipient) {
	// Get letter details for notification
	appContext := appcontext.FromGinContext(ctx)
	letter, err := s.processor.GetIncomingLetterByID(ctx, letterID)
	if err != nil {
		return
	}

	for _, recipient := range recipients {
		if recipient.RecipientUserID != nil && recipient.Status != entities.RecipientStatusCompleted {
			subject := "Surat Masuk"
			message := fmt.Sprintf("Disposisi surat dari %s: %s", appContext.UserName, letter.Subject)

			err := s.notificationProcessor.SendIncomingLetterNotification(
				ctx,
				letterID,
				*recipient.RecipientUserID,
				subject,
				message)

			if err != nil {
				// Failed to send notification, continue anyway
			}
		}
	}
}

func (s *LetterServiceImpl) GetIncomingLetterByID(ctx context.Context, id uuid.UUID) (*contract.IncomingLetterResponse, error) {
	return s.processor.GetIncomingLetterByID(ctx, id)
}
func (s *LetterServiceImpl) ListIncomingLetters(ctx context.Context, req *contract.ListIncomingLettersRequest) (*contract.ListIncomingLettersResponse, error) {
	appCtx := appcontext.FromGinContext(ctx)
	userID := appCtx.UserID
	departmentID := appCtx.DepartmentID

	filter := repository.ListIncomingLettersFilter{
		Status:          req.Status,
		Query:           req.Query,
		DepartmentID:    &departmentID,
		UserID:          &userID,
		IsRead:          req.IsRead,
		PriorityIDs:     req.PriorityIDs,
		IsDispositioned: req.IsDispositioned,
		IsArchived:      req.IsArchived,
	}

	letters, total, err := s.processor.ListIncomingLetters(ctx, filter, req.Page, req.Limit)
	if err != nil {
		return nil, err
	}

	if len(letters) == 0 {
		return &contract.ListIncomingLettersResponse{
			Letters:     []contract.IncomingLetterResponse{},
			Pagination:  transformer.CreatePaginationResponse(int(total), req.Page, req.Limit),
			TotalUnread: 0,
		}, nil
	}

	letterIDs := make([]uuid.UUID, 0, len(letters))
	priorityIDSet := make(map[uuid.UUID]bool)
	institutionIDSet := make(map[uuid.UUID]bool)

	for _, letter := range letters {
		letterIDs = append(letterIDs, letter.ID)
		if letter.PriorityID != nil {
			priorityIDSet[*letter.PriorityID] = true
		}
		if letter.SenderInstitutionID != nil {
			institutionIDSet[*letter.SenderInstitutionID] = true
		}
	}

	priorityIDs := make([]uuid.UUID, 0, len(priorityIDSet))
	for id := range priorityIDSet {
		priorityIDs = append(priorityIDs, id)
	}

	institutionIDs := make([]uuid.UUID, 0, len(institutionIDSet))
	for id := range institutionIDSet {
		institutionIDs = append(institutionIDs, id)
	}

	type batchResult struct {
		attachments  map[uuid.UUID][]entities.LetterIncomingAttachment
		priorities   map[uuid.UUID]*entities.Priority
		institutions map[uuid.UUID]*entities.Institution
		recipients   map[uuid.UUID]*entities.LetterIncomingRecipient
		err          error
	}

	resultChan := make(chan batchResult, 1)

	go func() {
		result := batchResult{
			attachments:  make(map[uuid.UUID][]entities.LetterIncomingAttachment),
			priorities:   make(map[uuid.UUID]*entities.Priority),
			institutions: make(map[uuid.UUID]*entities.Institution),
			recipients:   make(map[uuid.UUID]*entities.LetterIncomingRecipient),
		}

		errChan := make(chan error, 4)

		go func() {
			var err error
			result.attachments, err = s.processor.GetBatchAttachments(ctx, letterIDs)
			errChan <- err
		}()

		go func() {
			var err error
			result.priorities, err = s.processor.GetBatchPriorities(ctx, priorityIDs)
			errChan <- err
		}()

		go func() {
			var err error
			result.institutions, err = s.processor.GetBatchInstitutions(ctx, institutionIDs)
			errChan <- err
		}()

		go func() {
			var err error
			result.recipients, err = s.processor.GetBatchRecipientsByUser(ctx, letterIDs, userID)
			errChan <- err
		}()

		for i := 0; i < 4; i++ {
			if err := <-errChan; err != nil {
				// Batch load error, continue anyway
			}
		}

		resultChan <- result
	}()

	batchData := <-resultChan

	respList := make([]contract.IncomingLetterResponse, 0, len(letters))
	for _, letter := range letters {
		attachments := batchData.attachments[letter.ID]
		if attachments == nil {
			attachments = []entities.LetterIncomingAttachment{}
		}

		var priority *entities.Priority
		if letter.PriorityID != nil {
			priority = batchData.priorities[*letter.PriorityID]
		}

		var institution *entities.Institution
		if letter.SenderInstitutionID != nil {
			institution = batchData.institutions[*letter.SenderInstitutionID]
		}

		isRead := false
		if recipient, exists := batchData.recipients[letter.ID]; exists && recipient != nil {
			isRead = recipient.ReadAt != nil
		}

		resp := transformer.LetterEntityToContract(&letter, attachments, priority, institution)
		resp.IsRead = isRead
		respList = append(respList, *resp)
	}

	totalUnread, _ := s.processor.CountUnreadByUser(ctx, userID)

	return &contract.ListIncomingLettersResponse{
		Letters:     respList,
		Pagination:  transformer.CreatePaginationResponse(int(total), req.Page, req.Limit),
		TotalUnread: totalUnread,
	}, nil
}

func (s *LetterServiceImpl) GetLetterUnreadCounts(ctx context.Context) (*contract.LetterUnreadCountResponse, error) {
	return s.processor.GetLetterUnreadCounts(ctx)
}

func (s *LetterServiceImpl) MarkIncomingLetterAsRead(ctx context.Context, letterID uuid.UUID) (*contract.MarkLetterReadResponse, error) {
	return s.processor.MarkIncomingLetterAsRead(ctx, letterID)
}
func (s *LetterServiceImpl) MarkOutgoingLetterAsRead(ctx context.Context, letterID uuid.UUID) (*contract.MarkLetterReadResponse, error) {
	return s.processor.MarkOutgoingLetterAsRead(ctx, letterID)
}
func (s *LetterServiceImpl) UpdateIncomingLetter(ctx context.Context, id uuid.UUID, req *contract.UpdateIncomingLetterRequest) (*contract.IncomingLetterResponse, error) {
	return s.processor.UpdateIncomingLetter(ctx, id, req)
}
func (s *LetterServiceImpl) SoftDeleteIncomingLetter(ctx context.Context, id uuid.UUID) error {
	return s.processor.SoftDeleteIncomingLetter(ctx, id)
}

func (s *LetterServiceImpl) CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error) {
	log.Printf("[DEBUG] CreateDispositions START - LetterID: %s\n", req.LetterID.String())
	userID := appcontext.FromGinContext(ctx).UserID
	req.CreatedBy = userID

	if req.FromDepartment == uuid.Nil {
		req.FromDepartment = appcontext.FromGinContext(ctx).DepartmentID
	}

	var result *contract.ListDispositionsResponse
	var recipients []entities.LetterIncomingRecipient

	err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
		var err error
		result, err = s.processor.CreateDispositions(txCtx, req)
		if err != nil {
			return err
		}

		if len(req.ToDepartmentIDs) > 0 && s.recipientProcessor != nil {
			recipients, err = s.recipientProcessor.CreateRecipients(txCtx, req.LetterID, req.ToDepartmentIDs)
			if err != nil {
				return err
			}
		}

		if s.activityLogger != nil && result != nil && len(result.Dispositions) > 0 {
			if err := s.activityLogger.LogLetterDispositionStatusUpdate(txCtx, req.LetterID, userID, "disposition_created"); err != nil {

			}
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	// Send notifications to newly created recipients asynchronously
	if s.notificationProcessor != nil {
		// Send notifications to newly created recipients
		if len(recipients) > 0 {
			go s.sendDispositionNotifications(context.Background(), req.LetterID, recipients)
		}
		
		// Send notification to letter creator about new disposition
		go s.sendDispositionCreatorNotification(context.Background(), req.LetterID, userID)
	}

	return result, nil
}

func (s *LetterServiceImpl) GetEnhancedDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListEnhancedDispositionsResponse, error) {
	return s.processor.GetEnhancedDispositionsByLetter(ctx, letterID)
}

func (s *LetterServiceImpl) CreateDiscussion(ctx context.Context, letterID uuid.UUID, req *contract.CreateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error) {
	userID := appcontext.FromGinContext(ctx).UserID
	
	var result *contract.LetterDiscussionResponse
	err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
		var err error
		result, err = s.processor.CreateDiscussion(txCtx, letterID, req)
		if err != nil {
			return err
		}
		
		// Log activity for discussion creation
		if s.activityLogger != nil && result != nil {
			if err := s.activityLogger.LogLetterDispositionStatusUpdate(txCtx, letterID, userID, "discussion_created"); err != nil {
				// Don't fail the transaction for logging errors
			}
		}
		
		return nil
	})
	
	if err != nil {
		return nil, err
	}
	
	// Send notifications to mentioned users asynchronously
	if s.notificationProcessor != nil && req.Mentions != nil {
		go s.sendDiscussionMentionNotifications(context.Background(), letterID, userID, req.Mentions, req.Message)
	}
	
	return result, nil
}

func (s *LetterServiceImpl) UpdateDiscussion(ctx context.Context, letterID uuid.UUID, discussionID uuid.UUID, req *contract.UpdateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error) {
	userID := appcontext.FromGinContext(ctx).UserID
	
	var result *contract.LetterDiscussionResponse
	
	err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
		var err error
		var oldMessage string
		result, oldMessage, err = s.processor.UpdateDiscussion(txCtx, letterID, discussionID, req)
		if err != nil {
			return err
		}
		
		// Log activity for discussion update (could use oldMessage for more detailed logging)
		if s.activityLogger != nil && result != nil {
			// Create a simple activity log - oldMessage could be included in a more detailed log
			_ = oldMessage // Mark as intentionally unused for now
			if err := s.activityLogger.LogLetterDispositionStatusUpdate(txCtx, letterID, userID, "discussion_updated"); err != nil {
				// Don't fail the transaction for logging errors
			}
		}
		
		return nil
	})
	
	if err != nil {
		return nil, err
	}
	
	return result, nil
}

func (s *LetterServiceImpl) GetDepartmentDispositionStatus(ctx context.Context, req *contract.GetDepartmentDispositionStatusRequest) (*contract.ListDepartmentDispositionStatusResponse, error) {
	return s.processor.GetDepartmentDispositionStatus(ctx, req)
}

func (s *LetterServiceImpl) UpdateDispositionStatus(ctx context.Context, req *contract.UpdateDispositionStatusRequest) (*contract.DepartmentDispositionStatusResponse, error) {
	// For now, delegate to the processor which handles this
	// The processor needs to be refactored to remove context extraction
	return s.processor.UpdateDispositionStatus(ctx, req)
}

func (s *LetterServiceImpl) GetLetterCTA(ctx context.Context, letterID uuid.UUID) (*contract.LetterCTAResponse, error) {
	departmentID := appcontext.FromGinContext(ctx).DepartmentID
	return s.processor.GetLetterCTA(ctx, letterID, departmentID)
}

func (s *LetterServiceImpl) BulkArchiveIncomingLetters(ctx context.Context, letterIDs []uuid.UUID) (*contract.BulkArchiveLettersResponse, error) {
	// Extract user context to archive only for the current user
	appCtx := appcontext.FromGinContext(ctx)
	userID := appCtx.UserID

	// Archive letters only for the current user
	archivedCount, err := s.processor.BulkArchiveIncomingLettersForUser(ctx, letterIDs, userID)
	if err != nil {
		return nil, err
	}

	return &contract.BulkArchiveLettersResponse{
		Success:       true,
		Message:       "Letters archived successfully",
		ArchivedCount: int(archivedCount),
	}, nil
}

func (s *LetterServiceImpl) sendDiscussionMentionNotifications(ctx context.Context, letterID uuid.UUID, senderUserID uuid.UUID, mentions map[string]interface{}, message string) {
	// Extract user_ids from mentions
	userIDs := s.extractUserIDsFromMentions(mentions)
	if len(userIDs) == 0 {
		return
	}
	
	// Get letter details for notification
	letter, err := s.processor.GetIncomingLetterByID(ctx, letterID)
	if err != nil {
		return
	}
	
	// Get sender user name (you might need to implement this)
	appContext := appcontext.FromGinContext(ctx)
	senderName := appContext.UserName // or get from user service
	
	// Send notification to each mentioned user
	for _, mentionedUserID := range userIDs {
		// Don't send notification to the sender themselves
		if mentionedUserID == senderUserID {
			continue
		}
		
		subject := "Anda Disebutkan dalam Diskusi"
		notificationMessage := fmt.Sprintf("%s menyebutkan Anda dalam diskusi surat: %s", senderName, letter.Subject)
		
		err := s.notificationProcessor.SendIncomingLetterNotification(
			ctx,
			letterID,
			mentionedUserID,
			subject,
			notificationMessage)
		
		if err != nil {
			// Log error but continue with other notifications
		}
	}
}

func (s *LetterServiceImpl) extractUserIDsFromMentions(mentions map[string]interface{}) []uuid.UUID {
	userIDs := make([]uuid.UUID, 0)
	
	if userIDsInterface, exists := mentions["user_ids"]; exists {
		switch userIDsValue := userIDsInterface.(type) {
		case []interface{}:
			for _, userIDInterface := range userIDsValue {
				if userIDStr, ok := userIDInterface.(string); ok {
					if userID, err := uuid.Parse(userIDStr); err == nil {
						userIDs = append(userIDs, userID)
					}
				}
			}
		case []string:
			for _, userIDStr := range userIDsValue {
				if userID, err := uuid.Parse(userIDStr); err == nil {
					userIDs = append(userIDs, userID)
				}
			}
		}
	}
	
	return userIDs
}

func (s *LetterServiceImpl) sendDispositionCreatorNotification(ctx context.Context, letterID uuid.UUID, dispositionCreatorID uuid.UUID) {
	// Get letter details
	letter, err := s.processor.GetIncomingLetterByID(ctx, letterID)
	if err != nil {
		return
	}

	fmt.Printf("[DEBUG] Starting sendDispositionCreatorNotification for letterID: %s\n", letterID.String())
	fmt.Printf("[DEBUG] Successfully retrieved letter: %s\n", letter.Subject)
	fmt.Printf("[DEBUG] Successfully retrieved letter: %s\n", letter.CreatedBy)
	
	

	letterCreatorID := letter.CreatedBy

	// Don't send notification if the disposition creator is the same as letter creator
	if letterCreatorID == dispositionCreatorID {
		return
	}

	// Get disposition creator name from context
	appContext := appcontext.FromGinContext(ctx)
	dispositionCreatorName := appContext.UserName

	subject := "Disposisi Baru pada Surat Anda"
	message := fmt.Sprintf("Surat yang Anda buat telah didisposisikan oleh %s: %s", 
		dispositionCreatorName, letter.Subject)

	err = s.notificationProcessor.SendIncomingLetterNotification(
		ctx,
		letterID,
		letterCreatorID,
		subject,
		message)

	if err != nil {
		// Log error but don't fail the operation
		// You might want to add proper logging here
	}
}