/// Typed-item shared TypeScript types.
///
/// These mirror the Rust core's serde serialization. See
/// crates/relicario-core/src/item.rs, item_types/, and settings.rs
/// for the source shapes.

// --- IDs ---

export type ItemId = string;       // 16-char hex
export type FieldId = string;      // 16-char hex
export type AttachmentId = string; // 16-char hex (sha256 of plaintext, truncated)

// --- ItemType / ItemCore ---

// snake_case from serde rename_all
export type ItemType =
  | 'login' | 'secure_note' | 'identity' | 'card' | 'key' | 'document' | 'totp';

// ItemCore is internally-tagged on "type":
//   Login → { type: 'login', username, password, url, totp }
export type ItemCore =
  | ({ type: 'login' }       & LoginCore)
  | ({ type: 'secure_note' } & SecureNoteCore)
  | ({ type: 'identity' }    & IdentityCore)
  | ({ type: 'card' }        & CardCore)
  | ({ type: 'key' }         & KeyCore)
  | ({ type: 'document' }    & DocumentCore)
  | ({ type: 'totp' }        & TotpCore);

// Optional fields use `?` because Rust #[serde(skip_serializing_if = "Option::is_none")]
// omits them from the JSON; serde_wasm_bindgen produces `undefined` on read.

export interface LoginCore {
  username?: string;
  password?: string;
  url?: string;
  totp?: TotpConfig;
}

export interface SecureNoteCore { body: string; }

export interface IdentityCore {
  full_name?: string;
  address?: string;
  phone?: string;
  email?: string;
  date_of_birth?: string;           // "YYYY-MM-DD"
}

export interface CardCore {
  number?: string;
  holder?: string;
  expiry?: { month: number; year: number };
  cvv?: string;
  pin?: string;
  kind: CardKind;
}

export type CardKind = 'credit' | 'debit' | 'gift' | 'loyalty' | 'other';

export interface KeyCore {
  key_material: string;
  label?: string;
  public_key?: string;
  algorithm?: string;
}

export interface DocumentCore {
  filename: string;
  mime_type: string;
  primary_attachment: AttachmentId;
}

export interface TotpCore {
  config: TotpConfig;
  issuer?: string;
  label?: string;
}

// --- TOTP ---

export type TotpKind = 'totp' | 'steam' | { hotp: { counter: number } };

export interface TotpConfig {
  secret: number[];                 // Vec<u8> → JSON number array
  algorithm: 'sha1' | 'sha256' | 'sha512';
  digits: number;
  period_seconds: number;
  kind: TotpKind;
}

// --- Sections + custom fields ---

export interface Section {
  name?: string;
  fields: Field[];
}

export interface Field {
  id: FieldId;
  label: string;
  kind: FieldKind;
  value: FieldValue;
  hidden_by_default: boolean;
}

export type FieldKind =
  | 'text' | 'multiline' | 'password' | 'concealed' | 'url' | 'email'
  | 'phone' | 'date' | 'month_year' | 'totp' | 'reference';

// adjacently-tagged { tag: "kind", content: "value" }
export type FieldValue =
  | { kind: 'text';       value: string }
  | { kind: 'multiline';  value: string }
  | { kind: 'password';   value: string }
  | { kind: 'concealed';  value: string }
  | { kind: 'url';        value: string }
  | { kind: 'email';      value: string }
  | { kind: 'phone';      value: string }
  | { kind: 'date';       value: string }
  | { kind: 'month_year'; value: { month: number; year: number } }
  | { kind: 'totp';       value: TotpConfig }
  | { kind: 'reference';  value: AttachmentId };

// --- Attachments + history ---

export interface AttachmentRef {
  id: AttachmentId;
  filename: string;
  mime_type: string;
  size: number;
  created: number;
}

export interface FieldHistoryEntry {
  value: string;
  replaced_at: number;
}

export interface AttachmentSummary {
  id: AttachmentId;
  filename: string;
  mime_type: string;
  size: number;
}

// --- Devices ---

export interface Device {
  name: string;
  public_key: string;  // hex-encoded ed25519 pubkey
  added_at: number;    // unix timestamp
  added_by?: string;   // device name that registered this device (optional)
}

// --- Field history view ---

export interface FieldHistoryViewEntry {
  value: string;
  changed_at: number;
}

export interface FieldHistoryView {
  field_id: string;
  field_name: string;
  current_value: string;
  entries: FieldHistoryViewEntry[];
}

// --- Item envelope ---

export interface Item {
  id: ItemId;
  title: string;
  type: ItemType;                   // Rust r#type → JSON key "type"
  tags: string[];
  favorite: boolean;
  group?: string;
  notes?: string;
  created: number;
  modified: number;
  trashed_at?: number;
  core: ItemCore;
  sections: Section[];
  attachments: AttachmentRef[];
  field_history: Record<FieldId, FieldHistoryEntry[]>;
}

// --- Manifest (schema_version 2) ---

export interface Manifest {
  schema_version: number;           // 2
  items: Record<ItemId, ManifestEntry>;
}

export interface ManifestEntry {
  id: ItemId;
  type: ItemType;
  title: string;
  tags: string[];
  favorite: boolean;
  group?: string;
  icon_hint?: string;
  modified: number;
  trashed_at?: number;
  attachment_summaries: AttachmentSummary[];
}

// --- Vault settings ---
// Full shape lives on the Rust side and in docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md
// β₂ tightens retention + generator_defaults; γ owns attachment_caps.

export type TrashRetention =
  | { kind: 'forever' }
  | { kind: 'days'; value: number };

export type HistoryRetention =
  | { kind: 'forever' }
  | { kind: 'last_n'; value: number }
  | { kind: 'days'; value: number };

/// Optional per-level caps on attachment plaintext sizes.
/// All fields optional; if undefined that level is uncapped.
/// Field names mirror the Rust core's `AttachmentCaps` struct.
/// γ₁ enforces; γ₂ ships the configuration UI.
export interface AttachmentCaps {
  per_attachment_max_bytes?: number;
  per_item_max_count?: number;           // count of attachments per item, NOT bytes
  per_vault_soft_cap_bytes?: number;     // soft cap — warn user but allow
  per_vault_hard_cap_bytes?: number;     // hard cap — reject
}

export interface VaultSettings {
  trash_retention: TrashRetention;
  field_history_retention: HistoryRetention;
  generator_defaults: GeneratorRequest;
  attachment_caps: AttachmentCaps;
  autofill_origin_acks: Record<string, number>;
}

// --- Vault config (device-local) ---

export interface VaultConfig {
  hostType: 'gitea' | 'github';
  hostUrl: string;
  repoPath: string;
  apiToken: string;
}

export interface SetupState {
  config: VaultConfig | null;
  imageBase64: string | null;
  isConfigured: boolean;
}

// --- Device-local UX settings (chrome.storage.local — renamed from RelicarioSettings) ---

export interface DeviceSettings {
  captureEnabled: boolean;
  captureStyle: 'bar' | 'toast';
}

export const DEFAULT_DEVICE_SETTINGS: DeviceSettings = {
  captureEnabled: false,
  captureStyle: 'bar',
};

// --- Generator request (matches Rust GeneratorRequest — tag="kind") ---

export type GeneratorRequest =
  | { kind: 'bip39';  word_count: number; separator: string; capitalization: Capitalization }
  | { kind: 'random'; length: number; classes: CharClasses; symbol_charset: SymbolCharset };

export type Capitalization = 'lower' | 'upper' | 'first_of_each' | 'title' | 'mixed';
export interface CharClasses { lower: boolean; upper: boolean; digits: boolean; symbols: boolean; }
export type SymbolCharset =
  | { kind: 'safe_only' }
  | { kind: 'extended' }
  | { kind: 'custom'; value: string };

// Default used by the α popup "gen" button:
export const DEFAULT_PASSWORD_REQUEST: GeneratorRequest = {
  kind: 'random',
  length: 20,
  classes: { lower: true, upper: true, digits: true, symbols: true },
  symbol_charset: { kind: 'safe_only' },
};
