-- Poimen Workflows schema
-- Tables: workflows, workflow_executions, execution_logs, activity_traces, workflow_stats, workflow_memory_links
-- Integrates with temporal workflow orchestrator and memory service

-- Workflows (canvas definitions with JSONB nodes/edges)
CREATE TABLE IF NOT EXISTS workflows (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  customer_id TEXT NOT NULL,
  name TEXT NOT NULL,
  description TEXT,
  status TEXT NOT NULL CHECK (status IN ('draft', 'active', 'archived')) DEFAULT 'draft',
  version INT NOT NULL DEFAULT 1,
  
  -- Canvas data (React Flow format)
  nodes JSONB NOT NULL DEFAULT '[]'::jsonb,  -- WorkflowNode[]
  edges JSONB NOT NULL DEFAULT '[]'::jsonb,  -- WorkflowEdge[]
  
  -- Metadata
  created_by TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  last_executed_at TIMESTAMPTZ,
  
  CONSTRAINT workflow_name_per_customer UNIQUE (customer_id, name)
);

CREATE INDEX idx_workflows_customer ON workflows(customer_id);
CREATE INDEX idx_workflows_status ON workflows(status);
CREATE INDEX idx_workflows_created_at ON workflows(created_at DESC);

-- Workflow executions (runs triggered by user)
CREATE TABLE IF NOT EXISTS workflow_executions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  workflow_id UUID NOT NULL REFERENCES workflows(id) ON DELETE CASCADE,
  customer_id TEXT NOT NULL,
  
  -- Temporal details
  temporal_id TEXT NOT NULL UNIQUE,  -- Temporal workflow execution ID
  status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'success', 'failed', 'cancelled')) DEFAULT 'pending',
  
  -- Input/Output
  inputs JSONB NOT NULL,
  outputs JSONB,
  
  -- Timing
  started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  completed_at TIMESTAMPTZ,
  duration_ms INT,
  
  -- Error tracking
  error_message TEXT,
  error_count INT DEFAULT 0,
  
  CONSTRAINT duration_when_completed CHECK (
    (status IN ('success', 'failed') AND completed_at IS NOT NULL) OR
    (status IN ('pending', 'running', 'cancelled'))
  )
);

CREATE INDEX idx_executions_workflow ON workflow_executions(workflow_id);
CREATE INDEX idx_executions_customer ON workflow_executions(customer_id);
CREATE INDEX idx_executions_status ON workflow_executions(status);
CREATE INDEX idx_executions_temporal_id ON workflow_executions(temporal_id);
CREATE INDEX idx_executions_started_at ON workflow_executions(started_at DESC);

-- Execution logs (detailed activity logs)
CREATE TABLE IF NOT EXISTS execution_logs (
  id BIGSERIAL PRIMARY KEY,
  execution_id UUID NOT NULL REFERENCES workflow_executions(id) ON DELETE CASCADE,
  
  -- Node/Activity info
  node_id TEXT NOT NULL,  -- "activity-123" from canvas
  activity_name TEXT NOT NULL,  -- "CloneRepo", "AnalyzeCode", etc.
  
  -- Log entry
  level TEXT NOT NULL CHECK (level IN ('info', 'warn', 'error', 'debug')),
  message TEXT NOT NULL,
  metadata JSONB,  -- Arbitrary structured data (duration, result, etc.)
  
  -- Timing
  logged_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  
  CONSTRAINT log_order UNIQUE (execution_id, logged_at, id)
);

CREATE INDEX idx_logs_execution ON execution_logs(execution_id);
CREATE INDEX idx_logs_node ON execution_logs(execution_id, node_id);
CREATE INDEX idx_logs_level ON execution_logs(level);
CREATE INDEX idx_logs_logged_at ON execution_logs(logged_at DESC);

-- Activity execution trace (detailed per-activity metrics)
CREATE TABLE IF NOT EXISTS activity_traces (
  id BIGSERIAL PRIMARY KEY,
  execution_id UUID NOT NULL REFERENCES workflow_executions(id) ON DELETE CASCADE,
  node_id TEXT NOT NULL,
  
  -- Activity details
  activity_name TEXT NOT NULL,
  parameters JSONB NOT NULL,
  result JSONB,
  
  -- Timing
  started_at TIMESTAMPTZ NOT NULL,
  completed_at TIMESTAMPTZ,
  duration_ms INT,
  
  -- Retry info
  attempt INT DEFAULT 1,
  retry_reason TEXT,
  
  -- Status
  status TEXT NOT NULL CHECK (status IN ('running', 'success', 'failed', 'skipped')),
  error_message TEXT
);

CREATE INDEX idx_traces_execution ON activity_traces(execution_id);
CREATE INDEX idx_traces_activity ON activity_traces(activity_name);
CREATE INDEX idx_traces_status ON activity_traces(status);
CREATE INDEX idx_traces_started_at ON activity_traces(started_at DESC);

-- Workflow stats (materialized for fast dashboard queries)
CREATE TABLE IF NOT EXISTS workflow_stats (
  workflow_id UUID PRIMARY KEY REFERENCES workflows(id) ON DELETE CASCADE,
  customer_id TEXT NOT NULL,
  
  total_runs INT DEFAULT 0,
  successful_runs INT DEFAULT 0,
  failed_runs INT DEFAULT 0,
  
  avg_duration_ms NUMERIC,
  min_duration_ms INT,
  max_duration_ms INT,
  
  last_30d_runs INT DEFAULT 0,
  last_30d_success_rate NUMERIC,
  
  updated_at TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX idx_stats_customer ON workflow_stats(customer_id);

-- Memory links (connect executions to memory/lessons learned)
CREATE TABLE IF NOT EXISTS workflow_memory_links (
  execution_id UUID NOT NULL REFERENCES workflow_executions(id) ON DELETE CASCADE,
  memory_node_sha TEXT NOT NULL REFERENCES memory_node(sha256) ON DELETE CASCADE,
  relationship TEXT NOT NULL CHECK (relationship IN ('generated', 'used', 'learned', 'failed_on')),
  
  -- Context
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  notes TEXT,
  
  PRIMARY KEY (execution_id, memory_node_sha, relationship)
);

CREATE INDEX idx_memory_links_memory_node ON workflow_memory_links(memory_node_sha);
CREATE INDEX idx_memory_links_execution ON workflow_memory_links(execution_id);

-- View: Recent executions with workflow context
CREATE OR REPLACE VIEW v_recent_executions AS
SELECT 
  we.id,
  we.workflow_id,
  w.name as workflow_name,
  we.customer_id,
  we.status,
  we.started_at,
  we.completed_at,
  we.duration_ms,
  we.error_message,
  (SELECT COUNT(*) FROM execution_logs WHERE execution_id = we.id) as log_count,
  (SELECT COUNT(*) FROM activity_traces WHERE execution_id = we.id) as activity_count
FROM workflow_executions we
JOIN workflows w ON we.workflow_id = w.id
ORDER BY we.started_at DESC;

-- View: Execution timeline (for state machine visualization)
CREATE OR REPLACE VIEW v_execution_timeline AS
SELECT 
  el.execution_id,
  el.logged_at,
  el.node_id,
  el.activity_name,
  el.level,
  el.message,
  at.duration_ms as activity_duration,
  at.status as activity_status
FROM execution_logs el
LEFT JOIN activity_traces at ON el.execution_id = at.execution_id 
  AND el.node_id = at.node_id
ORDER BY el.execution_id, el.logged_at;
