package sqlite

import (
	"context"
	"encoding/json"
	"time"

	"chat-switchboard/models"
	"chat-switchboard/store"
)

// RoutingPolicyStore implements store.RoutingPolicyStore for SQLite.
type RoutingPolicyStore struct{}

func NewRoutingPolicyStore() *RoutingPolicyStore { return &RoutingPolicyStore{} }

func (s *RoutingPolicyStore) Create(ctx context.Context, p *models.RoutingPolicy) error {
	p.ID = store.NewID()
	configJSON, err := json.Marshal(p.Config)
	if err != nil {
		return err
	}
	now := time.Now().UTC()
	p.CreatedAt = now
	p.UpdatedAt = now
	_, err = DB.ExecContext(ctx, `
		INSERT INTO routing_policies (id, name, scope, team_id, priority, policy_type, config, is_active, created_at, updated_at)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`, p.ID, p.Name, p.Scope, p.TeamID, p.Priority, p.Type, string(configJSON), boolToInt(p.IsActive), p.CreatedAt.Format(time.RFC3339), p.UpdatedAt.Format(time.RFC3339))
	return err
}

func (s *RoutingPolicyStore) Update(ctx context.Context, p *models.RoutingPolicy) error {
	configJSON, err := json.Marshal(p.Config)
	if err != nil {
		return err
	}
	_, err = DB.ExecContext(ctx, `
		UPDATE routing_policies
		SET name = ?, scope = ?, team_id = ?, priority = ?,
		    policy_type = ?, config = ?, is_active = ?, updated_at = datetime('now')
		WHERE id = ?
	`, p.Name, p.Scope, p.TeamID, p.Priority, p.Type, string(configJSON), boolToInt(p.IsActive), p.ID)
	return err
}

func (s *RoutingPolicyStore) Delete(ctx context.Context, id string) error {
	_, err := DB.ExecContext(ctx, `DELETE FROM routing_policies WHERE id = ?`, id)
	return err
}

func (s *RoutingPolicyStore) GetByID(ctx context.Context, id string) (*models.RoutingPolicy, error) {
	var p models.RoutingPolicy
	var configJSON string
	var isActive int
	err := DB.QueryRowContext(ctx, `
		SELECT id, name, scope, team_id, priority, policy_type, config, is_active, created_at, updated_at
		FROM routing_policies WHERE id = ?
	`, id).Scan(&p.ID, &p.Name, &p.Scope, &p.TeamID, &p.Priority, &p.Type, &configJSON, &isActive, st(&p.CreatedAt), st(&p.UpdatedAt))
	if err != nil {
		return nil, err
	}
	p.IsActive = isActive != 0
	json.Unmarshal([]byte(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 = 1
		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 = 1 AND (scope = 'global' OR (scope = 'team' AND team_id = ?))
		ORDER BY priority ASC, created_at ASC
	`, teamID)
}

func (s *RoutingPolicyStore) query(ctx context.Context, q string, args ...interface{}) ([]models.RoutingPolicy, error) {
	rows, err := 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 string
		var isActive int
		if err := rows.Scan(&p.ID, &p.Name, &p.Scope, &p.TeamID, &p.Priority, &p.Type, &configJSON, &isActive, st(&p.CreatedAt), st(&p.UpdatedAt)); err != nil {
			return nil, err
		}
		p.IsActive = isActive != 0
		json.Unmarshal([]byte(configJSON), &p.Config)
		result = append(result, p)
	}
	return result, rows.Err()
}

var _ store.RoutingPolicyStore = (*RoutingPolicyStore)(nil)
