import { db, eq } from "@haushaltsApp/db";
import { householdSettings } from "@haushaltsApp/db/schema";
import type { UpdateHouseholdSettingsInput } from "@haushaltsApp/shared/schemas/household-settings.schema";

export type HouseholdSettings = {
  id: string;
  householdId: string;
  ownerName: string;
  partnerName: string;
  userSharePercent: number;
  monthlyBudget: number;
  currency: string;
  splitChildCosts: boolean;
  payerUserId: string | null;
  onboardingComplete: boolean;
  language: string;
  createdAt: Date;
  updatedAt: Date;
};

function mapRow(row: typeof householdSettings.$inferSelect): HouseholdSettings {
  return {
    id: row.id,
    householdId: row.householdId,
    ownerName: row.ownerName,
    partnerName: row.partnerName,
    userSharePercent: parseFloat(row.userSharePercent),
    monthlyBudget: parseFloat(row.monthlyBudget),
    currency: row.currency,
    splitChildCosts: row.splitChildCosts,
    payerUserId: row.payerUserId,
    onboardingComplete: row.onboardingComplete,
    language: row.language,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
  };
}

const DEFAULTS: Omit<HouseholdSettings, "id" | "householdId" | "createdAt" | "updatedAt"> = {
  ownerName: "Ich",
  partnerName: "Partner",
  userSharePercent: 50,
  monthlyBudget: 400,
  currency: "EUR",
  splitChildCosts: true,
  payerUserId: null,
  onboardingComplete: false,
  language: "auto",
};

export async function getOrCreateHouseholdSettings(householdId: string): Promise<HouseholdSettings> {
  const existing = await db
    .select()
    .from(householdSettings)
    .where(eq(householdSettings.householdId, householdId))
    .limit(1);

  if (existing[0]) return mapRow(existing[0]);

  // Auto-create with defaults (idempotent — safe to call multiple times)
  const [created] = await db
    .insert(householdSettings)
    .values({ householdId })
    .onConflictDoNothing()
    .returning();

  if (created) return mapRow(created);

  // Race condition: another request created it first
  const retry = await db
    .select()
    .from(householdSettings)
    .where(eq(householdSettings.householdId, householdId))
    .limit(1);

  return mapRow(retry[0]!);
}

export async function updateHouseholdSettings(
  householdId: string,
  input: UpdateHouseholdSettingsInput,
): Promise<HouseholdSettings> {
  const values: Partial<typeof householdSettings.$inferInsert> = {};
  if (input.ownerName !== undefined) values.ownerName = input.ownerName;
  if (input.partnerName !== undefined) values.partnerName = input.partnerName;
  if (input.userSharePercent !== undefined) values.userSharePercent = String(input.userSharePercent);
  if (input.monthlyBudget !== undefined) values.monthlyBudget = String(input.monthlyBudget);
  if (input.currency !== undefined) values.currency = input.currency;
  if (input.splitChildCosts !== undefined) values.splitChildCosts = input.splitChildCosts;
  if (input.payerUserId !== undefined) values.payerUserId = input.payerUserId;
  if (input.onboardingComplete !== undefined) values.onboardingComplete = input.onboardingComplete;
  if (input.language !== undefined) values.language = input.language;

  const [row] = await db
    .update(householdSettings)
    .set(values)
    .where(eq(householdSettings.householdId, householdId))
    .returning();

  if (row) return mapRow(row);

  // Settings don't exist yet — create then update
  await getOrCreateHouseholdSettings(householdId);
  return updateHouseholdSettings(householdId, input);
}

export { DEFAULTS as HOUSEHOLD_SETTINGS_DEFAULTS };
