#!/usr/bin/env python3
"""
InsightFlow Growth Manager - Phase 8 Task 5
运营与增长工具模块
- 用户行为分析（Mixpanel/Amplitude 集成）
- A/B 测试框架
- 邮件营销自动化
- 推荐系统（邀请返利、团队升级激励）

作者: InsightFlow Team
"""

import asyncio
import hashlib
import json
import os
import random
import re
import sqlite3
import uuid
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import StrEnum
from typing import Any

import httpx

# Database path
DB_PATH = os.path.join(os.path.dirname(__file__), "insightflow.db")


class EventType(StrEnum):
    """事件类型"""

    PAGE_VIEW = "page_view"  # 页面浏览
    FEATURE_USE = "feature_use"  # 功能使用
    CONVERSION = "conversion"  # 转化
    SIGNUP = "signup"  # 注册
    LOGIN = "login"  # 登录
    UPGRADE = "upgrade"  # 升级
    DOWNGRADE = "downgrade"  # 降级
    CANCEL = "cancel"  # 取消订阅
    INVITE_SENT = "invite_sent"  # 发送邀请
    INVITE_ACCEPTED = "invite_accepted"  # 接受邀请
    REFERRAL_REWARD = "referral_reward"  # 推荐奖励


class ExperimentStatus(StrEnum):
    """实验状态"""

    DRAFT = "draft"  # 草稿
    RUNNING = "running"  # 运行中
    PAUSED = "paused"  # 暂停
    COMPLETED = "completed"  # 已完成
    ARCHIVED = "archived"  # 已归档


class TrafficAllocationType(StrEnum):
    """流量分配类型"""

    RANDOM = "random"  # 随机分配
    STRATIFIED = "stratified"  # 分层分配
    TARGETED = "targeted"  # 定向分配


class EmailTemplateType(StrEnum):
    """邮件模板类型"""

    WELCOME = "welcome"  # 欢迎邮件
    ONBOARDING = "onboarding"  # 引导邮件
    FEATURE_ANNOUNCEMENT = "feature_announcement"  # 功能公告
    CHURN_RECOVERY = "churn_recovery"  # 流失挽回
    UPGRADE_PROMPT = "upgrade_prompt"  # 升级提示
    REFERRAL = "referral"  # 推荐邀请
    NEWSLETTER = "newsletter"  # 新闻通讯


class EmailStatus(StrEnum):
    """邮件状态"""

    DRAFT = "draft"  # 草稿
    SCHEDULED = "scheduled"  # 已计划
    SENDING = "sending"  # 发送中
    SENT = "sent"  # 已发送
    DELIVERED = "delivered"  # 已送达
    OPENED = "opened"  # 已打开
    CLICKED = "clicked"  # 已点击
    BOUNCED = "bounced"  # 退信
    FAILED = "failed"  # 失败


class WorkflowTriggerType(StrEnum):
    """工作流触发类型"""

    USER_SIGNUP = "user_signup"  # 用户注册
    USER_LOGIN = "user_login"  # 用户登录
    SUBSCRIPTION_CREATED = "subscription_created"  # 创建订阅
    SUBSCRIPTION_CANCELLED = "subscription_cancelled"  # 取消订阅
    INACTIVITY = "inactivity"  # 不活跃
    MILESTONE = "milestone"  # 里程碑
    CUSTOM_EVENT = "custom_event"  # 自定义事件


class ReferralStatus(StrEnum):
    """推荐状态"""

    PENDING = "pending"  # 待处理
    CONVERTED = "converted"  # 已转化
    REWARDED = "rewarded"  # 已奖励
    EXPIRED = "expired"  # 已过期


@dataclass
class AnalyticsEvent:
    """分析事件"""

    id: str
    tenant_id: str
    user_id: str
    event_type: EventType
    event_name: str
    properties: dict[str, Any]  # 事件属性
    timestamp: datetime
    session_id: str | None
    device_info: dict[str, str]  # 设备信息
    referrer: str | None
    utm_source: str | None
    utm_medium: str | None
    utm_campaign: str | None


@dataclass
class UserProfile:
    """用户画像"""

    id: str
    tenant_id: str
    user_id: str
    first_seen: datetime
    last_seen: datetime
    total_sessions: int
    total_events: int
    feature_usage: dict[str, int]  # 功能使用次数
    subscription_history: list[dict]
    ltv: float  # 生命周期价值
    churn_risk_score: float  # 流失风险分数
    engagement_score: float  # 参与度分数
    created_at: datetime
    updated_at: datetime


@dataclass
class Funnel:
    """转化漏斗"""

    id: str
    tenant_id: str
    name: str
    description: str
    steps: list[dict]  # 漏斗步骤
    created_at: datetime
    updated_at: datetime


@dataclass
class FunnelAnalysis:
    """漏斗分析结果"""

    funnel_id: str
    period_start: datetime
    period_end: datetime
    total_users: int
    step_conversions: list[dict]  # 每步转化数据
    overall_conversion: float  # 总体转化率
    drop_off_points: list[dict]  # 流失点


@dataclass
class Experiment:
    """A/B 测试实验"""

    id: str
    tenant_id: str
    name: str
    description: str
    hypothesis: str
    status: ExperimentStatus
    variants: list[dict]  # 实验变体
    traffic_allocation: TrafficAllocationType
    traffic_split: dict[str, float]  # 流量分配比例
    target_audience: dict  # 目标受众
    primary_metric: str  # 主要指标
    secondary_metrics: list[str]  # 次要指标
    start_date: datetime | None
    end_date: datetime | None
    min_sample_size: int  # 最小样本量
    confidence_level: float  # 置信水平
    created_at: datetime
    updated_at: datetime
    created_by: str


@dataclass
class ExperimentResult:
    """实验结果"""

    id: str
    experiment_id: str
    variant_id: str
    metric_name: str
    sample_size: int
    mean_value: float
    std_dev: float
    confidence_interval: tuple[float, float]
    p_value: float
    is_significant: bool
    uplift: float  # 提升幅度
    created_at: datetime


@dataclass
class EmailTemplate:
    """邮件模板"""

    id: str
    tenant_id: str
    name: str
    template_type: EmailTemplateType
    subject: str
    html_content: str
    text_content: str
    variables: list[str]  # 模板变量
    preview_text: str | None
    from_name: str
    from_email: str
    reply_to: str | None
    is_active: bool
    created_at: datetime
    updated_at: datetime


@dataclass
class EmailCampaign:
    """邮件营销活动"""

    id: str
    tenant_id: str
    name: str
    template_id: str
    status: str
    recipient_count: int
    sent_count: int
    delivered_count: int
    opened_count: int
    clicked_count: int
    bounced_count: int
    failed_count: int
    scheduled_at: datetime | None
    started_at: datetime | None
    completed_at: datetime | None
    created_at: datetime


@dataclass
class EmailLog:
    """邮件发送记录"""

    id: str
    campaign_id: str
    tenant_id: str
    user_id: str
    email: str
    template_id: str
    status: EmailStatus
    subject: str
    sent_at: datetime | None
    delivered_at: datetime | None
    opened_at: datetime | None
    clicked_at: datetime | None
    ip_address: str | None
    user_agent: str | None
    error_message: str | None
    created_at: datetime


@dataclass
class AutomationWorkflow:
    """自动化工作流"""

    id: str
    tenant_id: str
    name: str
    description: str
    trigger_type: WorkflowTriggerType
    trigger_conditions: dict  # 触发条件
    actions: list[dict]  # 执行动作
    is_active: bool
    execution_count: int
    created_at: datetime
    updated_at: datetime


@dataclass
class ReferralProgram:
    """推荐计划"""

    id: str
    tenant_id: str
    name: str
    description: str
    referrer_reward_type: str  # 奖励类型: credit/discount/feature
    referrer_reward_value: float
    referee_reward_type: str
    referee_reward_value: float
    max_referrals_per_user: int  # 每用户最大推荐数
    referral_code_length: int
    expiry_days: int  # 推荐码过期天数
    is_active: bool
    created_at: datetime
    updated_at: datetime


@dataclass
class Referral:
    """推荐记录"""

    id: str
    program_id: str
    tenant_id: str
    referrer_id: str  # 推荐人
    referee_id: str | None  # 被推荐人
    referral_code: str
    status: ReferralStatus
    referrer_rewarded: bool
    referee_rewarded: bool
    referrer_reward_value: float
    referee_reward_value: float
    converted_at: datetime | None
    rewarded_at: datetime | None
    expires_at: datetime
    created_at: datetime


@dataclass
class TeamIncentive:
    """团队升级激励"""

    id: str
    tenant_id: str
    name: str
    description: str
    target_tier: str  # 目标层级
    min_team_size: int
    incentive_type: str  # 激励类型
    incentive_value: float
    valid_from: datetime
    valid_until: datetime
    is_active: bool
    created_at: datetime


class GrowthManager:
    """运营与增长管理主类"""

    def __init__(self, db_path: str = DB_PATH):
        self.db_path = db_path
        self.mixpanel_token = os.getenv("MIXPANEL_TOKEN", "")
        self.amplitude_api_key = os.getenv("AMPLITUDE_API_KEY", "")
        self.segment_write_key = os.getenv("SEGMENT_WRITE_KEY", "")
        self.sendgrid_api_key = os.getenv("SENDGRID_API_KEY", "")

    def _get_db(self) -> None:
        """获取数据库连接"""
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        return conn

    # ==================== 用户行为分析 ====================

    async def track_event(
        self,
        tenant_id: str,
        user_id: str,
        event_type: EventType,
        event_name: str,
        properties: dict = None,
        session_id: str = None,
        device_info: dict = None,
        referrer: str = None,
        utm_params: dict = None,
    ) -> AnalyticsEvent:
        """追踪事件"""
        event_id = f"evt_{uuid.uuid4().hex[:16]}"
        now = datetime.now()

        event = AnalyticsEvent(
            id=event_id,
            tenant_id=tenant_id,
            user_id=user_id,
            event_type=event_type,
            event_name=event_name,
            properties=properties or {},
            timestamp=now,
            session_id=session_id,
            device_info=device_info or {},
            referrer=referrer,
            utm_source=utm_params.get("source") if utm_params else None,
            utm_medium=utm_params.get("medium") if utm_params else None,
            utm_campaign=utm_params.get("campaign") if utm_params else None,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO analytics_events
                (id, tenant_id, user_id, event_type, event_name, properties, timestamp,
                 session_id, device_info, referrer, utm_source, utm_medium, utm_campaign)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    event.id,
                    event.tenant_id,
                    event.user_id,
                    event.event_type.value,
                    event.event_name,
                    json.dumps(event.properties),
                    event.timestamp.isoformat(),
                    event.session_id,
                    json.dumps(event.device_info),
                    event.referrer,
                    event.utm_source,
                    event.utm_medium,
                    event.utm_campaign,
                ),
            )
            conn.commit()

        # 异步发送到第三方分析平台
        asyncio.create_task(self._send_to_analytics_platforms(event))

        # 更新用户画像
        asyncio.create_task(self._update_user_profile(tenant_id, user_id, event_type, event_name))

        return event

    async def _send_to_analytics_platforms(self, event: AnalyticsEvent):
        """发送事件到第三方分析平台"""
        tasks = []

        if self.mixpanel_token:
            tasks.append(self._send_to_mixpanel(event))
        if self.amplitude_api_key:
            tasks.append(self._send_to_amplitude(event))

        if tasks:
            await asyncio.gather(*tasks, return_exceptions=True)

    async def _send_to_mixpanel(self, event: AnalyticsEvent):
        """发送事件到 Mixpanel"""
        try:
            headers = {
                "Content-Type": "application/json",
                "Authorization": f"Basic {self.mixpanel_token}",
            }

            payload = {
                "event": event.event_name,
                "properties": {
                    "distinct_id": event.user_id,
                    "token": self.mixpanel_token,
                    "time": int(event.timestamp.timestamp()),
                    **event.properties,
                },
            }

            async with httpx.AsyncClient() as client:
                await client.post(
                    "https://api.mixpanel.com/track", headers=headers, json=[payload], timeout=10.0
                )
        except Exception as e:
            print(f"Failed to send to Mixpanel: {e}")

    async def _send_to_amplitude(self, event: AnalyticsEvent):
        """发送事件到 Amplitude"""
        try:
            headers = {"Content-Type": "application/json"}

            payload = {
                "api_key": self.amplitude_api_key,
                "events": [
                    {
                        "user_id": event.user_id,
                        "event_type": event.event_name,
                        "time": int(event.timestamp.timestamp() * 1000),
                        "event_properties": event.properties,
                        "user_properties": {},
                    }
                ],
            }

            async with httpx.AsyncClient() as client:
                await client.post(
                    "https://api.amplitude.com/2/httpapi",
                    headers=headers,
                    json=payload,
                    timeout=10.0,
                )
        except Exception as e:
            print(f"Failed to send to Amplitude: {e}")

    async def _update_user_profile(
        self, tenant_id: str, user_id: str, event_type: EventType, event_name: str
    ):
        """更新用户画像"""
        with self._get_db() as conn:
            # 检查用户画像是否存在
            row = conn.execute(
                "SELECT * FROM user_profiles WHERE tenant_id = ? AND user_id = ?",
                (tenant_id, user_id),
            ).fetchone()

            now = datetime.now().isoformat()

            if row:
                # 更新现有画像
                feature_usage = json.loads(row["feature_usage"])
                if event_name not in feature_usage:
                    feature_usage[event_name] = 0
                feature_usage[event_name] += 1

                conn.execute(
                    """
                    UPDATE user_profiles
                    SET last_seen = ?, total_events = total_events + 1,
                        feature_usage = ?, updated_at = ?
                    WHERE id = ?
                """,
                    (now, json.dumps(feature_usage), now, row["id"]),
                )
            else:
                # 创建新画像
                profile_id = f"up_{uuid.uuid4().hex[:16]}"
                conn.execute(
                    """
                    INSERT INTO user_profiles
                    (id, tenant_id, user_id, first_seen, last_seen, total_sessions,
                     total_events, feature_usage, subscription_history, ltv,
                     churn_risk_score, engagement_score, created_at, updated_at)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                """,
                    (
                        profile_id,
                        tenant_id,
                        user_id,
                        now,
                        now,
                        1,
                        1,
                        json.dumps({event_name: 1}),
                        "[]",
                        0.0,
                        0.0,
                        0.5,
                        now,
                        now,
                    ),
                )

            conn.commit()

    def get_user_profile(self, tenant_id: str, user_id: str) -> UserProfile | None:
        """获取用户画像"""
        with self._get_db() as conn:
            row = conn.execute(
                "SELECT * FROM user_profiles WHERE tenant_id = ? AND user_id = ?",
                (tenant_id, user_id),
            ).fetchone()

            if row:
                return self._row_to_user_profile(row)
            return None

    def get_user_analytics_summary(
        self, tenant_id: str, start_date: datetime = None, end_date: datetime = None
    ) -> dict:
        """获取用户分析汇总"""
        with self._get_db() as conn:
            query = """
                SELECT
                    COUNT(DISTINCT user_id) as unique_users,
                    COUNT(*) as total_events,
                    COUNT(DISTINCT session_id) as total_sessions,
                    COUNT(DISTINCT date(timestamp)) as active_days
                FROM analytics_events
                WHERE tenant_id = ?
            """
            params = [tenant_id]

            if start_date:
                query += " AND timestamp >= ?"
                params.append(start_date.isoformat())
            if end_date:
                query += " AND timestamp <= ?"
                params.append(end_date.isoformat())

            row = conn.execute(query, params).fetchone()

            # 获取事件类型分布
            type_query = """
                SELECT event_type, COUNT(*) as count
                FROM analytics_events
                WHERE tenant_id = ?
            """
            type_params = [tenant_id]

            if start_date:
                type_query += " AND timestamp >= ?"
                type_params.append(start_date.isoformat())
            if end_date:
                type_query += " AND timestamp <= ?"
                type_params.append(end_date.isoformat())

            type_query += " GROUP BY event_type"

            type_rows = conn.execute(type_query, type_params).fetchall()

            return {
                "unique_users": row["unique_users"],
                "total_events": row["total_events"],
                "total_sessions": row["total_sessions"],
                "active_days": row["active_days"],
                "events_per_user": row["total_events"] / max(row["unique_users"], 1),
                "events_per_session": row["total_events"] / max(row["total_sessions"], 1),
                "event_type_distribution": {r["event_type"]: r["count"] for r in type_rows},
            }

    def create_funnel(
        self, tenant_id: str, name: str, description: str, steps: list[dict], created_by: str
    ) -> Funnel:
        """创建转化漏斗"""
        funnel_id = f"fnl_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        funnel = Funnel(
            id=funnel_id,
            tenant_id=tenant_id,
            name=name,
            description=description,
            steps=steps,
            created_at=now,
            updated_at=now,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO funnels
                (id, tenant_id, name, description, steps, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    funnel.id,
                    funnel.tenant_id,
                    funnel.name,
                    funnel.description,
                    json.dumps(funnel.steps),
                    funnel.created_at,
                    funnel.updated_at,
                ),
            )
            conn.commit()

        return funnel

    def analyze_funnel(
        self, funnel_id: str, period_start: datetime = None, period_end: datetime = None
    ) -> FunnelAnalysis | None:
        """分析漏斗转化率"""
        with self._get_db() as conn:
            funnel_row = conn.execute("SELECT * FROM funnels WHERE id = ?", (funnel_id,)).fetchone()

            if not funnel_row:
                return None

            steps = json.loads(funnel_row["steps"])

            if not period_start:
                period_start = datetime.now() - timedelta(days=30)
            if not period_end:
                period_end = datetime.now()

            # 计算每步转化
            step_conversions = []
            previous_count = None

            for step in steps:
                event_name = step.get("event_name")

                query = """
                    SELECT COUNT(DISTINCT user_id) as user_count
                    FROM analytics_events
                    WHERE event_name = ? AND timestamp >= ? AND timestamp <= ?
                """
                row = conn.execute(
                    query, (event_name, period_start.isoformat(), period_end.isoformat())
                ).fetchone()

                user_count = row["user_count"] if row else 0

                conversion_rate = 0.0
                drop_off_rate = 0.0

                if previous_count and previous_count > 0:
                    conversion_rate = user_count / previous_count
                    drop_off_rate = 1 - conversion_rate

                step_conversions.append(
                    {
                        "step_name": step.get("name", event_name),
                        "event_name": event_name,
                        "user_count": user_count,
                        "conversion_rate": round(conversion_rate, 4),
                        "drop_off_rate": round(drop_off_rate, 4),
                    }
                )

                previous_count = user_count

            # 计算总体转化率
            if steps and step_conversions:
                first_step_count = step_conversions[0]["user_count"]
                last_step_count = step_conversions[-1]["user_count"]
                overall_conversion = last_step_count / max(first_step_count, 1)
            else:
                overall_conversion = 0.0

            # 找出主要流失点
            drop_off_points = [
                s for s in step_conversions if s["drop_off_rate"] > 0.2 and s != step_conversions[0]
            ]

            return FunnelAnalysis(
                funnel_id=funnel_id,
                period_start=period_start,
                period_end=period_end,
                total_users=step_conversions[0]["user_count"] if step_conversions else 0,
                step_conversions=step_conversions,
                overall_conversion=round(overall_conversion, 4),
                drop_off_points=drop_off_points,
            )

    def calculate_retention(
        self, tenant_id: str, cohort_date: datetime, periods: list[int] = None
    ) -> dict:
        """计算留存率"""
        if periods is None:
            periods = [1, 3, 7, 14, 30]

        with self._get_db() as conn:
            # 获取同期群用户（在 cohort_date 当天首次活跃的用户）
            cohort_query = """
                SELECT DISTINCT user_id
                FROM analytics_events
                WHERE tenant_id = ? AND date(timestamp) = date(?)
                AND user_id IN (
                    SELECT user_id FROM user_profiles
                    WHERE tenant_id = ? AND date(first_seen) = date(?)
                )
            """
            cohort_rows = conn.execute(
                cohort_query,
                (tenant_id, cohort_date.isoformat(), tenant_id, cohort_date.isoformat()),
            ).fetchall()

            cohort_users = {r["user_id"] for r in cohort_rows}
            cohort_size = len(cohort_users)

            if cohort_size == 0:
                return {"cohort_date": cohort_date.isoformat(), "cohort_size": 0, "retention": {}}

            retention_rates = {}

            for period in periods:
                period_date = cohort_date + timedelta(days=period)

                active_query = """
                    SELECT COUNT(DISTINCT user_id) as active_count
                    FROM analytics_events
                    WHERE tenant_id = ? AND date(timestamp) = date(?)
                    AND user_id IN ({})
                """.format(",".join(["?" for _ in cohort_users]))

                params = [tenant_id, period_date.isoformat()] + list(cohort_users)
                row = conn.execute(active_query, params).fetchone()

                active_count = row["active_count"] if row else 0
                retention_rate = active_count / cohort_size

                retention_rates[f"day_{period}"] = {
                    "active_users": active_count,
                    "retention_rate": round(retention_rate, 4),
                }

            return {
                "cohort_date": cohort_date.isoformat(),
                "cohort_size": cohort_size,
                "retention": retention_rates,
            }

    # ==================== A/B 测试框架 ====================

    def create_experiment(
        self,
        tenant_id: str,
        name: str,
        description: str,
        hypothesis: str,
        variants: list[dict],
        traffic_allocation: TrafficAllocationType,
        traffic_split: dict[str, float],
        target_audience: dict,
        primary_metric: str,
        secondary_metrics: list[str],
        min_sample_size: int = 100,
        confidence_level: float = 0.95,
        created_by: str = None,
    ) -> Experiment:
        """创建 A/B 测试实验"""
        experiment_id = f"exp_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        experiment = Experiment(
            id=experiment_id,
            tenant_id=tenant_id,
            name=name,
            description=description,
            hypothesis=hypothesis,
            status=ExperimentStatus.DRAFT,
            variants=variants,
            traffic_allocation=traffic_allocation,
            traffic_split=traffic_split,
            target_audience=target_audience,
            primary_metric=primary_metric,
            secondary_metrics=secondary_metrics,
            start_date=None,
            end_date=None,
            min_sample_size=min_sample_size,
            confidence_level=confidence_level,
            created_at=now,
            updated_at=now,
            created_by=created_by or "system",
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO experiments
                (id, tenant_id, name, description, hypothesis, status, variants,
                 traffic_allocation, traffic_split, target_audience, primary_metric,
                 secondary_metrics, start_date, end_date, min_sample_size,
                 confidence_level, created_at, updated_at, created_by)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    experiment.id,
                    experiment.tenant_id,
                    experiment.name,
                    experiment.description,
                    experiment.hypothesis,
                    experiment.status.value,
                    json.dumps(experiment.variants),
                    experiment.traffic_allocation.value,
                    json.dumps(experiment.traffic_split),
                    json.dumps(experiment.target_audience),
                    experiment.primary_metric,
                    json.dumps(experiment.secondary_metrics),
                    experiment.start_date,
                    experiment.end_date,
                    experiment.min_sample_size,
                    experiment.confidence_level,
                    experiment.created_at,
                    experiment.updated_at,
                    experiment.created_by,
                ),
            )
            conn.commit()

        return experiment

    def get_experiment(self, experiment_id: str) -> Experiment | None:
        """获取实验详情"""
        with self._get_db() as conn:
            row = conn.execute(
                "SELECT * FROM experiments WHERE id = ?", (experiment_id,)
            ).fetchone()

            if row:
                return self._row_to_experiment(row)
            return None

    def list_experiments(self, tenant_id: str, status: ExperimentStatus = None) -> list[Experiment]:
        """列出实验"""
        query = "SELECT * FROM experiments WHERE tenant_id = ?"
        params = [tenant_id]

        if status:
            query += " AND status = ?"
            params.append(status.value)

        query += " ORDER BY created_at DESC"

        with self._get_db() as conn:
            rows = conn.execute(query, params).fetchall()
            return [self._row_to_experiment(row) for row in rows]

    def assign_variant(
        self, experiment_id: str, user_id: str, user_attributes: dict = None
    ) -> str | None:
        """为用户分配实验变体"""
        experiment = self.get_experiment(experiment_id)
        if not experiment or experiment.status != ExperimentStatus.RUNNING:
            return None

        # 检查用户是否已分配
        with self._get_db() as conn:
            row = conn.execute(
                """SELECT variant_id FROM experiment_assignments
                   WHERE experiment_id = ? AND user_id = ?""",
                (experiment_id, user_id),
            ).fetchone()

            if row:
                return row["variant_id"]

            # 根据分配策略选择变体
            if experiment.traffic_allocation == TrafficAllocationType.RANDOM:
                variant_id = self._random_allocation(experiment.variants, experiment.traffic_split)
            elif experiment.traffic_allocation == TrafficAllocationType.STRATIFIED:
                variant_id = self._stratified_allocation(
                    experiment.variants, experiment.traffic_split, user_attributes
                )
            else:  # TARGETED
                variant_id = self._targeted_allocation(
                    experiment.variants, experiment.target_audience, user_attributes
                )

            if variant_id:
                now = datetime.now().isoformat()
                conn.execute(
                    """
                    INSERT INTO experiment_assignments
                    (id, experiment_id, user_id, variant_id, user_attributes, assigned_at)
                    VALUES (?, ?, ?, ?, ?, ?)
                """,
                    (
                        f"ea_{uuid.uuid4().hex[:16]}",
                        experiment_id,
                        user_id,
                        variant_id,
                        json.dumps(user_attributes or {}),
                        now,
                    ),
                )
                conn.commit()

            return variant_id

    def _random_allocation(self, variants: list[dict], traffic_split: dict[str, float]) -> str:
        """随机分配"""
        variant_ids = [v["id"] for v in variants]
        weights = [traffic_split.get(v_id, 1.0 / len(variants)) for v_id in variant_ids]

        total = sum(weights)
        normalized_weights = [w / total for w in weights]

        return random.choices(variant_ids, weights=normalized_weights, k=1)[0]

    def _stratified_allocation(
        self, variants: list[dict], traffic_split: dict[str, float], user_attributes: dict
    ) -> str:
        """分层分配（基于用户属性）"""
        # 简化的分层分配：根据用户 ID 哈希值分配
        if user_attributes and "user_id" in user_attributes:
            hash_value = int(hashlib.md5(user_attributes["user_id"].encode()).hexdigest(), 16)
            variant_ids = [v["id"] for v in variants]
            index = hash_value % len(variant_ids)
            return variant_ids[index]

        return self._random_allocation(variants, traffic_split)

    def _targeted_allocation(
        self, variants: list[dict], target_audience: dict, user_attributes: dict
    ) -> str | None:
        """定向分配（基于目标受众条件）"""
        # 检查用户是否符合目标受众条件
        conditions = target_audience.get("conditions", [])

        matches = True
        for condition in conditions:
            attr_name = condition.get("attribute")
            operator = condition.get("operator")
            value = condition.get("value")

            user_value = user_attributes.get(attr_name) if user_attributes else None

            if operator == "equals" and user_value != value:
                matches = False
                break
            elif operator == "not_equals" and user_value == value:
                matches = False
                break
            elif operator == "in" and user_value not in value:
                matches = False
                break

        if not matches:
            # 用户不符合条件，返回对照组
            control_variant = next((v for v in variants if v.get("is_control")), variants[0])
            return control_variant["id"] if control_variant else None

        return self._random_allocation(variants, target_audience.get("traffic_split", {}))

    def record_experiment_metric(
        self,
        experiment_id: str,
        variant_id: str,
        user_id: str,
        metric_name: str,
        metric_value: float,
    ):
        """记录实验指标"""
        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO experiment_metrics
                (id, experiment_id, variant_id, user_id, metric_name, metric_value, recorded_at)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    f"em_{uuid.uuid4().hex[:16]}",
                    experiment_id,
                    variant_id,
                    user_id,
                    metric_name,
                    metric_value,
                    datetime.now().isoformat(),
                ),
            )
            conn.commit()

    def analyze_experiment(self, experiment_id: str) -> dict:
        """分析实验结果"""
        experiment = self.get_experiment(experiment_id)
        if not experiment:
            return {"error": "Experiment not found"}

        with self._get_db() as conn:
            results = {}

            for variant in experiment.variants:
                variant_id = variant["id"]

                # 获取样本量
                sample_row = conn.execute(
                    """
                    SELECT COUNT(DISTINCT user_id) as sample_size
                    FROM experiment_assignments
                    WHERE experiment_id = ? AND variant_id = ?
                """,
                    (experiment_id, variant_id),
                ).fetchone()

                sample_size = sample_row["sample_size"] if sample_row else 0

                # 获取主要指标统计
                metric_row = conn.execute(
                    """
                    SELECT
                        AVG(metric_value) as mean_value,
                        COUNT(*) as metric_count,
                        SUM(metric_value) as total_value
                    FROM experiment_metrics
                    WHERE experiment_id = ? AND variant_id = ? AND metric_name = ?
                """,
                    (experiment_id, variant_id, experiment.primary_metric),
                ).fetchone()

                mean_value = (
                    metric_row["mean_value"] if metric_row and metric_row["mean_value"] else 0
                )

                results[variant_id] = {
                    "variant_name": variant.get("name", variant_id),
                    "is_control": variant.get("is_control", False),
                    "sample_size": sample_size,
                    "mean_value": round(mean_value, 4),
                    "metric_count": metric_row["metric_count"] if metric_row else 0,
                }

            # 计算统计显著性（简化版）
            control_variant = next((v for v in experiment.variants if v.get("is_control")), None)
            if control_variant:
                control_id = control_variant["id"]
                control_result = results.get(control_id, {})

                for variant_id, result in results.items():
                    if variant_id != control_id:
                        control_mean = control_result.get("mean_value", 0)
                        variant_mean = result.get("mean_value", 0)

                        if control_mean > 0:
                            uplift = (variant_mean - control_mean) / control_mean
                        else:
                            uplift = 0

                        # 简化的显著性判断
                        is_significant = abs(uplift) > 0.05 and result["sample_size"] > 100

                        result["uplift"] = round(uplift, 4)
                        result["is_significant"] = is_significant
                        result["p_value"] = 0.05 if is_significant else 0.5

            return {
                "experiment_id": experiment_id,
                "experiment_name": experiment.name,
                "primary_metric": experiment.primary_metric,
                "status": experiment.status.value,
                "variant_results": results,
            }

    def start_experiment(self, experiment_id: str) -> Experiment | None:
        """启动实验"""
        with self._get_db() as conn:
            now = datetime.now().isoformat()
            conn.execute(
                """
                UPDATE experiments
                SET status = ?, start_date = ?, updated_at = ?
                WHERE id = ? AND status = ?
            """,
                (
                    ExperimentStatus.RUNNING.value,
                    now,
                    now,
                    experiment_id,
                    ExperimentStatus.DRAFT.value,
                ),
            )
            conn.commit()

        return self.get_experiment(experiment_id)

    def stop_experiment(self, experiment_id: str) -> Experiment | None:
        """停止实验"""
        with self._get_db() as conn:
            now = datetime.now().isoformat()
            conn.execute(
                """
                UPDATE experiments
                SET status = ?, end_date = ?, updated_at = ?
                WHERE id = ? AND status = ?
            """,
                (
                    ExperimentStatus.COMPLETED.value,
                    now,
                    now,
                    experiment_id,
                    ExperimentStatus.RUNNING.value,
                ),
            )
            conn.commit()

        return self.get_experiment(experiment_id)

    # ==================== 邮件营销自动化 ====================

    def create_email_template(
        self,
        tenant_id: str,
        name: str,
        template_type: EmailTemplateType,
        subject: str,
        html_content: str,
        text_content: str = None,
        variables: list[str] = None,
        from_name: str = None,
        from_email: str = None,
        reply_to: str = None,
    ) -> EmailTemplate:
        """创建邮件模板"""
        template_id = f"et_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        # 自动提取变量
        if variables is None:
            variables = re.findall(r"\{\{(\w+)\}\}", html_content)

        template = EmailTemplate(
            id=template_id,
            tenant_id=tenant_id,
            name=name,
            template_type=template_type,
            subject=subject,
            html_content=html_content,
            text_content=text_content or re.sub(r"<[^>]+>", "", html_content),
            variables=variables,
            preview_text=None,
            from_name=from_name or "InsightFlow",
            from_email=from_email or "noreply@insightflow.io",
            reply_to=reply_to,
            is_active=True,
            created_at=now,
            updated_at=now,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO email_templates
                (id, tenant_id, name, template_type, subject, html_content, text_content,
                 variables, from_name, from_email, reply_to, is_active, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    template.id,
                    template.tenant_id,
                    template.name,
                    template.template_type.value,
                    template.subject,
                    template.html_content,
                    template.text_content,
                    json.dumps(template.variables),
                    template.from_name,
                    template.from_email,
                    template.reply_to,
                    template.is_active,
                    template.created_at,
                    template.updated_at,
                ),
            )
            conn.commit()

        return template

    def get_email_template(self, template_id: str) -> EmailTemplate | None:
        """获取邮件模板"""
        with self._get_db() as conn:
            row = conn.execute(
                "SELECT * FROM email_templates WHERE id = ?", (template_id,)
            ).fetchone()

            if row:
                return self._row_to_email_template(row)
            return None

    def list_email_templates(
        self, tenant_id: str, template_type: EmailTemplateType = None
    ) -> list[EmailTemplate]:
        """列出邮件模板"""
        query = "SELECT * FROM email_templates WHERE tenant_id = ? AND is_active = 1"
        params = [tenant_id]

        if template_type:
            query += " AND template_type = ?"
            params.append(template_type.value)

        query += " ORDER BY created_at DESC"

        with self._get_db() as conn:
            rows = conn.execute(query, params).fetchall()
            return [self._row_to_email_template(row) for row in rows]

    def render_template(self, template_id: str, variables: dict) -> dict[str, str]:
        """渲染邮件模板"""
        template = self.get_email_template(template_id)
        if not template:
            return None

        subject = template.subject
        html_content = template.html_content
        text_content = template.text_content

        for key, value in variables.items():
            placeholder = f"{{{{{key}}}}}"
            subject = subject.replace(placeholder, str(value))
            html_content = html_content.replace(placeholder, str(value))
            text_content = text_content.replace(placeholder, str(value))

        return {
            "subject": subject,
            "html": html_content,
            "text": text_content,
            "from_name": template.from_name,
            "from_email": template.from_email,
            "reply_to": template.reply_to,
        }

    def create_email_campaign(
        self,
        tenant_id: str,
        name: str,
        template_id: str,
        recipient_list: list[dict],
        scheduled_at: datetime = None,
    ) -> EmailCampaign:
        """创建邮件营销活动"""
        campaign_id = f"ec_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        campaign = EmailCampaign(
            id=campaign_id,
            tenant_id=tenant_id,
            name=name,
            template_id=template_id,
            status="draft",
            recipient_count=len(recipient_list),
            sent_count=0,
            delivered_count=0,
            opened_count=0,
            clicked_count=0,
            bounced_count=0,
            failed_count=0,
            scheduled_at=scheduled_at.isoformat() if scheduled_at else None,
            started_at=None,
            completed_at=None,
            created_at=now,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO email_campaigns
                (id, tenant_id, name, template_id, status, recipient_count,
                 sent_count, delivered_count, opened_count, clicked_count,
                 bounced_count, failed_count, scheduled_at, started_at, completed_at, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    campaign.id,
                    campaign.tenant_id,
                    campaign.name,
                    campaign.template_id,
                    campaign.status,
                    campaign.recipient_count,
                    campaign.sent_count,
                    campaign.delivered_count,
                    campaign.opened_count,
                    campaign.clicked_count,
                    campaign.bounced_count,
                    campaign.failed_count,
                    campaign.scheduled_at,
                    campaign.started_at,
                    campaign.completed_at,
                    campaign.created_at,
                ),
            )

            # 创建邮件发送记录
            for recipient in recipient_list:
                conn.execute(
                    """
                    INSERT INTO email_logs
                    (id, campaign_id, tenant_id, user_id, email, template_id, status, subject, created_at)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
                """,
                    (
                        f"el_{uuid.uuid4().hex[:16]}",
                        campaign_id,
                        tenant_id,
                        recipient.get("user_id"),
                        recipient.get("email"),
                        template_id,
                        EmailStatus.SCHEDULED.value if scheduled_at else EmailStatus.DRAFT.value,
                        "",
                        now,
                    ),
                )

            conn.commit()

        return campaign

    async def send_email(
        self, campaign_id: str, user_id: str, email: str, template_id: str, variables: dict
    ) -> bool:
        """发送单封邮件"""
        template = self.get_email_template(template_id)
        if not template:
            return False

        rendered = self.render_template(template_id, variables)

        # 更新状态为发送中
        with self._get_db() as conn:
            now = datetime.now().isoformat()
            conn.execute(
                """
                UPDATE email_logs
                SET status = ?, sent_at = ?, subject = ?
                WHERE campaign_id = ? AND user_id = ?
            """,
                (EmailStatus.SENDING.value, now, rendered["subject"], campaign_id, user_id),
            )
            conn.commit()

        try:
            # 这里集成实际的邮件发送服务（SendGrid, AWS SES 等）
            # 目前使用模拟发送
            await asyncio.sleep(0.1)

            success = True  # 模拟成功

            # 更新状态
            with self._get_db() as conn:
                now = datetime.now().isoformat()
                if success:
                    conn.execute(
                        """
                        UPDATE email_logs
                        SET status = ?, delivered_at = ?
                        WHERE campaign_id = ? AND user_id = ?
                    """,
                        (EmailStatus.DELIVERED.value, now, campaign_id, user_id),
                    )
                else:
                    conn.execute(
                        """
                        UPDATE email_logs
                        SET status = ?, error_message = ?
                        WHERE campaign_id = ? AND user_id = ?
                    """,
                        (EmailStatus.FAILED.value, "Send failed", campaign_id, user_id),
                    )
                conn.commit()

            return success

        except Exception as e:
            with self._get_db() as conn:
                conn.execute(
                    """
                    UPDATE email_logs
                    SET status = ?, error_message = ?
                    WHERE campaign_id = ? AND user_id = ?
                """,
                    (EmailStatus.FAILED.value, str(e), campaign_id, user_id),
                )
                conn.commit()
            return False

    async def send_campaign(self, campaign_id: str) -> dict:
        """发送整个营销活动"""
        with self._get_db() as conn:
            campaign_row = conn.execute(
                "SELECT * FROM email_campaigns WHERE id = ?", (campaign_id,)
            ).fetchone()

            if not campaign_row:
                return {"error": "Campaign not found"}

            # 获取待发送的邮件
            logs = conn.execute(
                """SELECT * FROM email_logs
                   WHERE campaign_id = ? AND status IN (?, ?)""",
                (campaign_id, EmailStatus.DRAFT.value, EmailStatus.SCHEDULED.value),
            ).fetchall()

            # 更新活动状态
            now = datetime.now().isoformat()
            conn.execute(
                "UPDATE email_campaigns SET status = ?, started_at = ? WHERE id = ?",
                ("sending", now, campaign_id),
            )
            conn.commit()

        # 批量发送
        success_count = 0
        failed_count = 0

        for log in logs:
            # 获取用户变量
            variables = self._get_user_variables(log["tenant_id"], log["user_id"])

            success = await self.send_email(
                campaign_id, log["user_id"], log["email"], log["template_id"], variables
            )

            if success:
                success_count += 1
            else:
                failed_count += 1

        # 更新活动状态
        with self._get_db() as conn:
            now = datetime.now().isoformat()
            conn.execute(
                """
                UPDATE email_campaigns
                SET status = ?, completed_at = ?, sent_count = ?
                WHERE id = ?
            """,
                ("completed", now, success_count, campaign_id),
            )
            conn.commit()

        return {
            "campaign_id": campaign_id,
            "total": len(logs),
            "success": success_count,
            "failed": failed_count,
        }

    def _get_user_variables(self, tenant_id: str, user_id: str) -> dict:
        """获取用户变量用于邮件模板"""
        # 这里应该从用户服务获取用户信息
        # 简化实现
        return {"user_id": user_id, "user_name": "User", "tenant_id": tenant_id}

    def create_automation_workflow(
        self,
        tenant_id: str,
        name: str,
        description: str,
        trigger_type: WorkflowTriggerType,
        trigger_conditions: dict,
        actions: list[dict],
    ) -> AutomationWorkflow:
        """创建自动化工作流"""
        workflow_id = f"aw_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        workflow = AutomationWorkflow(
            id=workflow_id,
            tenant_id=tenant_id,
            name=name,
            description=description,
            trigger_type=trigger_type,
            trigger_conditions=trigger_conditions,
            actions=actions,
            is_active=True,
            execution_count=0,
            created_at=now,
            updated_at=now,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO automation_workflows
                (id, tenant_id, name, description, trigger_type, trigger_conditions,
                 actions, is_active, execution_count, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    workflow.id,
                    workflow.tenant_id,
                    workflow.name,
                    workflow.description,
                    workflow.trigger_type.value,
                    json.dumps(workflow.trigger_conditions),
                    json.dumps(workflow.actions),
                    workflow.is_active,
                    workflow.execution_count,
                    workflow.created_at,
                    workflow.updated_at,
                ),
            )
            conn.commit()

        return workflow

    async def trigger_workflow(self, workflow_id: str, event_data: dict):
        """触发自动化工作流"""
        with self._get_db() as conn:
            row = conn.execute(
                "SELECT * FROM automation_workflows WHERE id = ? AND is_active = 1", (workflow_id,)
            ).fetchone()

            if not row:
                return False

            workflow = self._row_to_automation_workflow(row)

            # 检查触发条件
            if not self._check_trigger_conditions(workflow.trigger_conditions, event_data):
                return False

            # 执行动作
            for action in workflow.actions:
                await self._execute_action(action, event_data)

            # 更新执行计数
            conn.execute(
                "UPDATE automation_workflows SET execution_count = execution_count + 1 WHERE id = ?",
                (workflow_id,),
            )
            conn.commit()

        return True

    def _check_trigger_conditions(self, conditions: dict, event_data: dict) -> bool:
        """检查触发条件"""
        # 简化的条件检查
        for key, value in conditions.items():
            if event_data.get(key) != value:
                return False
        return True

    async def _execute_action(self, action: dict, event_data: dict):
        """执行工作流动作"""
        action_type = action.get("type")

        if action_type == "send_email":
            action.get("template_id")
            # 发送邮件逻辑
        elif action_type == "update_user":
            # 更新用户属性
            pass
        elif action_type == "webhook":
            # 调用 webhook
            pass

    # ==================== 推荐系统 ====================

    def create_referral_program(
        self,
        tenant_id: str,
        name: str,
        description: str,
        referrer_reward_type: str,
        referrer_reward_value: float,
        referee_reward_type: str,
        referee_reward_value: float,
        max_referrals_per_user: int = 10,
        referral_code_length: int = 8,
        expiry_days: int = 30,
    ) -> ReferralProgram:
        """创建推荐计划"""
        program_id = f"rp_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        program = ReferralProgram(
            id=program_id,
            tenant_id=tenant_id,
            name=name,
            description=description,
            referrer_reward_type=referrer_reward_type,
            referrer_reward_value=referrer_reward_value,
            referee_reward_type=referee_reward_type,
            referee_reward_value=referee_reward_value,
            max_referrals_per_user=max_referrals_per_user,
            referral_code_length=referral_code_length,
            expiry_days=expiry_days,
            is_active=True,
            created_at=now,
            updated_at=now,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO referral_programs
                (id, tenant_id, name, description, referrer_reward_type, referrer_reward_value,
                 referee_reward_type, referee_reward_value, max_referrals_per_user,
                 referral_code_length, expiry_days, is_active, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    program.id,
                    program.tenant_id,
                    program.name,
                    program.description,
                    program.referrer_reward_type,
                    program.referrer_reward_value,
                    program.referee_reward_type,
                    program.referee_reward_value,
                    program.max_referrals_per_user,
                    program.referral_code_length,
                    program.expiry_days,
                    program.is_active,
                    program.created_at,
                    program.updated_at,
                ),
            )
            conn.commit()

        return program

    def generate_referral_code(self, program_id: str, referrer_id: str) -> Referral:
        """生成推荐码"""
        program = self._get_referral_program(program_id)
        if not program:
            return None

        # 检查推荐次数限制
        with self._get_db() as conn:
            count_row = conn.execute(
                """SELECT COUNT(*) as count FROM referrals
                   WHERE program_id = ? AND referrer_id = ? AND status != ?""",
                (program_id, referrer_id, ReferralStatus.EXPIRED.value),
            ).fetchone()

            if count_row["count"] >= program.max_referrals_per_user:
                return None

            # 生成推荐码
            referral_code = self._generate_unique_code(program.referral_code_length)

            referral_id = f"ref_{uuid.uuid4().hex[:16]}"
            now = datetime.now()
            expires_at = now + timedelta(days=program.expiry_days)

            referral = Referral(
                id=referral_id,
                program_id=program_id,
                tenant_id=program.tenant_id,
                referrer_id=referrer_id,
                referee_id=None,
                referral_code=referral_code,
                status=ReferralStatus.PENDING,
                referrer_rewarded=False,
                referee_rewarded=False,
                referrer_reward_value=program.referrer_reward_value,
                referee_reward_value=program.referee_reward_value,
                converted_at=None,
                rewarded_at=None,
                expires_at=expires_at,
                created_at=now,
            )

            conn.execute(
                """
                INSERT INTO referrals
                (id, program_id, tenant_id, referrer_id, referee_id, referral_code,
                 status, referrer_rewarded, referee_rewarded, referrer_reward_value,
                 referee_reward_value, converted_at, rewarded_at, expires_at, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    referral.id,
                    referral.program_id,
                    referral.tenant_id,
                    referral.referrer_id,
                    referral.referee_id,
                    referral.referral_code,
                    referral.status.value,
                    referral.referrer_rewarded,
                    referral.referee_rewarded,
                    referral.referrer_reward_value,
                    referral.referee_reward_value,
                    referral.converted_at,
                    referral.rewarded_at,
                    referral.expires_at.isoformat(),
                    referral.created_at.isoformat(),
                ),
            )
            conn.commit()

        return referral

    def _generate_unique_code(self, length: int) -> str:
        """生成唯一推荐码"""
        chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"  # 排除易混淆字符
        while True:
            code = "".join(random.choices(chars, k=length))

            with self._get_db() as conn:
                row = conn.execute(
                    "SELECT 1 FROM referrals WHERE referral_code = ?", (code,)
                ).fetchone()

                if not row:
                    return code

    def _get_referral_program(self, program_id: str) -> ReferralProgram | None:
        """获取推荐计划"""
        with self._get_db() as conn:
            row = conn.execute(
                "SELECT * FROM referral_programs WHERE id = ?", (program_id,)
            ).fetchone()

            if row:
                return self._row_to_referral_program(row)
            return None

    def apply_referral_code(self, referral_code: str, referee_id: str) -> bool:
        """应用推荐码"""
        with self._get_db() as conn:
            row = conn.execute(
                """SELECT * FROM referrals
                   WHERE referral_code = ? AND status = ? AND expires_at > ?""",
                (referral_code, ReferralStatus.PENDING.value, datetime.now().isoformat()),
            ).fetchone()

            if not row:
                return False

            now = datetime.now().isoformat()
            conn.execute(
                """
                UPDATE referrals
                SET referee_id = ?, status = ?, converted_at = ?
                WHERE id = ?
            """,
                (referee_id, ReferralStatus.CONVERTED.value, now, row["id"]),
            )
            conn.commit()

        return True

    def reward_referral(self, referral_id: str) -> bool:
        """发放推荐奖励"""
        with self._get_db() as conn:
            row = conn.execute("SELECT * FROM referrals WHERE id = ?", (referral_id,)).fetchone()

            if not row or row["status"] != ReferralStatus.CONVERTED.value:
                return False

            now = datetime.now().isoformat()
            conn.execute(
                """
                UPDATE referrals
                SET status = ?, referrer_rewarded = 1, referee_rewarded = 1, rewarded_at = ?
                WHERE id = ?
            """,
                (ReferralStatus.REWARDED.value, now, referral_id),
            )
            conn.commit()

        return True

    def get_referral_stats(self, program_id: str) -> dict:
        """获取推荐统计"""
        with self._get_db() as conn:
            stats = conn.execute(
                """
                SELECT
                    COUNT(*) as total_referrals,
                    SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as pending,
                    SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as converted,
                    SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as rewarded,
                    SUM(CASE WHEN status = ? THEN 1 ELSE 0 END) as expired,
                    COUNT(DISTINCT referrer_id) as unique_referrers
                FROM referrals
                WHERE program_id = ?
            """,
                (
                    ReferralStatus.PENDING.value,
                    ReferralStatus.CONVERTED.value,
                    ReferralStatus.REWARDED.value,
                    ReferralStatus.EXPIRED.value,
                    program_id,
                ),
            ).fetchone()

            return {
                "program_id": program_id,
                "total_referrals": stats["total_referrals"] or 0,
                "pending": stats["pending"] or 0,
                "converted": stats["converted"] or 0,
                "rewarded": stats["rewarded"] or 0,
                "expired": stats["expired"] or 0,
                "unique_referrers": stats["unique_referrers"] or 0,
                "conversion_rate": round(
                    (stats["converted"] or 0) / max(stats["total_referrals"] or 1, 1), 4
                ),
            }

    def create_team_incentive(
        self,
        tenant_id: str,
        name: str,
        description: str,
        target_tier: str,
        min_team_size: int,
        incentive_type: str,
        incentive_value: float,
        valid_from: datetime,
        valid_until: datetime,
    ) -> TeamIncentive:
        """创建团队升级激励"""
        incentive_id = f"ti_{uuid.uuid4().hex[:16]}"
        now = datetime.now().isoformat()

        incentive = TeamIncentive(
            id=incentive_id,
            tenant_id=tenant_id,
            name=name,
            description=description,
            target_tier=target_tier,
            min_team_size=min_team_size,
            incentive_type=incentive_type,
            incentive_value=incentive_value,
            valid_from=valid_from.isoformat(),
            valid_until=valid_until.isoformat(),
            is_active=True,
            created_at=now,
        )

        with self._get_db() as conn:
            conn.execute(
                """
                INSERT INTO team_incentives
                (id, tenant_id, name, description, target_tier, min_team_size,
                 incentive_type, incentive_value, valid_from, valid_until, is_active, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
                (
                    incentive.id,
                    incentive.tenant_id,
                    incentive.name,
                    incentive.description,
                    incentive.target_tier,
                    incentive.min_team_size,
                    incentive.incentive_type,
                    incentive.incentive_value,
                    incentive.valid_from,
                    incentive.valid_until,
                    incentive.is_active,
                    incentive.created_at,
                ),
            )
            conn.commit()

        return incentive

    def check_team_incentive_eligibility(
        self, tenant_id: str, current_tier: str, team_size: int
    ) -> list[TeamIncentive]:
        """检查团队激励资格"""
        with self._get_db() as conn:
            now = datetime.now().isoformat()
            rows = conn.execute(
                """
                SELECT * FROM team_incentives
                WHERE tenant_id = ? AND is_active = 1
                AND target_tier = ? AND min_team_size <= ?
                AND valid_from <= ? AND valid_until >= ?
            """,
                (tenant_id, current_tier, team_size, now, now),
            ).fetchall()

            return [self._row_to_team_incentive(row) for row in rows]

    # ==================== 实时分析仪表板 ====================

    def get_realtime_dashboard(self, tenant_id: str) -> dict:
        """获取实时分析仪表板数据"""
        now = datetime.now()
        today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)

        with self._get_db() as conn:
            # 今日统计
            today_stats = conn.execute(
                """
                SELECT
                    COUNT(DISTINCT user_id) as active_users,
                    COUNT(*) as total_events,
                    COUNT(DISTINCT session_id) as sessions
                FROM analytics_events
                WHERE tenant_id = ? AND timestamp >= ?
            """,
                (tenant_id, today_start.isoformat()),
            ).fetchone()

            # 最近事件
            recent_events = conn.execute(
                """
                SELECT event_name, event_type, timestamp, user_id
                FROM analytics_events
                WHERE tenant_id = ?
                ORDER BY timestamp DESC
                LIMIT 20
            """,
                (tenant_id,),
            ).fetchall()

            # 热门功能
            top_features = conn.execute(
                """
                SELECT event_name, COUNT(*) as count
                FROM analytics_events
                WHERE tenant_id = ? AND timestamp >= ? AND event_type = ?
                GROUP BY event_name
                ORDER BY count DESC
                LIMIT 10
            """,
                (tenant_id, today_start.isoformat(), EventType.FEATURE_USE.value),
            ).fetchall()

            # 活跃用户趋势（最近24小时，每小时）
            hourly_trend = []
            for i in range(24):
                hour_start = now - timedelta(hours=i + 1)
                hour_end = now - timedelta(hours=i)

                row = conn.execute(
                    """
                    SELECT COUNT(DISTINCT user_id) as count
                    FROM analytics_events
                    WHERE tenant_id = ? AND timestamp >= ? AND timestamp < ?
                """,
                    (tenant_id, hour_start.isoformat(), hour_end.isoformat()),
                ).fetchone()

                hourly_trend.append(
                    {"hour": hour_end.strftime("%H:00"), "active_users": row["count"] or 0}
                )

            return {
                "tenant_id": tenant_id,
                "timestamp": now.isoformat(),
                "today": {
                    "active_users": today_stats["active_users"] or 0,
                    "total_events": today_stats["total_events"] or 0,
                    "sessions": today_stats["sessions"] or 0,
                },
                "recent_events": [
                    {
                        "event_name": r["event_name"],
                        "event_type": r["event_type"],
                        "timestamp": r["timestamp"],
                        "user_id": r["user_id"][:8] + "...",  # 脱敏
                    }
                    for r in recent_events
                ],
                "top_features": [
                    {"feature": r["event_name"], "usage_count": r["count"]} for r in top_features
                ],
                "hourly_trend": list(reversed(hourly_trend)),
            }

    # ==================== 辅助方法 ====================

    def _row_to_user_profile(self, row) -> UserProfile:
        """将数据库行转换为 UserProfile"""
        return UserProfile(
            id=row["id"],
            tenant_id=row["tenant_id"],
            user_id=row["user_id"],
            first_seen=datetime.fromisoformat(row["first_seen"]),
            last_seen=datetime.fromisoformat(row["last_seen"]),
            total_sessions=row["total_sessions"],
            total_events=row["total_events"],
            feature_usage=json.loads(row["feature_usage"]),
            subscription_history=json.loads(row["subscription_history"]),
            ltv=row["ltv"],
            churn_risk_score=row["churn_risk_score"],
            engagement_score=row["engagement_score"],
            created_at=datetime.fromisoformat(row["created_at"]),
            updated_at=datetime.fromisoformat(row["updated_at"]),
        )

    def _row_to_experiment(self, row) -> Experiment:
        """将数据库行转换为 Experiment"""
        return Experiment(
            id=row["id"],
            tenant_id=row["tenant_id"],
            name=row["name"],
            description=row["description"],
            hypothesis=row["hypothesis"],
            status=ExperimentStatus(row["status"]),
            variants=json.loads(row["variants"]),
            traffic_allocation=TrafficAllocationType(row["traffic_allocation"]),
            traffic_split=json.loads(row["traffic_split"]),
            target_audience=json.loads(row["target_audience"]),
            primary_metric=row["primary_metric"],
            secondary_metrics=json.loads(row["secondary_metrics"]),
            start_date=datetime.fromisoformat(row["start_date"]) if row["start_date"] else None,
            end_date=datetime.fromisoformat(row["end_date"]) if row["end_date"] else None,
            min_sample_size=row["min_sample_size"],
            confidence_level=row["confidence_level"],
            created_at=row["created_at"],
            updated_at=row["updated_at"],
            created_by=row["created_by"],
        )

    def _row_to_email_template(self, row) -> EmailTemplate:
        """将数据库行转换为 EmailTemplate"""
        return EmailTemplate(
            id=row["id"],
            tenant_id=row["tenant_id"],
            name=row["name"],
            template_type=EmailTemplateType(row["template_type"]),
            subject=row["subject"],
            html_content=row["html_content"],
            text_content=row["text_content"],
            variables=json.loads(row["variables"]),
            preview_text=row["preview_text"],
            from_name=row["from_name"],
            from_email=row["from_email"],
            reply_to=row["reply_to"],
            is_active=bool(row["is_active"]),
            created_at=row["created_at"],
            updated_at=row["updated_at"],
        )

    def _row_to_automation_workflow(self, row) -> AutomationWorkflow:
        """将数据库行转换为 AutomationWorkflow"""
        return AutomationWorkflow(
            id=row["id"],
            tenant_id=row["tenant_id"],
            name=row["name"],
            description=row["description"],
            trigger_type=WorkflowTriggerType(row["trigger_type"]),
            trigger_conditions=json.loads(row["trigger_conditions"]),
            actions=json.loads(row["actions"]),
            is_active=bool(row["is_active"]),
            execution_count=row["execution_count"],
            created_at=row["created_at"],
            updated_at=row["updated_at"],
        )

    def _row_to_referral_program(self, row) -> ReferralProgram:
        """将数据库行转换为 ReferralProgram"""
        return ReferralProgram(
            id=row["id"],
            tenant_id=row["tenant_id"],
            name=row["name"],
            description=row["description"],
            referrer_reward_type=row["referrer_reward_type"],
            referrer_reward_value=row["referrer_reward_value"],
            referee_reward_type=row["referee_reward_type"],
            referee_reward_value=row["referee_reward_value"],
            max_referrals_per_user=row["max_referrals_per_user"],
            referral_code_length=row["referral_code_length"],
            expiry_days=row["expiry_days"],
            is_active=bool(row["is_active"]),
            created_at=row["created_at"],
            updated_at=row["updated_at"],
        )

    def _row_to_team_incentive(self, row) -> TeamIncentive:
        """将数据库行转换为 TeamIncentive"""
        return TeamIncentive(
            id=row["id"],
            tenant_id=row["tenant_id"],
            name=row["name"],
            description=row["description"],
            target_tier=row["target_tier"],
            min_team_size=row["min_team_size"],
            incentive_type=row["incentive_type"],
            incentive_value=row["incentive_value"],
            valid_from=datetime.fromisoformat(row["valid_from"]),
            valid_until=datetime.fromisoformat(row["valid_until"]),
            is_active=bool(row["is_active"]),
            created_at=row["created_at"],
        )


# Singleton instance
_growth_manager = None


def get_growth_manager() -> GrowthManager:
    global _growth_manager
    if _growth_manager is None:
        _growth_manager = GrowthManager()
    return _growth_manager
