package services import ( "database/sql" "fmt" "time" "github.com/rede5/gohorsejobs/backend/internal/models" ) type CompanyFollowerService struct { DB *sql.DB } func NewCompanyFollowerService(db *sql.DB) *CompanyFollowerService { return &CompanyFollowerService{DB: db} } func (s *CompanyFollowerService) Follow(userID, companyID string) (*models.CompanyFollower, error) { query := ` INSERT INTO company_followers (user_id, company_id, created_at) VALUES ($1, $2, $3) ON CONFLICT (user_id, company_id) DO NOTHING RETURNING id, user_id, company_id, created_at ` var follower models.CompanyFollower err := s.DB.QueryRow(query, userID, companyID, time.Now()).Scan( &follower.ID, &follower.UserID, &follower.CompanyID, &follower.CreatedAt, ) if err == sql.ErrNoRows { err = s.DB.QueryRow( "SELECT id, user_id, company_id, created_at FROM company_followers WHERE user_id = $1 AND company_id = $2", userID, companyID, ).Scan(&follower.ID, &follower.UserID, &follower.CompanyID, &follower.CreatedAt) if err != nil { return nil, err } } else if err != nil { return nil, err } return &follower, nil } func (s *CompanyFollowerService) Unfollow(userID, companyID string) error { _, err := s.DB.Exec("DELETE FROM company_followers WHERE user_id = $1 AND company_id = $2", userID, companyID) return err } func (s *CompanyFollowerService) GetFollowing(userID string) ([]models.CompanyFollowerWithCompany, error) { query := ` SELECT cf.id, cf.user_id, cf.company_id, cf.created_at, c.name, c.logo_url, (SELECT COUNT(*) FROM jobs j WHERE j.company_id = c.id AND j.status = 'published') as jobs_count FROM company_followers cf JOIN companies c ON cf.company_id = c.id WHERE cf.user_id = $1 ORDER BY cf.created_at DESC ` rows, err := s.DB.Query(query, userID) if err != nil { return nil, err } defer rows.Close() var followers []models.CompanyFollowerWithCompany for rows.Next() { var f models.CompanyFollowerWithCompany err := rows.Scan( &f.ID, &f.UserID, &f.CompanyID, &f.CreatedAt, &f.CompanyName, &f.CompanyLogoURL, &f.JobsCount, ) if err != nil { return nil, err } followers = append(followers, f) } return followers, nil } func (s *CompanyFollowerService) IsFollowing(userID, companyID string) (bool, error) { var exists bool err := s.DB.QueryRow( "SELECT EXISTS(SELECT 1 FROM company_followers WHERE user_id = $1 AND company_id = $2)", userID, companyID, ).Scan(&exists) return exists, err } func (s *CompanyFollowerService) GetCompanyFollowersCount(companyID string) (int, error) { var count int err := s.DB.QueryRow( "SELECT COUNT(*) FROM company_followers WHERE company_id = $1", companyID, ).Scan(&count) return count, err } func (s *CompanyFollowerService) GetCompaniesWithJobs(limit, offset int) ([]models.CompanyFollowerWithCompany, error) { query := ` SELECT cf.id, cf.user_id, cf.company_id, cf.created_at, c.name, c.logo_url, (SELECT COUNT(*) FROM jobs j WHERE j.company_id = c.id AND j.status = 'published') as jobs_count FROM companies c LEFT JOIN company_followers cf ON cf.company_id = c.id WHERE c.active = true GROUP BY c.id, cf.id ORDER BY jobs_count DESC, c.name ASC LIMIT $1 OFFSET $2 ` rows, err := s.DB.Query(query, limit, offset) if err != nil { return nil, err } defer rows.Close() var companies []models.CompanyFollowerWithCompany for rows.Next() { var c models.CompanyFollowerWithCompany err := rows.Scan( &c.ID, &c.UserID, &c.CompanyID, &c.CreatedAt, &c.CompanyName, &c.CompanyLogoURL, &c.JobsCount, ) if err != nil { return nil, err } companies = append(companies, c) } return companies, nil }