-- Chat Tables Migration
-- Creates tables for chatbot functionality with visitor sessions and message history
-- Version: 001
-- Date: 2026-01-25

-- ============================================================================
-- Table: chat_sessions
-- Stores chatbot session information for visitors
-- ============================================================================
CREATE TABLE IF NOT EXISTS chat_sessions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
  visitor_id TEXT NOT NULL,
  metadata JSONB DEFAULT '{}'::jsonb,
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);

-- Index for quick lookup by visitor_id (used for session continuity)
CREATE INDEX IF NOT EXISTS idx_chat_sessions_visitor_id ON chat_sessions(visitor_id);

-- Index for ordering sessions by creation time
CREATE INDEX IF NOT EXISTS idx_chat_sessions_created_at ON chat_sessions(created_at DESC);

-- Comment on table
COMMENT ON TABLE chat_sessions IS 'Stores chatbot sessions for website visitors';
COMMENT ON COLUMN chat_sessions.visitor_id IS 'Unique identifier for the visitor (generated client-side or from fingerprint)';
COMMENT ON COLUMN chat_sessions.metadata IS 'Additional session data (locale, user_agent, referrer, etc.)';

-- ============================================================================
-- Table: chat_messages
-- Stores individual chat messages within a session
-- ============================================================================
CREATE TABLE IF NOT EXISTS chat_messages (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  session_id UUID NOT NULL REFERENCES chat_sessions(id) ON DELETE CASCADE,
  role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
  content TEXT NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);

-- Index for fetching messages by session (primary query pattern)
CREATE INDEX IF NOT EXISTS idx_chat_messages_session_id ON chat_messages(session_id);

-- Composite index for fetching messages in order within a session
CREATE INDEX IF NOT EXISTS idx_chat_messages_session_created ON chat_messages(session_id, created_at ASC);

-- Comment on table
COMMENT ON TABLE chat_messages IS 'Stores individual messages in chatbot conversations';
COMMENT ON COLUMN chat_messages.role IS 'Message sender role: user, assistant (AI), or system (instructions)';
COMMENT ON COLUMN chat_messages.content IS 'The message text content';

-- ============================================================================
-- Updated At Trigger for chat_sessions
-- Automatically updates the updated_at column when a session is modified
-- ============================================================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER update_chat_sessions_updated_at
  BEFORE UPDATE ON chat_sessions
  FOR EACH ROW
  EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- Row Level Security (RLS)
-- Enabled for production security - server uses service role key to bypass
-- ============================================================================

-- Enable RLS on chat_sessions
ALTER TABLE chat_sessions ENABLE ROW LEVEL SECURITY;

-- Enable RLS on chat_messages
ALTER TABLE chat_messages ENABLE ROW LEVEL SECURITY;

-- ============================================================================
-- RLS Policies for chat_sessions
-- ============================================================================

-- Policy: Allow service role full access (for server-side API routes)
-- Note: Service role key automatically bypasses RLS, but this is explicit
CREATE POLICY "Service role has full access to chat_sessions"
  ON chat_sessions
  FOR ALL
  TO service_role
  USING (true)
  WITH CHECK (true);

-- Policy: Allow visitors to read their own sessions (for potential future client-side access)
CREATE POLICY "Visitors can read their own sessions"
  ON chat_sessions
  FOR SELECT
  TO anon, authenticated
  USING (visitor_id = current_setting('request.headers')::json->>'x-visitor-id');

-- Policy: Allow visitors to create sessions (for potential future client-side access)
CREATE POLICY "Visitors can create sessions"
  ON chat_sessions
  FOR INSERT
  TO anon, authenticated
  WITH CHECK (visitor_id = current_setting('request.headers')::json->>'x-visitor-id');

-- ============================================================================
-- RLS Policies for chat_messages
-- ============================================================================

-- Policy: Allow service role full access (for server-side API routes)
CREATE POLICY "Service role has full access to chat_messages"
  ON chat_messages
  FOR ALL
  TO service_role
  USING (true)
  WITH CHECK (true);

-- Policy: Allow visitors to read messages from their sessions
CREATE POLICY "Visitors can read messages from their sessions"
  ON chat_messages
  FOR SELECT
  TO anon, authenticated
  USING (
    EXISTS (
      SELECT 1 FROM chat_sessions
      WHERE chat_sessions.id = chat_messages.session_id
      AND chat_sessions.visitor_id = current_setting('request.headers')::json->>'x-visitor-id'
    )
  );

-- Policy: Allow visitors to insert messages into their sessions
CREATE POLICY "Visitors can insert messages into their sessions"
  ON chat_messages
  FOR INSERT
  TO anon, authenticated
  WITH CHECK (
    EXISTS (
      SELECT 1 FROM chat_sessions
      WHERE chat_sessions.id = chat_messages.session_id
      AND chat_sessions.visitor_id = current_setting('request.headers')::json->>'x-visitor-id'
    )
  );

-- ============================================================================
-- Grants
-- ============================================================================

-- Grant usage on tables to authenticated and anon roles
GRANT SELECT, INSERT ON chat_sessions TO anon, authenticated;
GRANT SELECT, INSERT ON chat_messages TO anon, authenticated;

-- Grant all to service role (for server-side operations)
GRANT ALL ON chat_sessions TO service_role;
GRANT ALL ON chat_messages TO service_role;
