package repository import ( "github.com/google/uuid" "github.com/zs/InsightReply/internal/model" "gorm.io/gorm" ) type ReplyRepository struct { db *gorm.DB } func NewReplyRepository(db *gorm.DB) *ReplyRepository { return &ReplyRepository{db: db} } // CreateGeneratedReply logs an AI generated response when it is copied/used by the user func (r *ReplyRepository) CreateGeneratedReply(reply *model.GeneratedReply) error { return r.db.Create(reply).Error } // GetPendingPerformanceChecks returns copied replies that need their performance checked (e.g. older than 24h) func (r *ReplyRepository) GetPendingPerformanceChecks() ([]model.GeneratedReply, error) { var replies []model.GeneratedReply // Complex: Fetch replies that are "copied", created more than 24 hours ago, // and DO NOT already have a corresponding entry in reply_performance. err := r.db.Table("generated_replies"). Select("generated_replies.*"). Joins("LEFT JOIN reply_performance rp ON rp.reply_id = generated_replies.id"). Where("generated_replies.status = ?", "copied"). Where("generated_replies.created_at < NOW() - INTERVAL '1 day'"). Where("rp.id IS NULL"). Find(&replies).Error return replies, err } // SaveReplyPerformance persists the checked engagement scores of a generated reply func (r *ReplyRepository) SaveReplyPerformance(perf *model.ReplyPerformance) error { return r.db.Create(perf).Error } // UpsertDummyTweet acts as a safety hook to guarantee foreign key integrity exists before recording a reply onto an un-crawled Tweet. func (r *ReplyRepository) UpsertDummyTweet(tweet *model.Tweet) error { return r.db.Where("x_tweet_id = ?", tweet.XTweetID).FirstOrCreate(tweet).Error } // GetTweetXTweetID returns the string identifier string X uses, converting backwards from the postgres UUID func (r *ReplyRepository) GetTweetXTweetID(tweetID uuid.UUID) (string, error) { var tweet model.Tweet err := r.db.Where("id = ?", tweetID).First(&tweet).Error return tweet.XTweetID, err } // SaveStyleExtraction commits an AI-learned writing style profile against the user for future inference injection func (r *ReplyRepository) SaveStyleExtraction(userID uuid.UUID, styleDesc string) error { // user_style_profiles might not exist yet; use raw SQL or Gorm Upsert return r.db.Exec(` INSERT INTO user_style_profiles (user_id, tone_preference) VALUES (?, ?) ON CONFLICT (user_id) DO UPDATE SET tone_preference = EXCLUDED.tone_preference, updated_at = NOW() `, userID, styleDesc).Error } // GetGeneratedRepliesByUser retrieves all AI replies for a user to display in the History dashboard func (r *ReplyRepository) GetGeneratedRepliesByUser(userID uuid.UUID) ([]model.GeneratedReply, error) { var replies []model.GeneratedReply // Preload the performance data if it exists. Preloading "Performance" requires GORM association. // We'll just fetch replies and order by newest first. err := r.db.Where("user_id = ?", userID).Order("created_at desc").Limit(100).Find(&replies).Error return replies, err }