-- M0: Local household ledger skeleton.
-- SQLite-compatible baseline schema. The SQLAlchemy models are the runtime source for dev
-- create_all(); this file documents the first relational shape for migration tooling.

CREATE TABLE IF NOT EXISTS households (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  default_currency TEXT NOT NULL DEFAULT 'EUR',
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  display_name TEXT NOT NULL,
  email TEXT,
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS login_identities (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id),
  provider TEXT NOT NULL,
  provider_subject TEXT NOT NULL,
  email TEXT,
  display_name TEXT,
  created_at TEXT NOT NULL,
  UNIQUE(provider, provider_subject)
);

CREATE TABLE IF NOT EXISTS local_sessions (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id),
  household_id TEXT NOT NULL REFERENCES households(id),
  token_hash TEXT NOT NULL UNIQUE,
  created_at TEXT NOT NULL,
  last_seen_at TEXT NOT NULL,
  expires_at TEXT NOT NULL,
  revoked_at TEXT
);

CREATE INDEX IF NOT EXISTS ix_local_session_token
  ON local_sessions(token_hash);
CREATE INDEX IF NOT EXISTS ix_local_session_user
  ON local_sessions(user_id, expires_at);

CREATE TABLE IF NOT EXISTS accounts (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  owner_user_id TEXT REFERENCES users(id),
  name TEXT NOT NULL,
  account_type TEXT NOT NULL,
  institution_name TEXT,
  currency TEXT NOT NULL DEFAULT 'EUR',
  visibility_mode TEXT NOT NULL,
  is_active INTEGER NOT NULL DEFAULT 1,
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS raw_observations (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  source_type TEXT NOT NULL,
  source_account_id TEXT REFERENCES accounts(id),
  owner_user_id TEXT REFERENCES users(id),
  observed_at TEXT,
  received_at TEXT NOT NULL,
  raw_hash TEXT NOT NULL,
  source_reference TEXT,
  provider_transaction_id TEXT,
  message_id TEXT,
  raw_text TEXT,
  raw_file_path TEXT,
  raw_payload_json TEXT,
  parsed_json TEXT,
  parser_name TEXT,
  parser_version TEXT,
  confidence NUMERIC(14, 2) NOT NULL DEFAULT 1.00,
  status TEXT NOT NULL,
  created_at TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS ix_observation_dedupe
  ON raw_observations(household_id, source_type, raw_hash);
CREATE INDEX IF NOT EXISTS ix_observation_external_refs
  ON raw_observations(provider_transaction_id, message_id);

CREATE TABLE IF NOT EXISTS categories (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  parent_id TEXT REFERENCES categories(id),
  name TEXT NOT NULL,
  path TEXT NOT NULL,
  is_active INTEGER NOT NULL DEFAULT 1
);

CREATE TABLE IF NOT EXISTS projects (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  name TEXT NOT NULL,
  description TEXT,
  start_date TEXT,
  end_date TEXT,
  default_split_rule_id TEXT,
  status TEXT NOT NULL,
  currency TEXT NOT NULL DEFAULT 'EUR',
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS financial_events (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  source_account_id TEXT REFERENCES accounts(id),
  payment_account_id TEXT REFERENCES accounts(id),
  payer_user_id TEXT REFERENCES users(id),
  event_type TEXT NOT NULL,
  status TEXT NOT NULL,
  event_date TEXT NOT NULL,
  booking_date TEXT,
  due_date TEXT,
  amount NUMERIC(14, 2) NOT NULL,
  currency TEXT NOT NULL DEFAULT 'EUR',
  merchant TEXT,
  counterparty TEXT,
  description TEXT,
  category_id TEXT REFERENCES categories(id),
  project_id TEXT REFERENCES projects(id),
  created_by_user_id TEXT REFERENCES users(id),
  fingerprint TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS ix_events_household_status_date
  ON financial_events(household_id, status, event_date);

CREATE TABLE IF NOT EXISTS event_observation_links (
  id TEXT PRIMARY KEY,
  event_id TEXT NOT NULL REFERENCES financial_events(id),
  observation_id TEXT NOT NULL REFERENCES raw_observations(id),
  relation TEXT NOT NULL,
  confidence NUMERIC(14, 2) NOT NULL DEFAULT 1.00,
  created_at TEXT NOT NULL,
  UNIQUE(event_id, observation_id, relation)
);

CREATE TABLE IF NOT EXISTS event_relations (
  id TEXT PRIMARY KEY,
  from_event_id TEXT NOT NULL REFERENCES financial_events(id),
  to_event_id TEXT NOT NULL REFERENCES financial_events(id),
  relation_type TEXT NOT NULL,
  confidence NUMERIC(14, 2) NOT NULL DEFAULT 1.00,
  created_by TEXT NOT NULL DEFAULT 'system',
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS split_lines (
  id TEXT PRIMARY KEY,
  event_id TEXT NOT NULL REFERENCES financial_events(id),
  user_id TEXT NOT NULL REFERENCES users(id),
  share_amount NUMERIC(14, 2) NOT NULL,
  share_percent NUMERIC(14, 2),
  reason TEXT NOT NULL,
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS tags (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  name TEXT NOT NULL,
  UNIQUE(household_id, name)
);

CREATE TABLE IF NOT EXISTS event_tags (
  event_id TEXT NOT NULL REFERENCES financial_events(id),
  tag_id TEXT NOT NULL REFERENCES tags(id),
  PRIMARY KEY(event_id, tag_id)
);

CREATE TABLE IF NOT EXISTS project_participants (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL REFERENCES projects(id),
  user_id TEXT NOT NULL REFERENCES users(id),
  role TEXT NOT NULL,
  default_share_percent NUMERIC(14, 2),
  UNIQUE(project_id, user_id)
);

CREATE TABLE IF NOT EXISTS project_budget_lines (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL REFERENCES projects(id),
  category_id TEXT REFERENCES categories(id),
  name TEXT NOT NULL,
  budgeted_amount NUMERIC(14, 2) NOT NULL DEFAULT 0.00,
  committed_amount_cached NUMERIC(14, 2),
  paid_amount_cached NUMERIC(14, 2),
  sort_order INTEGER NOT NULL DEFAULT 0,
  notes TEXT
);

CREATE TABLE IF NOT EXISTS project_planned_items (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL REFERENCES projects(id),
  budget_line_id TEXT REFERENCES project_budget_lines(id),
  description TEXT NOT NULL,
  estimated_amount NUMERIC(14, 2) NOT NULL DEFAULT 0.00,
  committed_amount NUMERIC(14, 2),
  expected_date TEXT,
  due_date TEXT,
  expected_payer_account_id TEXT REFERENCES accounts(id),
  split_rule_id TEXT,
  planning_status TEXT NOT NULL,
  payment_status TEXT NOT NULL,
  reconciliation_status TEXT NOT NULL,
  settlement_status TEXT NOT NULL,
  notes TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS payment_lines (
  id TEXT PRIMARY KEY,
  planned_item_id TEXT REFERENCES project_planned_items(id),
  event_id TEXT REFERENCES financial_events(id),
  amount NUMERIC(14, 2) NOT NULL,
  currency TEXT NOT NULL DEFAULT 'EUR',
  date TEXT NOT NULL,
  paid_by_user_id TEXT REFERENCES users(id),
  payment_account_id TEXT REFERENCES accounts(id),
  source_observation_id TEXT REFERENCES raw_observations(id),
  status TEXT NOT NULL,
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS recurring_commitments (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  provider TEXT NOT NULL,
  description TEXT,
  amount_expected NUMERIC(14, 2) NOT NULL,
  amount_min NUMERIC(14, 2),
  amount_max NUMERIC(14, 2),
  currency TEXT NOT NULL DEFAULT 'EUR',
  interval TEXT NOT NULL,
  next_due_date TEXT NOT NULL,
  payer_account_id TEXT REFERENCES accounts(id),
  split_rule_id TEXT,
  category_id TEXT REFERENCES categories(id),
  project_id TEXT REFERENCES projects(id),
  notice_period TEXT,
  renewal_date TEXT,
  status TEXT NOT NULL,
  matching_rule_json TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS promised_payments (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  related_event_id TEXT REFERENCES financial_events(id),
  provider TEXT NOT NULL,
  amount NUMERIC(14, 2) NOT NULL,
  currency TEXT NOT NULL DEFAULT 'EUR',
  created_date TEXT NOT NULL,
  due_date TEXT NOT NULL,
  expected_funding_account_id TEXT REFERENCES accounts(id),
  responsible_user_id TEXT REFERENCES users(id),
  status TEXT NOT NULL,
  source_observation_id TEXT REFERENCES raw_observations(id),
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS import_connections (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  owner_user_id TEXT NOT NULL REFERENCES users(id),
  connection_type TEXT NOT NULL,
  display_name TEXT NOT NULL,
  status TEXT NOT NULL,
  last_sync_at TEXT,
  last_error TEXT,
  secret_storage_ref TEXT,
  runs_locally INTEGER NOT NULL DEFAULT 1,
  connector_config_json TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS import_runs (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  connection_id TEXT REFERENCES import_connections(id),
  actor_user_id TEXT REFERENCES users(id),
  source_type TEXT,
  status TEXT NOT NULL DEFAULT 'running',
  imported_count INTEGER NOT NULL DEFAULT 0,
  duplicate_count INTEGER NOT NULL DEFAULT 0,
  created_event_count INTEGER NOT NULL DEFAULT 0,
  skipped_count INTEGER NOT NULL DEFAULT 0,
  error TEXT,
  summary_json TEXT,
  started_at TEXT NOT NULL,
  finished_at TEXT
);

CREATE INDEX IF NOT EXISTS ix_import_runs_household_started
  ON import_runs(household_id, started_at);
CREATE INDEX IF NOT EXISTS ix_import_runs_connection_started
  ON import_runs(connection_id, started_at);

CREATE TABLE IF NOT EXISTS audit_log (
  id TEXT PRIMARY KEY,
  household_id TEXT NOT NULL REFERENCES households(id),
  actor_user_id TEXT REFERENCES users(id),
  action TEXT NOT NULL,
  entity_type TEXT NOT NULL,
  entity_id TEXT,
  details_json TEXT,
  created_at TEXT NOT NULL
);
