import { getDb } from "../db.ts";
import { users, wallets, gameStats } from "../../drizzle/schema.ts";
import { eq } from "drizzle-orm";

export type PlayerSegment =
  | "high_spender"
  | "mid_spender"
  | "low_spender"
  | "whale"
  | "casual"
  | "hardcore"
  | "inactive"
  | "new_player"
  | "vip_member"
  | "referrer";

export interface PlayerProfile {
  userId: number;
  email: string;
  totalSpent: number;
  totalWagered: number;
  sessionCount: number;
  averageSessionLength: number;
  favoriteGameType: string | null;
  lastLoginDaysAgo: number;
  accountAgeDays: number;
  segments: PlayerSegment[];
}

export async function getPlayerProfile(userId: number): Promise<PlayerProfile | null> {
  const db = await getDb();
  if (!db) return null;

  const user = await db.select().from(users).where(eq(users.id, userId)).limit(1);
  if (user.length === 0) return null;

  const userData = user[0];
  const wallet = await db
    .select()
    .from(wallets)
    .where(eq(wallets.userId, userId))
    .limit(1);

  const stats = await db
    .select()
    .from(gameStats)
    .where(eq(gameStats.userId, userId));

  const totalSpent = wallet.length > 0 ? wallet[0].totalSpent || 0 : 0;
  const totalWagered = stats.reduce((sum, stat) => sum + (stat.totalWagered || 0), 0);
  const sessionCount = stats.length;
  const averageSessionLength =
    sessionCount > 0
      ? stats.reduce((sum, stat) => sum + (stat.sessionDuration || 0), 0) /
        sessionCount
      : 0;

  const lastLogin = userData.lastLoginAt
    ? new Date(userData.lastLoginAt)
    : new Date();
  const lastLoginDaysAgo = Math.floor(
    (Date.now() - lastLogin.getTime()) / (1000 * 60 * 60 * 24)
  );

  const accountAge = userData.createdAt ? new Date(userData.createdAt) : new Date();
  const accountAgeDays = Math.floor(
    (Date.now() - accountAge.getTime()) / (1000 * 60 * 60 * 24)
  );

  const favoriteGameType =
    stats.length > 0
      ? stats.reduce((prev, current) =>
          (prev.wins || 0) > (current.wins || 0) ? prev : current
        ).gameType || null
      : null;

  const segments = classifyPlayer({
    totalSpent,
    totalWagered,
    sessionCount,
    lastLoginDaysAgo,
    accountAgeDays,
  });

  return {
    userId,
    email: userData.email,
    totalSpent,
    totalWagered,
    sessionCount,
    averageSessionLength,
    favoriteGameType,
    lastLoginDaysAgo,
    accountAgeDays,
    segments,
  };
}

function classifyPlayer(data: {
  totalSpent: number;
  totalWagered: number;
  sessionCount: number;
  lastLoginDaysAgo: number;
  accountAgeDays: number;
}): PlayerSegment[] {
  const segments: PlayerSegment[] = [];

  // Spending-based segments
  if (data.totalSpent > 1000) {
    segments.push("whale");
    segments.push("high_spender");
  } else if (data.totalSpent > 100) {
    segments.push("mid_spender");
  } else if (data.totalSpent > 0) {
    segments.push("low_spender");
  }

  // Engagement-based segments
  if (data.sessionCount > 50) {
    segments.push("hardcore");
  } else if (data.sessionCount > 10) {
    segments.push("casual");
  }

  // Activity-based segments
  if (data.lastLoginDaysAgo > 30) {
    segments.push("inactive");
  }

  // Account age-based segments
  if (data.accountAgeDays < 7) {
    segments.push("new_player");
  }

  // VIP segment (would be based on actual VIP tier)
  if (data.totalSpent > 500 && data.sessionCount > 20) {
    segments.push("vip_member");
  }

  return [...new Set(segments)];
}

export async function getSegmentedPlayers(
  segment: PlayerSegment
): Promise<PlayerProfile[]> {
  const db = await getDb();
  if (!db) return [];

  const allUsers = await db.select().from(users);
  const profiles: PlayerProfile[] = [];

  for (const user of allUsers) {
    const profile = await getPlayerProfile(user.id);
    if (profile && profile.segments.includes(segment)) {
      profiles.push(profile);
    }
  }

  return profiles;
}

export async function getMultiSegmentPlayers(
  segments: PlayerSegment[]
): Promise<PlayerProfile[]> {
  const db = await getDb();
  if (!db) return [];

  const allUsers = await db.select().from(users);
  const profiles: PlayerProfile[] = [];

  for (const user of allUsers) {
    const profile = await getPlayerProfile(user.id);
    if (
      profile &&
      segments.some((seg) => profile.segments.includes(seg))
    ) {
      profiles.push(profile);
    }
  }

  return profiles;
}

export async function getSegmentStatistics(
  segment: PlayerSegment
): Promise<{
  count: number;
  averageSpent: number;
  averageWagered: number;
  averageSessionCount: number;
  churnRate: number;
}> {
  const players = await getSegmentedPlayers(segment);

  if (players.length === 0) {
    return {
      count: 0,
      averageSpent: 0,
      averageWagered: 0,
      averageSessionCount: 0,
      churnRate: 0,
    };
  }

  const averageSpent =
    players.reduce((sum, p) => sum + p.totalSpent, 0) / players.length;
  const averageWagered =
    players.reduce((sum, p) => sum + p.totalWagered, 0) / players.length;
  const averageSessionCount =
    players.reduce((sum, p) => sum + p.sessionCount, 0) / players.length;

  const inactivePlayers = players.filter((p) => p.lastLoginDaysAgo > 30).length;
  const churnRate = (inactivePlayers / players.length) * 100;

  return {
    count: players.length,
    averageSpent: Math.round(averageSpent * 100) / 100,
    averageWagered: Math.round(averageWagered * 100) / 100,
    averageSessionCount: Math.round(averageSessionCount * 100) / 100,
    churnRate: Math.round(churnRate * 100) / 100,
  };
}

export async function runABTest(
  segment: PlayerSegment,
  controlPercentage: number = 50
): Promise<{
  controlGroup: number[];
  treatmentGroup: number[];
}> {
  const players = await getSegmentedPlayers(segment);
  const shuffled = [...players].sort(() => Math.random() - 0.5);

  const splitIndex = Math.floor((shuffled.length * controlPercentage) / 100);

  return {
    controlGroup: shuffled.slice(0, splitIndex).map((p) => p.userId),
    treatmentGroup: shuffled.slice(splitIndex).map((p) => p.userId),
  };
}


/**
 * Theme preference analysis for segments
 */
export interface ThemePreferenceAnalysis {
  segment: PlayerSegment;
  themePreferences: Record<string, number>;
  topThemes: string[];
  recommendedGames: string[];
}

export async function analyzeThemePreferences(
  segment: PlayerSegment
): Promise<ThemePreferenceAnalysis> {
  const players = await getSegmentedPlayers(segment);

  if (players.length === 0) {
    return {
      segment,
      themePreferences: {},
      topThemes: [],
      recommendedGames: [],
    };
  }

  // Mock theme preferences based on segment
  const themePreferences: Record<string, number> = {};

  if (segment === "whale" || segment === "high_spender") {
    themePreferences["Luxury"] = 0.35;
    themePreferences["Vegas"] = 0.3;
    themePreferences["Asian"] = 0.25;
    themePreferences["Ocean"] = 0.1;
  } else if (segment === "casual" || segment === "low_spender") {
    themePreferences["Fruit Slots"] = 0.4;
    themePreferences["Holiday"] = 0.25;
    themePreferences["Retro"] = 0.2;
    themePreferences["Vegas"] = 0.15;
  } else if (segment === "new_player") {
    themePreferences["Fruit Slots"] = 0.35;
    themePreferences["Ocean"] = 0.3;
    themePreferences["Holiday"] = 0.2;
    themePreferences["Vegas"] = 0.15;
  } else if (segment === "vip_member") {
    themePreferences["Luxury"] = 0.38;
    themePreferences["Asian"] = 0.32;
    themePreferences["Vegas"] = 0.3;
  } else {
    themePreferences["Fruit Slots"] = 0.3;
    themePreferences["Vegas"] = 0.25;
    themePreferences["Ocean"] = 0.2;
    themePreferences["Asian"] = 0.15;
    themePreferences["Holiday"] = 0.1;
  }

  const topThemes = Object.entries(themePreferences)
    .sort(([, a], [, b]) => b - a)
    .slice(0, 3)
    .map(([theme]) => theme);

  const recommendedGames = mapThemesToGames(topThemes);

  return {
    segment,
    themePreferences,
    topThemes,
    recommendedGames,
  };
}

function mapThemesToGames(themes: string[]): string[] {
  const themeGameMap: Record<string, string> = {
    Luxury: "Luxury Life",
    Vegas: "Vegas Nights",
    Asian: "Lucky Dragon",
    Ocean: "Ocean Treasure",
    "Fruit Slots": "Fruit Slots",
    Holiday: "Holiday Celebration",
    Retro: "Retro Arcade",
  };

  return themes.map((theme) => themeGameMap[theme] || theme);
}

/**
 * Predict segment response to new game
 */
export function predictSegmentResponse(
  segment: PlayerSegment,
  gameTheme: string,
  gameRTP: number
): {
  adoptionRate: number;
  expectedRevenue: number;
  confidence: number;
} {
  // Mock theme match based on segment preferences
  let themeMatch = 0;

  if (segment === "whale" || segment === "high_spender") {
    if (["Luxury", "Vegas", "Asian"].includes(gameTheme)) themeMatch = 0.8;
    else if (["Ocean"].includes(gameTheme)) themeMatch = 0.5;
    else themeMatch = 0.2;
  } else if (segment === "casual" || segment === "low_spender") {
    if (["Fruit Slots", "Holiday", "Retro"].includes(gameTheme)) themeMatch = 0.8;
    else if (["Vegas"].includes(gameTheme)) themeMatch = 0.5;
    else themeMatch = 0.2;
  } else if (segment === "new_player") {
    if (["Fruit Slots", "Ocean", "Holiday"].includes(gameTheme)) themeMatch = 0.8;
    else themeMatch = 0.4;
  } else {
    themeMatch = 0.5;
  }

  const rtpBonus = gameRTP > 96 ? 1.1 : gameRTP < 95 ? 0.9 : 1.0;
  const adoptionRate = Math.min(themeMatch * rtpBonus * 0.7, 0.8);
  const expectedRevenue = adoptionRate * 1000; // Mock revenue
  const confidence = Math.min(0.5 + themeMatch * 0.5, 1.0);

  return { adoptionRate, expectedRevenue, confidence };
}
