-- =========================================
-- Extensions (optional but useful)
-- =========================================
CREATE EXTENSION IF NOT EXISTS pgcrypto;   -- for gen_random_uuid() if you want it later

-- =========================================
-- 1) Identity & Sessions
-- =========================================
CREATE TABLE IF NOT EXISTS app_user (
  id            TEXT PRIMARY KEY,
  username      TEXT NOT NULL UNIQUE,
  password_hash TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS app_session (
  id            TEXT PRIMARY KEY,
  user_id       TEXT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  created_at    TIMESTAMPTZ NOT NULL,
  last_seen_at  TIMESTAMPTZ,
  expires_at    TIMESTAMPTZ NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_app_session_user_id ON app_session(user_id);
CREATE INDEX IF NOT EXISTS idx_app_session_expires_at ON app_session(expires_at);

-- =========================================
-- 2) Broker links + Zerodha auth artifacts
-- Mirrors: user_brokers.json, zerodha_sessions.json, zerodha_request_tokens.json
-- =========================================

-- Current connected broker record per user (plus "pending" fields)
CREATE TABLE IF NOT EXISTS user_broker (
  user_id          TEXT PRIMARY KEY REFERENCES app_user(id) ON DELETE CASCADE,
  broker           TEXT,
  connected        BOOLEAN NOT NULL DEFAULT FALSE,

  access_token     TEXT,
  connected_at     TIMESTAMPTZ,

  api_key          TEXT,
  user_name        TEXT,
  broker_user_id   TEXT,

  -- pending fields (as you described)
  pending_broker     TEXT,
  pending_api_key    TEXT,
  pending_api_secret TEXT,
  pending_started_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_user_broker_broker ON user_broker(broker);
CREATE INDEX IF NOT EXISTS idx_user_broker_connected ON user_broker(connected);

-- Zerodha session history (can be multiple per user)
CREATE TABLE IF NOT EXISTS zerodha_session (
  id             BIGSERIAL PRIMARY KEY,
  user_id        TEXT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  linked_at      TIMESTAMPTZ NOT NULL,

  api_key        TEXT,
  access_token   TEXT,
  request_token  TEXT,

  user_name      TEXT,
  broker_user_id TEXT
);

CREATE INDEX IF NOT EXISTS idx_zerodha_session_user_id ON zerodha_session(user_id);
CREATE INDEX IF NOT EXISTS idx_zerodha_session_linked_at ON zerodha_session(linked_at);

-- Latest/active request token per user (mirrors zerodha_request_tokens.json)
CREATE TABLE IF NOT EXISTS zerodha_request_token (
  user_id        TEXT PRIMARY KEY REFERENCES app_user(id) ON DELETE CASCADE,
  request_token  TEXT NOT NULL
);

-- =========================================
-- 3) Strategy config + engine status
-- Mirrors: strategy_config.json, engine_status.json
-- =========================================

-- Keep it simple: single-row table (config "current")
CREATE TABLE IF NOT EXISTS strategy_config (
  id                SMALLINT PRIMARY KEY DEFAULT 1,
  strategy          TEXT,
  sip_amount        NUMERIC,

  sip_frequency_value INTEGER,
  sip_frequency_unit  TEXT,

  mode              TEXT,     -- paper/live
  broker            TEXT,

  -- legacy/optional fields
  active            BOOLEAN,
  frequency         TEXT,
  frequency_days    INTEGER,
  unit              TEXT,
  next_run          TIMESTAMPTZ
);

-- single-row engine status
CREATE TABLE IF NOT EXISTS engine_status (
  id            SMALLINT PRIMARY KEY DEFAULT 1,
  status        TEXT NOT NULL,
  last_updated  TIMESTAMPTZ NOT NULL
);

-- =========================================
-- 4) Logs / event streams
-- Mirrors: strategy_logs.json, engine.log (JSONL)
-- =========================================

-- strategy_logs.json
CREATE TABLE IF NOT EXISTS strategy_log (
  seq        BIGINT PRIMARY KEY,
  ts         TIMESTAMPTZ NOT NULL,
  level      TEXT,
  category   TEXT,
  event      TEXT,
  message    TEXT,
  run_id     TEXT,
  meta       JSONB
);

CREATE INDEX IF NOT EXISTS idx_strategy_log_ts ON strategy_log(ts);
CREATE INDEX IF NOT EXISTS idx_strategy_log_run_id ON strategy_log(run_id);
CREATE INDEX IF NOT EXISTS idx_strategy_log_event ON strategy_log(event);

-- engine.log JSONL
CREATE TABLE IF NOT EXISTS engine_event (
  id        BIGSERIAL PRIMARY KEY,
  ts        TIMESTAMPTZ NOT NULL,
  event     TEXT,
  data      JSONB,
  message   TEXT,
  meta      JSONB
);

CREATE INDEX IF NOT EXISTS idx_engine_event_ts ON engine_event(ts);
CREATE INDEX IF NOT EXISTS idx_engine_event_event ON engine_event(event);

-- =========================================
-- 5) Engine state (paper + derived)
-- Mirrors: state_paper.json, state.json
-- =========================================

-- state_paper.json
CREATE TABLE IF NOT EXISTS engine_state_paper (
  id              SMALLINT PRIMARY KEY DEFAULT 1,

  initial_cash    NUMERIC,
  cash            NUMERIC,
  total_invested  NUMERIC,

  nifty_units     NUMERIC,
  gold_units      NUMERIC,

  last_sip_ts     TIMESTAMPTZ,
  last_run        TIMESTAMPTZ,

  sip_frequency_value INTEGER,
  sip_frequency_unit  TEXT
);

-- state.json (lighter)
CREATE TABLE IF NOT EXISTS engine_state (
  id              SMALLINT PRIMARY KEY DEFAULT 1,

  total_invested  NUMERIC,
  nifty_units     NUMERIC,
  gold_units      NUMERIC,

  last_sip_ts     TIMESTAMPTZ,
  last_run        TIMESTAMPTZ
);

-- =========================================
-- 6) Paper broker (positions, orders, trades, equity curve)
-- Mirrors: paper_broker.json
-- =========================================

-- overall cash snapshot (paper_broker.json top-level cash)
CREATE TABLE IF NOT EXISTS paper_broker_account (
  id    SMALLINT PRIMARY KEY DEFAULT 1,
  cash  NUMERIC NOT NULL
);

-- positions map: symbol -> qty, avg_price, last_price
CREATE TABLE IF NOT EXISTS paper_position (
  symbol      TEXT PRIMARY KEY,
  qty         NUMERIC NOT NULL,
  avg_price   NUMERIC,
  last_price  NUMERIC,
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- orders list
CREATE TABLE IF NOT EXISTS paper_order (
  id         TEXT PRIMARY KEY,
  symbol     TEXT NOT NULL,
  side       TEXT NOT NULL,     -- buy/sell
  qty        NUMERIC NOT NULL,
  price      NUMERIC,
  status     TEXT NOT NULL,     -- new/filled/cancelled/rejected etc
  timestamp  TIMESTAMPTZ NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_paper_order_ts ON paper_order(timestamp);
CREATE INDEX IF NOT EXISTS idx_paper_order_symbol ON paper_order(symbol);
CREATE INDEX IF NOT EXISTS idx_paper_order_status ON paper_order(status);

-- trades list
CREATE TABLE IF NOT EXISTS paper_trade (
  id         TEXT PRIMARY KEY,
  order_id   TEXT REFERENCES paper_order(id) ON DELETE SET NULL,
  symbol     TEXT NOT NULL,
  side       TEXT NOT NULL,
  qty        NUMERIC NOT NULL,
  price      NUMERIC NOT NULL,
  timestamp  TIMESTAMPTZ NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_paper_trade_ts ON paper_trade(timestamp);
CREATE INDEX IF NOT EXISTS idx_paper_trade_symbol ON paper_trade(symbol);

-- equity_curve list
CREATE TABLE IF NOT EXISTS paper_equity_curve (
  timestamp  TIMESTAMPTZ PRIMARY KEY,
  equity     NUMERIC NOT NULL,
  pnl        NUMERIC
);

CREATE INDEX IF NOT EXISTS idx_paper_equity_curve_ts ON paper_equity_curve(timestamp);

-- =========================================
-- 7) MTM ledger + event ledger
-- Mirrors: mtm_ledger.csv, ledger.csv
-- =========================================

CREATE TABLE IF NOT EXISTS mtm_ledger (
  timestamp        TIMESTAMPTZ PRIMARY KEY,

  nifty_units      NUMERIC,
  gold_units       NUMERIC,

  nifty_price      NUMERIC,
  gold_price       NUMERIC,

  nifty_value      NUMERIC,
  gold_value       NUMERIC,

  portfolio_value  NUMERIC,
  total_invested   NUMERIC,
  pnl              NUMERIC
);

CREATE INDEX IF NOT EXISTS idx_mtm_ledger_ts ON mtm_ledger(timestamp);

CREATE TABLE IF NOT EXISTS event_ledger (
  id          BIGSERIAL PRIMARY KEY,
  timestamp   TIMESTAMPTZ NOT NULL,
  event       TEXT NOT NULL,

  nifty_units NUMERIC,
  gold_units  NUMERIC,

  nifty_price NUMERIC,
  gold_price  NUMERIC,

  amount      NUMERIC
);

CREATE INDEX IF NOT EXISTS idx_event_ledger_ts ON event_ledger(timestamp);
CREATE INDEX IF NOT EXISTS idx_event_ledger_event ON event_ledger(event);

-- =========================================
-- 8) Market data cache (History Cache CSVs)
-- Mirrors: SYMBOL.csv {Date, Close}
-- =========================================

CREATE TABLE IF NOT EXISTS market_close (
  symbol   TEXT NOT NULL,
  date     DATE NOT NULL,
  close    NUMERIC NOT NULL,
  PRIMARY KEY (symbol, date)
);

CREATE INDEX IF NOT EXISTS idx_market_close_symbol ON market_close(symbol);
CREATE INDEX IF NOT EXISTS idx_market_close_date ON market_close(date);
