-- ============================================================================
-- Trading Platform - Feature Flags Schema
-- Created: Sprint 2 - TASK-2026-01-30-ANALISIS-INTEGRACION
-- Based on: template-saas SAAS-009 Feature Flags (simplified without multi-tenancy)
-- ============================================================================

-- Create schema if not exists
CREATE SCHEMA IF NOT EXISTS feature_flags;

-- ============================================================================
-- ENUMS
-- ============================================================================

-- Flag status enum
DO $$ BEGIN
  CREATE TYPE feature_flags.flag_status AS ENUM ('disabled', 'enabled', 'percentage');
EXCEPTION
  WHEN duplicate_object THEN NULL;
END $$;

-- Rollout stage enum
DO $$ BEGIN
  CREATE TYPE feature_flags.rollout_stage AS ENUM ('development', 'beta', 'production');
EXCEPTION
  WHEN duplicate_object THEN NULL;
END $$;

-- ============================================================================
-- TABLE: flags (Global feature flag definitions)
-- ============================================================================

CREATE TABLE IF NOT EXISTS feature_flags.flags (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

  -- Identification
  code VARCHAR(100) NOT NULL UNIQUE,
  name VARCHAR(200) NOT NULL,
  description TEXT,
  category VARCHAR(100) DEFAULT 'general',

  -- Status and Rollout
  status feature_flags.flag_status NOT NULL DEFAULT 'disabled',
  rollout_stage feature_flags.rollout_stage NOT NULL DEFAULT 'development',
  rollout_percentage INTEGER DEFAULT 0,
  default_value BOOLEAN NOT NULL DEFAULT false,

  -- Targeting (simplified - by plan or role)
  targeting_rules JSONB DEFAULT '[]',
  -- Example: [{"type": "plan", "operator": "in", "values": ["pro", "premium"]}]

  -- Metadata
  metadata JSONB DEFAULT '{}',
  tags JSONB DEFAULT '[]',

  -- Lifecycle
  is_permanent BOOLEAN NOT NULL DEFAULT false,
  expires_at TIMESTAMPTZ,

  -- Audit
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  created_by VARCHAR(100),

  -- Constraints
  CONSTRAINT valid_flag_code CHECK (code ~ '^[a-z][a-z0-9_]*$'),
  CONSTRAINT valid_percentage CHECK (rollout_percentage >= 0 AND rollout_percentage <= 100)
);

-- ============================================================================
-- TABLE: user_flags (User-level flag overrides)
-- ============================================================================

CREATE TABLE IF NOT EXISTS feature_flags.user_flags (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  flag_id UUID NOT NULL REFERENCES feature_flags.flags(id) ON DELETE CASCADE,

  -- Override
  is_enabled BOOLEAN NOT NULL,
  reason VARCHAR(500),
  expires_at TIMESTAMPTZ,

  -- Audit
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_by UUID,

  -- Unique constraint per user/flag
  CONSTRAINT unique_user_flag UNIQUE (user_id, flag_id)
);

-- ============================================================================
-- TABLE: evaluations (Evaluation history for analytics)
-- ============================================================================

CREATE TABLE IF NOT EXISTS feature_flags.evaluations (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  flag_id UUID NOT NULL REFERENCES feature_flags.flags(id) ON DELETE CASCADE,
  user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,

  -- Evaluation result
  flag_code VARCHAR(100) NOT NULL,
  result BOOLEAN NOT NULL,
  evaluation_reason VARCHAR(100) NOT NULL,
  -- Reasons: 'default', 'user_override', 'targeting_rule', 'percentage', 'expired'

  -- Context
  context JSONB DEFAULT '{}',

  -- Timestamp
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ============================================================================
-- INDEXES
-- ============================================================================

-- Flags indexes
CREATE INDEX IF NOT EXISTS idx_flags_code ON feature_flags.flags(code);
CREATE INDEX IF NOT EXISTS idx_flags_status ON feature_flags.flags(status) WHERE status != 'disabled';
CREATE INDEX IF NOT EXISTS idx_flags_category ON feature_flags.flags(category);

-- User flags indexes
CREATE INDEX IF NOT EXISTS idx_user_flags_user ON feature_flags.user_flags(user_id);
CREATE INDEX IF NOT EXISTS idx_user_flags_flag ON feature_flags.user_flags(flag_id);

-- Evaluations indexes (partitioned by date for analytics)
CREATE INDEX IF NOT EXISTS idx_evaluations_flag ON feature_flags.evaluations(flag_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_evaluations_user ON feature_flags.evaluations(user_id, created_at DESC) WHERE user_id IS NOT NULL;

-- ============================================================================
-- FUNCTION: evaluate_flag
-- Evaluates a feature flag for a given user
-- ============================================================================

CREATE OR REPLACE FUNCTION feature_flags.evaluate_flag(
  p_flag_code VARCHAR(100),
  p_user_id UUID DEFAULT NULL
) RETURNS BOOLEAN AS $$
DECLARE
  v_flag RECORD;
  v_user_override RECORD;
  v_result BOOLEAN;
  v_reason VARCHAR(100);
BEGIN
  -- Get flag definition
  SELECT * INTO v_flag FROM feature_flags.flags WHERE code = p_flag_code;

  IF NOT FOUND THEN
    RETURN false;
  END IF;

  -- Check if expired
  IF v_flag.expires_at IS NOT NULL AND v_flag.expires_at < NOW() THEN
    v_result := false;
    v_reason := 'expired';

    -- Log evaluation
    INSERT INTO feature_flags.evaluations (flag_id, user_id, flag_code, result, evaluation_reason)
    VALUES (v_flag.id, p_user_id, p_flag_code, v_result, v_reason);

    RETURN v_result;
  END IF;

  -- Check user override (highest priority)
  IF p_user_id IS NOT NULL THEN
    SELECT * INTO v_user_override
    FROM feature_flags.user_flags
    WHERE flag_id = v_flag.id
      AND user_id = p_user_id
      AND (expires_at IS NULL OR expires_at > NOW());

    IF FOUND THEN
      v_result := v_user_override.is_enabled;
      v_reason := 'user_override';

      -- Log evaluation
      INSERT INTO feature_flags.evaluations (flag_id, user_id, flag_code, result, evaluation_reason)
      VALUES (v_flag.id, p_user_id, p_flag_code, v_result, v_reason);

      RETURN v_result;
    END IF;
  END IF;

  -- Check flag status
  CASE v_flag.status
    WHEN 'disabled' THEN
      v_result := false;
      v_reason := 'default';
    WHEN 'enabled' THEN
      v_result := true;
      v_reason := 'default';
    WHEN 'percentage' THEN
      -- Simple percentage-based rollout using user_id hash
      IF p_user_id IS NOT NULL THEN
        v_result := (abs(hashtext(p_user_id::text)) % 100) < v_flag.rollout_percentage;
      ELSE
        v_result := (random() * 100) < v_flag.rollout_percentage;
      END IF;
      v_reason := 'percentage';
    ELSE
      v_result := v_flag.default_value;
      v_reason := 'default';
  END CASE;

  -- Log evaluation
  INSERT INTO feature_flags.evaluations (flag_id, user_id, flag_code, result, evaluation_reason)
  VALUES (v_flag.id, p_user_id, p_flag_code, v_result, v_reason);

  RETURN v_result;
END;
$$ LANGUAGE plpgsql;

-- ============================================================================
-- TRIGGER: Update updated_at on flags
-- ============================================================================
-- DEPRECATED: Use public.update_updated_at() instead
-- Migration: migrations/2026-02-03_unify_common_functions.sql
-- Issue: DUP-003
-- Task: ST-2.3
-- ============================================================================

CREATE OR REPLACE FUNCTION feature_flags.update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_flags_updated_at ON feature_flags.flags;
CREATE TRIGGER trg_flags_updated_at
  BEFORE UPDATE ON feature_flags.flags
  FOR EACH ROW EXECUTE FUNCTION feature_flags.update_timestamp();

DROP TRIGGER IF EXISTS trg_user_flags_updated_at ON feature_flags.user_flags;
CREATE TRIGGER trg_user_flags_updated_at
  BEFORE UPDATE ON feature_flags.user_flags
  FOR EACH ROW EXECUTE FUNCTION feature_flags.update_timestamp();

-- ============================================================================
-- COMMENTS
-- ============================================================================

COMMENT ON TABLE feature_flags.flags IS 'Global feature flag definitions';
COMMENT ON TABLE feature_flags.user_flags IS 'User-level feature flag overrides';
COMMENT ON TABLE feature_flags.evaluations IS 'Feature flag evaluation history for analytics';
COMMENT ON FUNCTION feature_flags.evaluate_flag IS 'Evaluates a feature flag for a given user with priority: user_override > percentage > default';

-- ============================================================================
-- INITIAL FLAGS (common flags for trading platform)
-- ============================================================================

INSERT INTO feature_flags.flags (code, name, description, category, status, rollout_stage, default_value)
VALUES
  ('enable_dark_mode', 'Dark Mode', 'Enable dark mode UI theme', 'ui', 'enabled', 'production', true),
  ('enable_advanced_charts', 'Advanced Charts', 'Enable advanced TradingView-like charts', 'trading', 'enabled', 'production', true),
  ('enable_ml_signals', 'ML Signals', 'Show ML prediction signals on charts', 'ml', 'enabled', 'production', true),
  ('enable_llm_assistant', 'LLM Assistant', 'Enable AI trading assistant chat', 'assistant', 'percentage', 'beta', false),
  ('enable_portfolio_rebalancing', 'Portfolio Rebalancing', 'Enable automatic portfolio rebalancing', 'portfolio', 'disabled', 'development', false),
  ('enable_mt4_gateway', 'MT4 Gateway', 'Enable MetaTrader 4 integration', 'trading', 'disabled', 'development', false),
  ('enable_2fa_enforcement', '2FA Enforcement', 'Require 2FA for all users', 'security', 'disabled', 'development', false),
  ('enable_paper_trading', 'Paper Trading', 'Enable paper trading mode', 'trading', 'enabled', 'production', true)
ON CONFLICT (code) DO NOTHING;
