package app

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/message"
)

func (store *Store) HideDMChannelForUser(ctx context.Context, userID string, workspaceID string, channelID string) (message.DMChannel, error) {
	dmAccess, err := store.loadAuthorizedHumanDMAccess(ctx, store.db, userID, workspaceID, channelID, dmReadAction)
	if err != nil {
		return message.DMChannel{}, err
	}

	var result message.DMChannel
	if err := coredb.WithTx(ctx, store.db, func(tx coredb.Tx) error {
		if _, err := store.ensureDMScopeProjection(ctx, tx, dmAccess.DMThreadID); err != nil {
			return err
		}

		latestSeq, err := loadDMScopeLatestSeq(ctx, tx, dmAccess.DMThreadID)
		if err != nil {
			return err
		}

		now := time.Now().UTC()
		if _, err := tx.Exec(ctx, `
INSERT INTO dm_view_states (dm_thread_id, member_id, hidden_through_seq, updated_at)
VALUES ($1, $2, $3, $4)
ON DUPLICATE KEY UPDATE hidden_through_seq = VALUES(hidden_through_seq), updated_at = VALUES(updated_at)
`, dmAccess.DMThreadID, dmAccess.WorkspaceMember.Member.ID, latestSeq, now); err != nil {
			return fmt.Errorf("upsert dm view state: %w", err)
		}

		dm, err := message.LoadDMChannelByID(ctx, tx, workspaceID, dmAccess.WorkspaceMember.Member.ID, dmAccess.DMThreadID)
		if err != nil {
			return mapMessagingError(err)
		}
		result = dm
		return nil
	}); err != nil {
		return message.DMChannel{}, err
	}

	return result, nil
}

func loadDMScopeLatestSeq(ctx context.Context, queryer coredb.QueryRower, dmThreadID string) (int64, error) {
	trimmedDMThreadID := strings.TrimSpace(dmThreadID)
	if trimmedDMThreadID == "" {
		return 0, fmt.Errorf("dm thread id is required")
	}

	row := queryer.QueryRow(ctx, `
SELECT latest_seq
FROM scopes
WHERE id = $1
  AND type = 'dm'
`, trimmedDMThreadID)

	var latestSeq int64
	if err := row.Scan(&latestSeq); err != nil {
		if coredb.IsNotFound(err) {
			return 0, ErrNotFound
		}
		return 0, fmt.Errorf("load dm scope latest seq: %w", err)
	}
	return latestSeq, nil
}
