import { getDb } from "../db.ts";
import { eq, desc, and, gte, lte } from "drizzle-orm";
import { transactions, users } from "../../drizzle/schema.ts";

export interface BonusDistribution {
  id: number;
  userId: number;
  userName: string;
  userEmail: string;
  amount: string;
  currency: "GC" | "SC";
  reason: string;
  createdAt: string;
  adminId: number;
}

export interface BonusHistoryStats {
  totalDistributed: {
    GC: string;
    SC: string;
  };
  totalRecipients: number;
  averageAmount: {
    GC: string;
    SC: string;
  };
  distributionCount: number;
}

/**
 * Get bonus distribution history with pagination
 */
export async function getBonusHistory(
  limit: number = 50,
  offset: number = 0,
  startDate?: Date,
  endDate?: Date
): Promise<BonusDistribution[]> {
  const db = await getDb();
  if (!db) return [];

  let query = db
    .select({
      id: transactions.id,
      userId: transactions.userId,
      userName: users.name,
      userEmail: users.email,
      amount: transactions.amount,
      currency: transactions.currency,
      reason: transactions.description,
      createdAt: transactions.createdAt,
      adminId: transactions.userId, // Will be updated with actual admin ID from audit logs
    })
    .from(transactions)
    .leftJoin(users, eq(transactions.userId, users.id))
    .where(
      and(
        eq(transactions.type, "admin_bonus"),
        startDate ? gte(transactions.createdAt, startDate) : undefined,
        endDate ? lte(transactions.createdAt, endDate) : undefined
      )
    )
    .orderBy(desc(transactions.createdAt))
    .limit(limit)
    .offset(offset);

  try {
    const result = await query;
    return result.map((r: any) => ({
      id: r.id,
      userId: r.userId,
      userName: r.userName,
      userEmail: r.userEmail,
      amount: r.amount,
      currency: r.currency,
      reason: r.reason,
      createdAt: r.createdAt,
      adminId: r.adminId,
    })) as BonusDistribution[];
  } catch (error) {
    console.error("[BonusHistory] Error fetching bonus history:", error);
    return [];
  }
}

/**
 * Get bonus distribution statistics
 */
export async function getBonusHistoryStats(
  startDate?: Date,
  endDate?: Date
): Promise<BonusHistoryStats> {
  const db = await getDb();
  if (!db)
    return {
      totalDistributed: { GC: "0", SC: "0" },
      totalRecipients: 0,
      averageAmount: { GC: "0", SC: "0" },
      distributionCount: 0,
    };

  try {
    // Get all bonus transactions in date range
    const bonuses = await db
      .select({
        userId: transactions.userId,
        amount: transactions.amount,
        currency: transactions.currency,
      })
      .from(transactions)
      .where(
        and(
          eq(transactions.type, "admin_bonus"),
          startDate ? gte(transactions.createdAt, startDate) : undefined,
          endDate ? lte(transactions.createdAt, endDate) : undefined
        )
      );

    // Calculate statistics
    let totalGC = 0;
    let totalSC = 0;
    const uniqueUsers = new Set<number>();

    for (const bonus of bonuses) {
      uniqueUsers.add(bonus.userId);
      const amount = parseFloat(bonus.amount);
      if (bonus.currency === "GC") {
        totalGC += amount;
      } else {
        totalSC += amount;
      }
    }

    const gcCount = bonuses.filter((b) => b.currency === "GC").length;
    const scCount = bonuses.filter((b) => b.currency === "SC").length;

    return {
      totalDistributed: {
        GC: totalGC.toFixed(2),
        SC: totalSC.toFixed(2),
      },
      totalRecipients: uniqueUsers.size,
      averageAmount: {
        GC: gcCount > 0 ? (totalGC / gcCount).toFixed(2) : "0",
        SC: scCount > 0 ? (totalSC / scCount).toFixed(2) : "0",
      },
      distributionCount: bonuses.length,
    };
  } catch (error) {
    console.error("[BonusHistory] Error calculating stats:", error);
    return {
      totalDistributed: { GC: "0", SC: "0" },
      totalRecipients: 0,
      averageAmount: { GC: "0", SC: "0" },
      distributionCount: 0,
    };
  }
}

/**
 * Get bonus distribution by user
 */
export async function getUserBonusHistory(
  userId: number,
  limit: number = 50,
  offset: number = 0
): Promise<BonusDistribution[]> {
  const db = await getDb();
  if (!db) return [];

  try {
    const result = await db
      .select({
        id: transactions.id,
        userId: transactions.userId,
        userName: users.name,
        userEmail: users.email,
        amount: transactions.amount,
        currency: transactions.currency,
        reason: transactions.description,
        createdAt: transactions.createdAt,
        adminId: transactions.userId,
      })
      .from(transactions)
      .leftJoin(users, eq(transactions.userId, users.id))
      .where(
        and(
          eq(transactions.userId, userId),
          eq(transactions.type, "admin_bonus")
        )
      )
      .orderBy(desc(transactions.createdAt))
      .limit(limit)
      .offset(offset);

    return result.map((r: any) => ({
      id: r.id,
      userId: r.userId,
      userName: r.userName,
      userEmail: r.userEmail,
      amount: r.amount,
      currency: r.currency,
      reason: r.reason,
      createdAt: r.createdAt,
      adminId: r.adminId,
    })) as BonusDistribution[];
  } catch (error) {
    console.error("[BonusHistory] Error fetching user bonus history:", error);
    return [];
  }
}

/**
 * Get total bonuses received by user
 */
export async function getUserTotalBonuses(userId: number): Promise<{
  GC: string;
  SC: string;
}> {
  const db = await getDb();
  if (!db) return { GC: "0", SC: "0" };

  try {
    const bonuses = await db
      .select({
        amount: transactions.amount,
        currency: transactions.currency,
      })
      .from(transactions)
      .where(
        and(
          eq(transactions.userId, userId),
          eq(transactions.type, "admin_bonus")
        )
      );

    let totalGC = 0;
    let totalSC = 0;

    for (const bonus of bonuses) {
      const amount = parseFloat(bonus.amount);
      if (bonus.currency === "GC") {
        totalGC += amount;
      } else {
        totalSC += amount;
      }
    }

    return {
      GC: totalGC.toFixed(2),
      SC: totalSC.toFixed(2),
    };
  } catch (error) {
    console.error("[BonusHistory] Error calculating user total bonuses:", error);
    return { GC: "0", SC: "0" };
  }
}
