package sqlite

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

	"switchboard-core/models"
)

type GlobalConfigStore struct{}

func NewGlobalConfigStore() *GlobalConfigStore { return &GlobalConfigStore{} }

func (s *GlobalConfigStore) Get(ctx context.Context, key string) (models.JSONMap, error) {
	var valueJSON string
	err := DB.QueryRowContext(ctx,
		"SELECT value FROM global_settings WHERE key = ?", key).Scan(&valueJSON)
	if err == sql.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	var result models.JSONMap
	json.Unmarshal([]byte(valueJSON), &result)
	return result, nil
}

func (s *GlobalConfigStore) Set(ctx context.Context, key string, value models.JSONMap, updatedBy string) error {
	valueJSON := ToJSON(value)
	_, err := DB.ExecContext(ctx, `
		INSERT INTO global_settings (key, value, updated_by, updated_at)
		VALUES (?, ?, ?, datetime('now'))
		ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_by = excluded.updated_by, updated_at = datetime('now')`,
		key, valueJSON, updatedBy)
	return err
}

func (s *GlobalConfigStore) GetAll(ctx context.Context) (map[string]models.JSONMap, error) {
	rows, err := DB.QueryContext(ctx, "SELECT key, value FROM global_settings")
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	result := make(map[string]models.JSONMap)
	for rows.Next() {
		var key, valueJSON string
		if err := rows.Scan(&key, &valueJSON); err != nil {
			continue
		}
		var m models.JSONMap
		json.Unmarshal([]byte(valueJSON), &m)
		result[key] = m
	}
	return result, rows.Err()
}

// ── OIDC state (v0.29.0-cs4) ────────────────────────────────────────────

func (s *GlobalConfigStore) SaveOIDCState(ctx context.Context, state, nonce, redirectTo string) error {
	_, err := DB.ExecContext(ctx, `
		INSERT INTO oidc_auth_state (state, nonce, redirect_to) VALUES (?, ?, ?)
	`, state, nonce, redirectTo)
	return err
}

func (s *GlobalConfigStore) ConsumeOIDCState(ctx context.Context, state string) (string, string, error) {
	var nonce, redirectTo string
	err := DB.QueryRowContext(ctx, `
		SELECT nonce, COALESCE(redirect_to, '') FROM oidc_auth_state WHERE state = ?
	`, state).Scan(&nonce, &redirectTo)
	if err != nil {
		return "", "", err
	}
	_, _ = DB.ExecContext(ctx, `DELETE FROM oidc_auth_state WHERE state = ?`, state)
	return nonce, redirectTo, nil
}

func (s *GlobalConfigStore) CleanupOIDCState(ctx context.Context) error {
	_, err := DB.ExecContext(ctx,
		`DELETE FROM oidc_auth_state WHERE created_at < datetime('now', '-10 minutes')`)
	return err
}

// ── CS6 additions (v0.29.0) ─────────────────────────────────────────────

func (s *GlobalConfigStore) GetString(ctx context.Context, key string) (string, error) {
	var val string
	err := DB.QueryRowContext(ctx,
		"SELECT value FROM global_settings WHERE key = ?", key).Scan(&val)
	return val, err
}
