package postgres

import (
	"context"
	"database/sql"
	"encoding/json"

	"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()
}
