import { Type, type Static } from "@sinclair/typebox";

import { CreditSummarySchema } from "./auth.js";

const uuidPattern = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$";
const isoTimestampPattern = "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$";

export const CreditEntryTypeSchema = Type.Union([
  Type.Literal("registration_grant"), Type.Literal("generation_reserve"), Type.Literal("generation_commit"),
  Type.Literal("generation_release"), Type.Literal("admin_adjustment"),
], { $id: "CreditEntryType" });
export const CreditEntryStatusSchema = Type.Union([
  Type.Literal("succeeded"), Type.Literal("frozen"), Type.Literal("committed"), Type.Literal("released"),
], { $id: "CreditEntryStatus" });
export const CreditReferenceTypeSchema = Type.Union([
  Type.Literal("registration"), Type.Literal("generation"), Type.Literal("admin_adjustment"),
], { $id: "CreditReferenceType" });
export const CreditBalanceResponseSchema = Type.Object({
  ...CreditSummarySchema.properties,
  updated_at: Type.String({ pattern: isoTimestampPattern }),
}, { additionalProperties: false, $id: "CreditBalanceResponse" });
export const CreditLedgerEntrySchema = Type.Object({
  amount: Type.Integer(),
  available_after: Type.Integer(),
  available_before: Type.Integer(),
  created_at: Type.String({ pattern: isoTimestampPattern }),
  entry_id: Type.String({ pattern: uuidPattern }),
  entry_type: Type.Ref(CreditEntryTypeSchema),
  model_id: Type.Union([Type.String({ maxLength: 160, minLength: 1 }), Type.Null()]),
  reason: Type.Union([Type.String({ maxLength: 500, minLength: 1 }), Type.Null()]),
  reference_id: Type.Union([Type.String({ pattern: uuidPattern }), Type.Null()]),
  reference_type: Type.Union([Type.Ref(CreditReferenceTypeSchema), Type.Null()]),
  reserved_after: Type.Integer({ minimum: 0 }),
  reserved_before: Type.Integer({ minimum: 0 }),
  status: Type.Ref(CreditEntryStatusSchema),
}, { additionalProperties: false, $id: "CreditLedgerEntry" });
export const CreditLedgerQuerySchema = Type.Object({
  cursor: Type.Optional(Type.String({ maxLength: 300, minLength: 1, pattern: "^[A-Za-z0-9_-]+$" })),
  event_type: Type.Optional(Type.Ref(CreditEntryTypeSchema)),
  from: Type.Optional(Type.String({ pattern: isoTimestampPattern })),
  limit: Type.Optional(Type.Integer({ maximum: 100, minimum: 1 })),
  to: Type.Optional(Type.String({ pattern: isoTimestampPattern })),
}, { additionalProperties: false, $id: "CreditLedgerQuery" });
export const CreditLedgerResponseSchema = Type.Object({
  credits: Type.Ref(CreditSummarySchema),
  entries: Type.Array(Type.Ref(CreditLedgerEntrySchema), { maxItems: 100 }),
  next_cursor: Type.Union([Type.String({ maxLength: 300, minLength: 1 }), Type.Null()]),
  updated_at: Type.String({ pattern: isoTimestampPattern }),
}, { additionalProperties: false, $id: "CreditLedgerResponse" });
export const AdminCreditParamsSchema = Type.Object({
  userId: Type.String({ pattern: uuidPattern }),
}, { additionalProperties: false, $id: "AdminCreditParams" });
export const CreditAdjustmentHeadersSchema = Type.Object({
  "idempotency-key": Type.String({ maxLength: 200, minLength: 32, pattern: "^[A-Za-z0-9_-]+$" }),
  "x-csrf-token": Type.String({ maxLength: 64, minLength: 43, pattern: "^[A-Za-z0-9_-]+$" }),
}, { additionalProperties: true, $id: "CreditAdjustmentHeaders" });
export const CreditAdjustmentRequestSchema = Type.Object({
  adjustment_id: Type.String({ pattern: uuidPattern }),
  amount: Type.Union([Type.Integer({ maximum: -1 }), Type.Integer({ minimum: 1 })]),
  reason: Type.String({ maxLength: 500, minLength: 1 }),
}, { additionalProperties: false, $id: "CreditAdjustmentRequest" });
export const CreditAdjustmentResponseSchema = Type.Object({
  adjustment_id: Type.String({ pattern: uuidPattern }),
  available_balance: Type.Integer(),
  reserved_balance: Type.Integer({ minimum: 0 }),
  status: Type.Literal("adjusted"),
}, { additionalProperties: false, $id: "CreditAdjustmentResponse" });

export type CreditLedgerQuery = Static<typeof CreditLedgerQuerySchema>;
export type AdminCreditParams = Static<typeof AdminCreditParamsSchema>;
export type CreditAdjustmentHeaders = Static<typeof CreditAdjustmentHeadersSchema>;
export type CreditAdjustmentRequest = Static<typeof CreditAdjustmentRequestSchema>;
