import { eq, and } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";

export type ParticipantResult = typeof schema.participantResults.$inferSelect;
export type ParticipantResultWithParticipant = ParticipantResult & {
  participant: { id: string; name: string } | null;
};
export type NewParticipantResult = typeof schema.participantResults.$inferInsert;

export async function createParticipantResult(
  data: NewParticipantResult
): Promise<ParticipantResult> {
  const db = database();
  const [result] = await db
    .insert(schema.participantResults)
    .values(data)
    .returning();
  return result;
}

export async function createManyParticipantResults(
  data: NewParticipantResult[]
): Promise<ParticipantResult[]> {
  const db = database();
  return await db
    .insert(schema.participantResults)
    .values(data)
    .returning();
}

export async function findParticipantResultById(
  id: string
): Promise<ParticipantResult | undefined> {
  const db = database();
  return await db.query.participantResults.findFirst({
    where: eq(schema.participantResults.id, id),
    with: {
      participant: true,
      sportsSeason: {
        with: {
          sport: true,
        },
      },
    },
  });
}

export async function findParticipantResultByParticipantId(
  participantId: string
): Promise<ParticipantResult | undefined> {
  const db = database();
  return await db.query.participantResults.findFirst({
    where: eq(schema.participantResults.participantId, participantId),
    with: {
      participant: true,
      sportsSeason: {
        with: {
          sport: true,
        },
      },
    },
  });
}

export async function findParticipantResultsBySportsSeasonId(
  sportsSeasonId: string
): Promise<ParticipantResultWithParticipant[]> {
  const db = database();
  return await db.query.participantResults.findMany({
    where: eq(schema.participantResults.sportsSeasonId, sportsSeasonId),
    orderBy: (results, { asc }) => [asc(results.finalPosition)],
    with: {
      participant: true,
    },
  });
}

export async function updateParticipantResult(
  id: string,
  data: Partial<NewParticipantResult>
): Promise<ParticipantResult> {
  const db = database();
  const [result] = await db
    .update(schema.participantResults)
    .set({ ...data, updatedAt: new Date() })
    .where(eq(schema.participantResults.id, id))
    .returning();
  return result;
}

export async function deleteParticipantResult(id: string): Promise<void> {
  const db = database();
  await db.delete(schema.participantResults).where(eq(schema.participantResults.id, id));
}

export async function deleteParticipantResultsBySportsSeasonId(
  sportsSeasonId: string
): Promise<void> {
  const db = database();
  await db
    .delete(schema.participantResults)
    .where(eq(schema.participantResults.sportsSeasonId, sportsSeasonId));
}

/**
 * Set result for a participant in a sports season
 * Points are calculated on-demand based on each fantasy league's scoring rules
 */
export async function setParticipantResult(
  participantId: string,
  sportsSeasonId: string,
  finalPosition: number,
  qualifyingPoints?: number,
  notes?: string
): Promise<ParticipantResult> {
  const db = database();

  // Check if result already exists
  const existing = await db.query.participantResults.findFirst({
    where: and(
      eq(schema.participantResults.participantId, participantId),
      eq(schema.participantResults.sportsSeasonId, sportsSeasonId)
    ),
  });

  if (existing) {
    // Update existing result
    return await updateParticipantResult(existing.id, {
      finalPosition,
      qualifyingPoints: qualifyingPoints?.toString(),
      notes,
    });
  } else {
    // Create new result
    return await createParticipantResult({
      participantId,
      sportsSeasonId,
      finalPosition,
      qualifyingPoints: qualifyingPoints?.toString(),
      notes,
    });
  }
}
