import { pgTable, text, timestamp, integer, boolean, real } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod/v4";
import { nostrIdentities } from "./nostr-identities";

// ── Session state machine ─────────────────────────────────────────────────────

export const SESSION_STATES = [
  "awaiting_payment",
  "active",
  "paused",
  "expired",
] as const;
export type SessionState = (typeof SESSION_STATES)[number];

export const SESSION_REQUEST_STATES = [
  "processing",
  "complete",
  "rejected",
  "failed",
] as const;
export type SessionRequestState = (typeof SESSION_REQUEST_STATES)[number];

// ── sessions ──────────────────────────────────────────────────────────────────

export const sessions = pgTable("sessions", {
  id: text("id").primaryKey(),
  state: text("state").$type<SessionState>().notNull().default("awaiting_payment"),

  balanceSats: integer("balance_sats").notNull().default(0),
  depositAmountSats: integer("deposit_amount_sats").notNull(),

  // Deposit invoice (stored inline — avoids FK into jobs table)
  depositPaymentHash: text("deposit_payment_hash").notNull(),
  depositPaymentRequest: text("deposit_payment_request").notNull(),
  depositPaid: boolean("deposit_paid").notNull().default(false),

  // Current topup invoice (one at a time; all nullable until created)
  topupAmountSats: integer("topup_amount_sats"),
  topupPaymentHash: text("topup_payment_hash"),
  topupPaymentRequest: text("topup_payment_request"),
  topupPaid: boolean("topup_paid"),

  // Auth token — issued once when session activates; required for requests
  macaroon: text("macaroon"),

  // Optional Nostr identity bound at session creation (FK → nostr_identities.pubkey)
  nostrPubkey: text("nostr_pubkey").references(() => nostrIdentities.pubkey),

  // TTL — refreshed on each successful request
  expiresAt: timestamp("expires_at", { withTimezone: true }),

  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
});

export const insertSessionSchema = createInsertSchema(sessions).omit({
  createdAt: true,
  updatedAt: true,
});

export type Session = typeof sessions.$inferSelect;
export type InsertSession = z.infer<typeof insertSessionSchema>;

// ── session_requests ──────────────────────────────────────────────────────────

export const sessionRequests = pgTable("session_requests", {
  id: text("id").primaryKey(),
  sessionId: text("session_id")
    .notNull()
    .references(() => sessions.id),
  request: text("request").notNull(),
  state: text("state")
    .$type<SessionRequestState>()
    .notNull()
    .default("processing"),

  result: text("result"),
  reason: text("reason"),
  errorMessage: text("error_message"),

  // Eval token usage (Haiku judge)
  evalInputTokens: integer("eval_input_tokens"),
  evalOutputTokens: integer("eval_output_tokens"),

  // Work token usage (Sonnet; null for rejected requests)
  workInputTokens: integer("work_input_tokens"),
  workOutputTokens: integer("work_output_tokens"),

  // Balance debit for this request
  debitedSats: integer("debited_sats"),
  balanceAfterSats: integer("balance_after_sats"),
  btcPriceUsd: real("btc_price_usd"),

  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
});

export const insertSessionRequestSchema = createInsertSchema(sessionRequests).omit({
  createdAt: true,
  updatedAt: true,
});

export type SessionRequest = typeof sessionRequests.$inferSelect;
export type InsertSessionRequest = z.infer<typeof insertSessionRequestSchema>;
