import '../../chunk-BJTO5JO5.mjs';
import { pgTable, timestamp, text, jsonb, integer, index } from 'drizzle-orm/pg-core';
import { sql, lte, eq, gte, and, asc, count, desc, inArray } from 'drizzle-orm';

var analyticsEvents = pgTable(
  "analytics_events",
  {
    id: text().primaryKey().notNull(),
    eventType: text("event_type").notNull(),
    eventName: text("event_name").notNull(),
    timestamp: timestamp({ precision: 3, mode: "string" }).notNull(),
    priority: integer().notNull(),
    userId: text("user_id"),
    sessionId: text("session_id").notNull(),
    deviceId: text("device_id").notNull(),
    pageUrl: text("page_url"),
    pageTitle: text("page_title"),
    referrer: text(),
    properties: jsonb(),
    platform: text().notNull(),
    appVersion: text("app_version").notNull(),
    sdkVersion: text("sdk_version").notNull(),
    createdAt: timestamp({ precision: 3, mode: "string" }).default(sql`CURRENT_TIMESTAMP`).notNull()
  },
  (table) => [
    index("analytics_events_user_id_idx").using(
      "btree",
      table.userId.asc().nullsLast().op("text_ops")
    ),
    index("analytics_events_event_type_idx").using(
      "btree",
      table.eventType.asc().nullsLast().op("text_ops")
    ),
    index("analytics_events_platform_idx").using(
      "btree",
      table.platform.asc().nullsLast().op("text_ops")
    ),
    index("analytics_events_timestamp_idx").using("btree", table.timestamp.desc().nullsLast()),
    index("analytics_events_session_id_idx").using(
      "btree",
      table.sessionId.asc().nullsLast().op("text_ops")
    )
  ]
);
var defaultLogger = {
  info: (message, data) => console.log(`[Analytics] ${message}`, data || ""),
  error: (message, error) => console.error(`[Analytics] ${message}`, error)
};
function createAnalyticsService(db, analyticsEventsTable, logger = defaultLogger) {
  const analyticsEvents2 = analyticsEventsTable;
  return {
    /**
     * 批量插入埋点事件
     */
    async insertAnalyticsEvents(events) {
      try {
        if (events.length === 0) return;
        await db.insert(analyticsEvents2).values(events).onConflictDoNothing();
        logger.info("Analytics events inserted", { count: events.length });
      } catch (error) {
        logger.error("Failed to insert analytics events", error);
        throw error;
      }
    },
    /**
     * 查询埋点事件
     */
    async queryAnalyticsEvents(params) {
      try {
        const conditions = [];
        if (params.startDate) {
          conditions.push(gte(analyticsEvents2.timestamp, params.startDate));
        }
        if (params.endDate) {
          conditions.push(lte(analyticsEvents2.timestamp, params.endDate));
        }
        if (params.eventType) {
          conditions.push(eq(analyticsEvents2.eventType, params.eventType));
        }
        if (params.eventTypes && params.eventTypes.length > 0) {
          conditions.push(inArray(analyticsEvents2.eventType, params.eventTypes));
        }
        if (params.userId) {
          conditions.push(eq(analyticsEvents2.userId, params.userId));
        }
        if (params.platform) {
          conditions.push(eq(analyticsEvents2.platform, params.platform));
        }
        if (params.platforms && params.platforms.length > 0) {
          conditions.push(inArray(analyticsEvents2.platform, params.platforms));
        }
        if (params.sessionId) {
          conditions.push(eq(analyticsEvents2.sessionId, params.sessionId));
        }
        const whereClause = conditions.length > 0 ? and(...conditions) : void 0;
        const [{ total }] = await db.select({ total: count() }).from(analyticsEvents2).where(whereClause);
        const orderByColumn = params.orderBy || "timestamp";
        const orderDirection = params.orderDirection || "desc";
        const orderFn = orderDirection === "asc" ? asc : desc;
        let orderByField;
        switch (orderByColumn) {
          case "eventType":
            orderByField = analyticsEvents2.eventType;
            break;
          case "platform":
            orderByField = analyticsEvents2.platform;
            break;
          default:
            orderByField = analyticsEvents2.timestamp;
        }
        const events = await db.select().from(analyticsEvents2).where(whereClause).orderBy(orderFn(orderByField)).limit(params.limit || 100).offset(params.offset || 0);
        const formattedEvents = events.map((event) => ({
          ...event,
          timestamp: event.timestamp.endsWith("Z") ? event.timestamp : `${event.timestamp}Z`,
          createdAt: event.createdAt.endsWith("Z") ? event.createdAt : `${event.createdAt}Z`
        }));
        return {
          events: formattedEvents,
          total: Number(total)
        };
      } catch (error) {
        logger.error("Failed to query analytics events", error);
        throw error;
      }
    },
    /**
     * 获取统计数据
     */
    async getAnalyticsStats(startDate, endDate, platform) {
      try {
        const conditions = [];
        if (startDate) {
          conditions.push(gte(analyticsEvents2.timestamp, startDate));
        }
        if (endDate) {
          conditions.push(lte(analyticsEvents2.timestamp, endDate));
        }
        if (platform) {
          conditions.push(eq(analyticsEvents2.platform, platform));
        }
        const whereClause = conditions.length > 0 ? and(...conditions) : void 0;
        const [{ totalEvents }] = await db.select({ totalEvents: count() }).from(analyticsEvents2).where(whereClause);
        const [{ uniqueUsers }] = await db.select({ uniqueUsers: sql`COUNT(DISTINCT ${analyticsEvents2.userId})` }).from(analyticsEvents2).where(whereClause);
        const [{ uniqueSessions }] = await db.select({ uniqueSessions: sql`COUNT(DISTINCT ${analyticsEvents2.sessionId})` }).from(analyticsEvents2).where(whereClause);
        const [{ uniqueDevices }] = await db.select({ uniqueDevices: sql`COUNT(DISTINCT ${analyticsEvents2.deviceId})` }).from(analyticsEvents2).where(whereClause);
        const eventsByType = await db.select({
          eventType: analyticsEvents2.eventType,
          count: count()
        }).from(analyticsEvents2).where(whereClause).groupBy(analyticsEvents2.eventType).orderBy(desc(count())).limit(10);
        const eventsByPlatform = await db.select({
          platform: analyticsEvents2.platform,
          count: count()
        }).from(analyticsEvents2).where(whereClause).groupBy(analyticsEvents2.platform).orderBy(desc(count()));
        const topPages = await db.select({
          pageUrl: analyticsEvents2.pageUrl,
          count: count()
        }).from(analyticsEvents2).where(and(whereClause, sql`${analyticsEvents2.pageUrl} IS NOT NULL`)).groupBy(analyticsEvents2.pageUrl).orderBy(desc(count())).limit(10);
        return {
          totalEvents: Number(totalEvents),
          uniqueUsers: Number(uniqueUsers),
          uniqueSessions: Number(uniqueSessions),
          uniqueDevices: Number(uniqueDevices),
          eventsByType: eventsByType.map((e) => ({
            eventType: e.eventType,
            count: Number(e.count)
          })),
          eventsByPlatform: eventsByPlatform.map((e) => ({
            platform: e.platform,
            count: Number(e.count)
          })),
          topPages: topPages.filter((p) => p.pageUrl).map((p) => ({
            pageUrl: p.pageUrl,
            count: Number(p.count)
          }))
        };
      } catch (error) {
        logger.error("Failed to get analytics stats", error);
        throw error;
      }
    },
    /**
     * 获取用户行为分析
     */
    async getUserBehavior(userId, startDate, endDate) {
      try {
        const conditions = [eq(analyticsEvents2.userId, userId)];
        if (startDate) {
          conditions.push(gte(analyticsEvents2.timestamp, startDate));
        }
        if (endDate) {
          conditions.push(lte(analyticsEvents2.timestamp, endDate));
        }
        const whereClause = and(...conditions);
        const [{ eventCount }] = await db.select({ eventCount: count() }).from(analyticsEvents2).where(whereClause);
        if (eventCount === 0) return null;
        const [{ lastActive }] = await db.select({ lastActive: sql`MAX(${analyticsEvents2.timestamp})` }).from(analyticsEvents2).where(whereClause);
        const platformsResult = await db.select({ platform: analyticsEvents2.platform }).from(analyticsEvents2).where(whereClause).groupBy(analyticsEvents2.platform);
        const topEvents = await db.select({
          eventType: analyticsEvents2.eventType,
          count: count()
        }).from(analyticsEvents2).where(whereClause).groupBy(analyticsEvents2.eventType).orderBy(desc(count())).limit(5);
        return {
          userId,
          eventCount: Number(eventCount),
          lastActive,
          platforms: platformsResult.map((p) => p.platform),
          topEvents: topEvents.map((e) => ({
            eventType: e.eventType,
            count: Number(e.count)
          }))
        };
      } catch (error) {
        logger.error("Failed to get user behavior", error);
        throw error;
      }
    },
    /**
     * 获取会话分析
     */
    async getSessionAnalytics(sessionId) {
      try {
        const events = await db.select().from(analyticsEvents2).where(eq(analyticsEvents2.sessionId, sessionId)).orderBy(asc(analyticsEvents2.timestamp));
        if (events.length === 0) return null;
        const firstEvent = events[0];
        const lastEvent = events[events.length - 1];
        const startTime = new Date(firstEvent.timestamp).getTime();
        const endTime = new Date(lastEvent.timestamp).getTime();
        const duration = endTime - startTime;
        return {
          sessionId,
          userId: firstEvent.userId || void 0,
          deviceId: firstEvent.deviceId,
          platform: firstEvent.platform,
          startTime: firstEvent.timestamp,
          endTime: lastEvent.timestamp,
          duration,
          eventCount: events.length,
          events
        };
      } catch (error) {
        logger.error("Failed to get session analytics", error);
        throw error;
      }
    },
    /**
     * 获取漏斗分析
     */
    async getFunnelAnalysis(steps, startDate, endDate) {
      try {
        const results = [];
        let previousCount = 0;
        for (let i = 0; i < steps.length; i++) {
          const conditions = [eq(analyticsEvents2.eventType, steps[i])];
          if (startDate) {
            conditions.push(gte(analyticsEvents2.timestamp, startDate));
          }
          if (endDate) {
            conditions.push(lte(analyticsEvents2.timestamp, endDate));
          }
          const whereClause = and(...conditions);
          const [{ count: stepCount }] = await db.select({ count: sql`COUNT(DISTINCT ${analyticsEvents2.userId})` }).from(analyticsEvents2).where(whereClause);
          const conversionRate = i === 0 ? 100 : Number(stepCount) / previousCount * 100;
          results.push({
            step: steps[i] || "unknown",
            count: Number(stepCount),
            conversionRate: Math.round(conversionRate * 100) / 100
          });
          previousCount = Number(stepCount);
        }
        return results;
      } catch (error) {
        logger.error("Failed to get funnel analysis", error);
        throw error;
      }
    },
    /**
     * 删除旧数据（数据清理）
     */
    async cleanOldAnalyticsEvents(daysToKeep = 90) {
      try {
        const cutoffDate = /* @__PURE__ */ new Date();
        cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
        await db.delete(analyticsEvents2).where(lte(analyticsEvents2.timestamp, cutoffDate.toISOString()));
        logger.info("Old analytics events cleaned", { daysToKeep });
        return 0;
      } catch (error) {
        logger.error("Failed to clean old analytics events", error);
        throw error;
      }
    }
  };
}

// src/analytics/server/handlers.ts
function createAnalyticsHandlers(service, ResponseClass) {
  const createResponse = ResponseClass ? (data, init) => ResponseClass.json(data, init) : (data, init) => ({ body: data, status: init?.status || 200 });
  return {
    /**
     * POST /api/analytics/events
     * 处理事件上报
     */
    async handleEventsPost(request) {
      try {
        const body = await request.json();
        const { events } = body;
        if (!Array.isArray(events)) {
          return createResponse(
            { success: false, message: "Invalid events format" },
            { status: 400 }
          );
        }
        if (events.length === 0) {
          return createResponse(
            { success: true, message: "No events to process" },
            { status: 200 }
          );
        }
        for (const event of events) {
          if (!event.event_id || !event.event_type || !event.event_name) {
            return createResponse(
              { success: false, message: "Missing required event fields" },
              { status: 400 }
            );
          }
        }
        const formattedEvents = events.map((event) => ({
          id: event.event_id,
          eventType: event.event_type,
          eventName: event.event_name,
          timestamp: new Date(event.timestamp).toISOString(),
          priority: event.priority,
          userId: event.user_id || null,
          sessionId: event.session_id,
          deviceId: event.device_id,
          pageUrl: event.page_url || null,
          pageTitle: event.page_title || null,
          referrer: event.referrer || null,
          properties: event.properties || {},
          platform: event.platform,
          appVersion: event.app_version,
          sdkVersion: event.sdk_version
        }));
        await service.insertAnalyticsEvents(formattedEvents);
        return createResponse({
          success: true,
          message: "Events received successfully",
          count: events.length
        });
      } catch (error) {
        console.error("Failed to process analytics events", error);
        return createResponse(
          {
            success: false,
            message: "Internal server error",
            error: process.env.NODE_ENV === "development" ? error.message : void 0
          },
          { status: 500 }
        );
      }
    },
    /**
     * GET /api/analytics/query
     * 查询埋点事件
     */
    async handleQueryGet(request) {
      try {
        const searchParams = request.nextUrl?.searchParams || new URLSearchParams(request.url?.split("?")[1]);
        const params = {
          startDate: searchParams.get("startDate") || void 0,
          endDate: searchParams.get("endDate") || void 0,
          eventType: searchParams.get("eventType") || void 0,
          eventTypes: searchParams.get("eventTypes")?.split(",") || void 0,
          userId: searchParams.get("userId") || void 0,
          platform: searchParams.get("platform") || void 0,
          platforms: searchParams.get("platforms")?.split(",") || void 0,
          sessionId: searchParams.get("sessionId") || void 0,
          limit: parseInt(searchParams.get("limit") || "100"),
          offset: parseInt(searchParams.get("offset") || "0"),
          orderBy: searchParams.get("orderBy") || "timestamp",
          orderDirection: searchParams.get("orderDirection") || "desc"
        };
        const result = await service.queryAnalyticsEvents(params);
        return createResponse({
          success: true,
          data: result.events,
          total: result.total,
          limit: params.limit,
          offset: params.offset
        });
      } catch (error) {
        console.error("Failed to query analytics events", error);
        return createResponse(
          {
            success: false,
            message: "Internal server error",
            error: process.env.NODE_ENV === "development" ? error.message : void 0
          },
          { status: 500 }
        );
      }
    },
    /**
     * GET /api/analytics/stats
     * 获取统计数据
     */
    async handleStatsGet(request) {
      try {
        const searchParams = request.nextUrl?.searchParams || new URLSearchParams(request.url?.split("?")[1]);
        const startDate = searchParams.get("startDate") || void 0;
        const endDate = searchParams.get("endDate") || void 0;
        const platform = searchParams.get("platform") || void 0;
        const stats = await service.getAnalyticsStats(startDate, endDate, platform);
        return createResponse({
          success: true,
          data: stats
        });
      } catch (error) {
        console.error("Failed to get analytics stats", error);
        return createResponse(
          {
            success: false,
            message: "Internal server error",
            error: process.env.NODE_ENV === "development" ? error.message : void 0
          },
          { status: 500 }
        );
      }
    },
    /**
     * GET /api/analytics/user/[userId]
     * 获取用户行为分析
     */
    async handleUserBehaviorGet(request, params) {
      try {
        const { userId } = params;
        const searchParams = request.nextUrl?.searchParams || new URLSearchParams(request.url?.split("?")[1]);
        const startDate = searchParams.get("startDate") || void 0;
        const endDate = searchParams.get("endDate") || void 0;
        const behavior = await service.getUserBehavior(userId, startDate, endDate);
        if (!behavior) {
          return createResponse(
            { success: false, message: "No data found for this user" },
            { status: 404 }
          );
        }
        return createResponse({
          success: true,
          data: behavior
        });
      } catch (error) {
        console.error("Failed to get user behavior", error);
        return createResponse(
          {
            success: false,
            message: "Internal server error",
            error: process.env.NODE_ENV === "development" ? error.message : void 0
          },
          { status: 500 }
        );
      }
    },
    /**
     * GET /api/analytics/session/[sessionId]
     * 获取会话分析
     */
    async handleSessionAnalyticsGet(_request, params) {
      try {
        const { sessionId } = params;
        const session = await service.getSessionAnalytics(sessionId);
        if (!session) {
          return createResponse({ success: false, message: "Session not found" }, { status: 404 });
        }
        return createResponse({
          success: true,
          data: session
        });
      } catch (error) {
        console.error("Failed to get session analytics", error);
        return createResponse(
          {
            success: false,
            message: "Internal server error",
            error: process.env.NODE_ENV === "development" ? error.message : void 0
          },
          { status: 500 }
        );
      }
    },
    /**
     * POST /api/analytics/funnel
     * 漏斗分析
     */
    async handleFunnelPost(request) {
      try {
        const body = await request.json();
        const { steps, startDate, endDate } = body;
        if (!Array.isArray(steps) || steps.length === 0) {
          return createResponse(
            { success: false, message: "Invalid steps format" },
            { status: 400 }
          );
        }
        const funnel = await service.getFunnelAnalysis(steps, startDate, endDate);
        return createResponse({
          success: true,
          data: funnel
        });
      } catch (error) {
        console.error("Failed to get funnel analysis", error);
        return createResponse(
          {
            success: false,
            message: "Internal server error",
            error: process.env.NODE_ENV === "development" ? error.message : void 0
          },
          { status: 500 }
        );
      }
    }
  };
}

export { analyticsEvents, createAnalyticsHandlers, createAnalyticsService };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map