-- HWLAB L1 Cloud Core schema skeleton.
-- This file is source schema only; applying it to DEV/PROD is a separate
-- operator action and is not performed by source tests or smokes.

CREATE TABLE IF NOT EXISTS projects (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL DEFAULT '',
  status TEXT NOT NULL DEFAULT 'pending',
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY,
  username TEXT NOT NULL UNIQUE,
  display_name TEXT NOT NULL DEFAULT '',
  role TEXT NOT NULL CHECK (role IN ('admin', 'user')),
  status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled')),
  password_hash TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS user_sessions (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL REFERENCES users(id),
  session_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 TABLE IF NOT EXISTS gateway_sessions (
  id TEXT PRIMARY KEY,
  project_id TEXT,
  gateway_service_id TEXT NOT NULL,
  status TEXT NOT NULL DEFAULT 'pending',
  started_at TEXT,
  ended_at TEXT,
  gateway_session_json TEXT NOT NULL DEFAULT '{}'
);

CREATE TABLE IF NOT EXISTS box_resources (
  id TEXT PRIMARY KEY,
  project_id TEXT,
  gateway_session_id TEXT,
  resource_state TEXT NOT NULL DEFAULT 'available',
  labels_json TEXT NOT NULL DEFAULT '{}',
  resource_json TEXT NOT NULL DEFAULT '{}',
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS box_capabilities (
  id TEXT PRIMARY KEY,
  box_resource_id TEXT NOT NULL,
  capability_type TEXT NOT NULL,
  capability_json TEXT NOT NULL DEFAULT '{}',
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS wiring_configs (
  id TEXT PRIMARY KEY,
  project_id TEXT,
  wiring_json TEXT NOT NULL DEFAULT '{}',
  status TEXT NOT NULL DEFAULT 'pending',
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS patch_panel_status (
  id TEXT PRIMARY KEY,
  gateway_session_id TEXT,
  wiring_config_id TEXT,
  status_json TEXT NOT NULL DEFAULT '{}',
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS hardware_operations (
  id TEXT PRIMARY KEY,
  project_id TEXT,
  requested_by TEXT,
  operation_type TEXT NOT NULL,
  operation_json TEXT NOT NULL DEFAULT '{}',
  status TEXT NOT NULL DEFAULT 'requested',
  requested_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS audit_events (
  id TEXT PRIMARY KEY,
  request_id TEXT NOT NULL,
  actor TEXT NOT NULL,
  source TEXT NOT NULL,
  operation TEXT NOT NULL,
  target TEXT NOT NULL,
  result TEXT NOT NULL,
  timestamp TEXT NOT NULL,
  event_json TEXT NOT NULL DEFAULT '{}'
);

CREATE TABLE IF NOT EXISTS agent_sessions (
  id TEXT PRIMARY KEY,
  project_id TEXT,
  agent_id TEXT NOT NULL,
  status TEXT NOT NULL DEFAULT 'pending',
  started_at TEXT,
  ended_at TEXT,
  owner_user_id TEXT REFERENCES users(id),
  conversation_id TEXT,
  thread_id TEXT,
  last_trace_id TEXT,
  session_json TEXT NOT NULL DEFAULT '{}',
  updated_at TEXT
);

ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS owner_user_id TEXT REFERENCES users(id);
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS conversation_id TEXT;
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS thread_id TEXT;
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS last_trace_id TEXT;
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS session_json TEXT NOT NULL DEFAULT '{}';
ALTER TABLE agent_sessions ADD COLUMN IF NOT EXISTS updated_at TEXT;
CREATE INDEX IF NOT EXISTS idx_agent_sessions_owner ON agent_sessions(owner_user_id);
CREATE INDEX IF NOT EXISTS idx_agent_sessions_conversation ON agent_sessions(conversation_id);

CREATE TABLE IF NOT EXISTS account_workspaces (
  id TEXT PRIMARY KEY,
  owner_user_id TEXT NOT NULL REFERENCES users(id),
  project_id TEXT NOT NULL,
  name TEXT NOT NULL DEFAULT 'Default Workbench',
  status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived')),
  is_default BOOLEAN NOT NULL DEFAULT true,
  selected_conversation_id TEXT,
  selected_agent_session_id TEXT,
  active_trace_id TEXT,
  provider_profile TEXT,
  workspace_json TEXT NOT NULL DEFAULT '{}',
  revision INTEGER NOT NULL DEFAULT 1,
  updated_by_session_id TEXT,
  updated_by_client TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_account_workspaces_default ON account_workspaces(owner_user_id, project_id) WHERE is_default = TRUE AND status = 'active';
CREATE INDEX IF NOT EXISTS idx_account_workspaces_owner ON account_workspaces(owner_user_id, project_id, updated_at DESC);

CREATE TABLE IF NOT EXISTS worker_sessions (
  id TEXT PRIMARY KEY,
  agent_session_id TEXT,
  worker_id TEXT NOT NULL,
  status TEXT NOT NULL DEFAULT 'pending',
  started_at TEXT,
  ended_at TEXT
);

CREATE TABLE IF NOT EXISTS agent_trace_events (
  id TEXT PRIMARY KEY,
  trace_id TEXT NOT NULL,
  agent_session_id TEXT,
  worker_session_id TEXT,
  level TEXT NOT NULL DEFAULT 'info',
  message TEXT NOT NULL DEFAULT '',
  event_json TEXT NOT NULL DEFAULT '{}',
  occurred_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS evidence_records (
  id TEXT PRIMARY KEY,
  project_id TEXT,
  operation_id TEXT,
  evidence_type TEXT NOT NULL,
  uri TEXT NOT NULL DEFAULT '',
  metadata_json TEXT NOT NULL DEFAULT '{}',
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS hwlab_schema_migrations (
  id TEXT PRIMARY KEY,
  schema_version TEXT NOT NULL,
  applied_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
  migration_json TEXT NOT NULL DEFAULT '{}'
);

INSERT INTO hwlab_schema_migrations (id, schema_version, applied_at, migration_json)
VALUES (
  '0001_cloud_core_skeleton',
  'runtime-durable-postgres-v2',
  CURRENT_TIMESTAMP,
  '{"path":"internal/db/migrations/0001_cloud_core_skeleton.sql","runtime":"cloud-api"}'
)
ON CONFLICT (id) DO UPDATE SET
  schema_version = EXCLUDED.schema_version,
  migration_json = EXCLUDED.migration_json;
