package postgres import ( "context" "database/sql" "encoding/json" "git.gobha.me/xcaliber/chat-switchboard/models" ) // RoutingPolicyStore implements store.RoutingPolicyStore for Postgres. type RoutingPolicyStore struct { db *sql.DB } func NewRoutingPolicyStore(db *sql.DB) *RoutingPolicyStore { return &RoutingPolicyStore{db: db} } func (s *RoutingPolicyStore) Create(ctx context.Context, p *models.RoutingPolicy) error { configJSON, err := json.Marshal(p.Config) if err != nil { return err } return s.db.QueryRowContext(ctx, ` INSERT INTO routing_policies (name, scope, team_id, priority, policy_type, config, is_active) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, created_at, updated_at `, p.Name, p.Scope, p.TeamID, p.Priority, p.Type, configJSON, p.IsActive, ).Scan(&p.ID, &p.CreatedAt, &p.UpdatedAt) } func (s *RoutingPolicyStore) Update(ctx context.Context, p *models.RoutingPolicy) error { configJSON, err := json.Marshal(p.Config) if err != nil { return err } _, err = s.db.ExecContext(ctx, ` UPDATE routing_policies SET name = $2, scope = $3, team_id = $4, priority = $5, policy_type = $6, config = $7, is_active = $8 WHERE id = $1 `, p.ID, p.Name, p.Scope, p.TeamID, p.Priority, p.Type, configJSON, p.IsActive) return err } func (s *RoutingPolicyStore) Delete(ctx context.Context, id string) error { _, err := s.db.ExecContext(ctx, `DELETE FROM routing_policies WHERE id = $1`, id) return err } func (s *RoutingPolicyStore) GetByID(ctx context.Context, id string) (*models.RoutingPolicy, error) { var p models.RoutingPolicy var configJSON []byte err := s.db.QueryRowContext(ctx, ` SELECT id, name, scope, team_id, priority, policy_type, config, is_active, created_at, updated_at FROM routing_policies WHERE id = $1 `, id).Scan(&p.ID, &p.Name, &p.Scope, &p.TeamID, &p.Priority, &p.Type, &configJSON, &p.IsActive, &p.CreatedAt, &p.UpdatedAt) if err != nil { return nil, err } json.Unmarshal(configJSON, &p.Config) return &p, nil } func (s *RoutingPolicyStore) ListActive(ctx context.Context) ([]models.RoutingPolicy, error) { return s.query(ctx, ` SELECT id, name, scope, team_id, priority, policy_type, config, is_active, created_at, updated_at FROM routing_policies WHERE is_active = true ORDER BY priority ASC, created_at ASC `) } func (s *RoutingPolicyStore) ListAll(ctx context.Context) ([]models.RoutingPolicy, error) { return s.query(ctx, ` SELECT id, name, scope, team_id, priority, policy_type, config, is_active, created_at, updated_at FROM routing_policies ORDER BY priority ASC, created_at ASC `) } func (s *RoutingPolicyStore) ListForTeam(ctx context.Context, teamID string) ([]models.RoutingPolicy, error) { return s.query(ctx, ` SELECT id, name, scope, team_id, priority, policy_type, config, is_active, created_at, updated_at FROM routing_policies WHERE is_active = true AND (scope = 'global' OR (scope = 'team' AND team_id = $1)) ORDER BY priority ASC, created_at ASC `, teamID) } func (s *RoutingPolicyStore) query(ctx context.Context, q string, args ...interface{}) ([]models.RoutingPolicy, error) { rows, err := s.db.QueryContext(ctx, q, args...) if err != nil { return nil, err } defer rows.Close() var result []models.RoutingPolicy for rows.Next() { var p models.RoutingPolicy var configJSON []byte if err := rows.Scan(&p.ID, &p.Name, &p.Scope, &p.TeamID, &p.Priority, &p.Type, &configJSON, &p.IsActive, &p.CreatedAt, &p.UpdatedAt); err != nil { return nil, err } json.Unmarshal(configJSON, &p.Config) result = append(result, p) } return result, rows.Err() }