package sqlite

import (
	"context"
	"fmt"

	"github.com/steveyegge/beads/internal/types"
)

// AddIssueComment adds a comment to an issue
func (s *SQLiteStorage) AddIssueComment(ctx context.Context, issueID, author, text string) (*types.Comment, error) {
	// Verify issue exists
	var exists bool
	err := s.db.QueryRowContext(ctx, `SELECT EXISTS(SELECT 1 FROM issues WHERE id = ?)`, issueID).Scan(&exists)
	if err != nil {
		return nil, fmt.Errorf("failed to check issue existence: %w", err)
	}
	if !exists {
		return nil, fmt.Errorf("issue %s not found", issueID)
	}

	// Insert comment
	result, err := s.db.ExecContext(ctx, `
		INSERT INTO comments (issue_id, author, text, created_at)
		VALUES (?, ?, ?, CURRENT_TIMESTAMP)
	`, issueID, author, text)
	if err != nil {
		return nil, fmt.Errorf("failed to insert comment: %w", err)
	}

	// Get the inserted comment ID
	commentID, err := result.LastInsertId()
	if err != nil {
		return nil, fmt.Errorf("failed to get comment ID: %w", err)
	}

	// Fetch the complete comment
	comment := &types.Comment{}
	err = s.db.QueryRowContext(ctx, `
		SELECT id, issue_id, author, text, created_at
		FROM comments WHERE id = ?
	`, commentID).Scan(&comment.ID, &comment.IssueID, &comment.Author, &comment.Text, &comment.CreatedAt)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch comment: %w", err)
	}

	// Mark issue as dirty for JSONL export
	if err := s.MarkIssueDirty(ctx, issueID); err != nil {
		return nil, fmt.Errorf("failed to mark issue dirty: %w", err)
	}

	return comment, nil
}

// ImportIssueComment adds a comment during import, preserving the original timestamp.
// Unlike AddIssueComment which uses CURRENT_TIMESTAMP, this method uses the provided
// createdAt time from the JSONL file. This prevents timestamp drift during sync cycles.
// GH#735: Comment created_at timestamps were being overwritten with current time during import.
func (s *SQLiteStorage) ImportIssueComment(ctx context.Context, issueID, author, text string, createdAt string) (*types.Comment, error) {
	// Verify issue exists
	var exists bool
	err := s.db.QueryRowContext(ctx, `SELECT EXISTS(SELECT 1 FROM issues WHERE id = ?)`, issueID).Scan(&exists)
	if err != nil {
		return nil, fmt.Errorf("failed to check issue existence: %w", err)
	}
	if !exists {
		return nil, fmt.Errorf("issue %s not found", issueID)
	}

	// Insert comment with provided timestamp
	result, err := s.db.ExecContext(ctx, `
		INSERT INTO comments (issue_id, author, text, created_at)
		VALUES (?, ?, ?, ?)
	`, issueID, author, text, createdAt)
	if err != nil {
		return nil, fmt.Errorf("failed to insert comment: %w", err)
	}

	// Get the inserted comment ID
	commentID, err := result.LastInsertId()
	if err != nil {
		return nil, fmt.Errorf("failed to get comment ID: %w", err)
	}

	// Fetch the complete comment
	comment := &types.Comment{}
	err = s.db.QueryRowContext(ctx, `
		SELECT id, issue_id, author, text, created_at
		FROM comments WHERE id = ?
	`, commentID).Scan(&comment.ID, &comment.IssueID, &comment.Author, &comment.Text, &comment.CreatedAt)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch comment: %w", err)
	}

	// Mark issue as dirty for JSONL export
	if err := s.MarkIssueDirty(ctx, issueID); err != nil {
		return nil, fmt.Errorf("failed to mark issue dirty: %w", err)
	}

	return comment, nil
}

// GetIssueComments retrieves all comments for an issue
func (s *SQLiteStorage) GetIssueComments(ctx context.Context, issueID string) ([]*types.Comment, error) {
	rows, err := s.db.QueryContext(ctx, `
		SELECT id, issue_id, author, text, created_at
		FROM comments
		WHERE issue_id = ?
		ORDER BY created_at ASC
	`, issueID)
	if err != nil {
		return nil, fmt.Errorf("failed to query comments: %w", err)
	}
	defer func() { _ = rows.Close() }()

	var comments []*types.Comment
	for rows.Next() {
		comment := &types.Comment{}
		err := rows.Scan(&comment.ID, &comment.IssueID, &comment.Author, &comment.Text, &comment.CreatedAt)
		if err != nil {
			return nil, fmt.Errorf("failed to scan comment: %w", err)
		}
		comments = append(comments, comment)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating comments: %w", err)
	}

	return comments, nil
}

// GetCommentsForIssues fetches comments for multiple issues in a single query
// Returns a map of issue_id -> []*Comment
func (s *SQLiteStorage) GetCommentsForIssues(ctx context.Context, issueIDs []string) (map[string][]*types.Comment, error) {
	if len(issueIDs) == 0 {
		return make(map[string][]*types.Comment), nil
	}

	// Build placeholders for IN clause
	placeholders := make([]interface{}, len(issueIDs))
	for i, id := range issueIDs {
		placeholders[i] = id
	}

	query := fmt.Sprintf(`
		SELECT id, issue_id, author, text, created_at
		FROM comments
		WHERE issue_id IN (%s)
		ORDER BY issue_id, created_at ASC
	`, buildPlaceholders(len(issueIDs))) // #nosec G201 -- placeholders are generated internally

	rows, err := s.db.QueryContext(ctx, query, placeholders...)
	if err != nil {
		return nil, fmt.Errorf("failed to batch get comments: %w", err)
	}
	defer func() { _ = rows.Close() }()

	result := make(map[string][]*types.Comment)
	for rows.Next() {
		comment := &types.Comment{}
		err := rows.Scan(&comment.ID, &comment.IssueID, &comment.Author, &comment.Text, &comment.CreatedAt)
		if err != nil {
			return nil, fmt.Errorf("failed to scan comment: %w", err)
		}
		result[comment.IssueID] = append(result[comment.IssueID], comment)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("error iterating comments: %w", err)
	}

	return result, nil
}
