-- Communication & Lead Layer - Core Tables
-- Migration: 2025081201

-- Contact Identity - central contact model
CREATE TABLE IF NOT EXISTS contacts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    email VARCHAR(255),
    phone VARCHAR(50),
    whatsapp_id VARCHAR(100),
    instagram_id VARCHAR(100),
    facebook_id VARCHAR(100),
    external_id VARCHAR(100),
    company VARCHAR(255),
    org_number VARCHAR(50),
    tags TEXT[],
    status VARCHAR(50) DEFAULT 'active',
    lead_score INTEGER DEFAULT 0,
    source VARCHAR(100),
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    merged_into UUID REFERENCES contacts(id),
    UNIQUE(tenant_id, email),
    UNIQUE(tenant_id, phone)
);

-- Contact Identity Links - for deduplication
CREATE TABLE IF NOT EXISTS contact_identity_links (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
    channel VARCHAR(50) NOT NULL, -- 'whatsapp', 'email', 'phone', 'instagram', etc.
    channel_id VARCHAR(255) NOT NULL,
    confidence FLOAT DEFAULT 1.0,
    verified BOOLEAN DEFAULT false,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(contact_id, channel, channel_id)
);

-- Conversations
CREATE TABLE IF NOT EXISTS conversations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    contact_id UUID NOT NULL REFERENCES contacts(id),
    channel VARCHAR(50) NOT NULL,
    channel_conversation_id VARCHAR(255),
    status VARCHAR(50) DEFAULT 'new', -- 'new', 'active', 'waiting', 'resolved', 'escalated'
    assigned_to UUID,
    assigned_team VARCHAR(100),
    lead_id UUID,
    tags TEXT[],
    priority VARCHAR(20) DEFAULT 'normal', -- 'low', 'normal', 'high', 'urgent'
    last_activity_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    next_action_at TIMESTAMP WITH TIME ZONE,
    next_action_type VARCHAR(100),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    metadata JSONB DEFAULT '{}'
);

-- Messages
CREATE TABLE IF NOT EXISTS messages (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
    contact_id UUID NOT NULL REFERENCES contacts(id),
    direction VARCHAR(20) NOT NULL, -- 'inbound', 'outbound'
    content TEXT NOT NULL,
    content_type VARCHAR(50) DEFAULT 'text', -- 'text', 'image', 'file', 'template'
    channel_message_id VARCHAR(255),
    sender_type VARCHAR(50) DEFAULT 'contact', -- 'contact', 'agent', 'system', 'user'
    sender_id UUID,
    read_at TIMESTAMP WITH TIME ZONE,
    delivered_at TIMESTAMP WITH TIME ZONE,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Leads
CREATE TABLE IF NOT EXISTS leads (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    contact_id UUID NOT NULL REFERENCES contacts(id),
    conversation_id UUID REFERENCES conversations(id),
    source VARCHAR(100) NOT NULL,
    source_metadata JSONB DEFAULT '{}',
    status VARCHAR(50) DEFAULT 'new', -- 'new', 'contacted', 'qualifying', 'qualified', 'sales', 'won', 'lost'
    interest VARCHAR(255),
    product VARCHAR(255),
    urgency VARCHAR(20) DEFAULT 'normal', -- 'low', 'normal', 'high', 'urgent'
    customer_type VARCHAR(50), -- 'new', 'existing'
    owner UUID,
    team VARCHAR(100),
    lead_score INTEGER DEFAULT 0,
    qualification_state JSONB DEFAULT '{}',
    qualification_complete BOOLEAN DEFAULT false,
    last_interaction_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    next_action_at TIMESTAMP WITH TIME ZONE,
    next_action_type VARCHAR(100),
    won_at TIMESTAMP WITH TIME ZONE,
    lost_at TIMESTAMP WITH TIME ZONE,
    lost_reason VARCHAR(255),
    tags TEXT[],
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Lead Score History
CREATE TABLE IF NOT EXISTS lead_score_history (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    lead_id UUID NOT NULL REFERENCES leads(id) ON DELETE CASCADE,
    score INTEGER NOT NULL,
    previous_score INTEGER,
    reason TEXT NOT NULL,
    factors JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Tags
CREATE TABLE IF NOT EXISTS tags (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    name VARCHAR(100) NOT NULL,
    color VARCHAR(20) DEFAULT '#2563EB',
    category VARCHAR(100),
    description TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(tenant_id, name)
);

-- Workflows
CREATE TABLE IF NOT EXISTS workflows (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    trigger VARCHAR(100) NOT NULL, -- 'new_contact', 'new_lead', 'tag_added', 'status_changed', etc.
    trigger_config JSONB DEFAULT '{}',
    conditions JSONB DEFAULT '[]',
    actions JSONB DEFAULT '[]',
    status VARCHAR(50) DEFAULT 'active', -- 'active', 'paused', 'draft'
    execution_count INTEGER DEFAULT 0,
    last_executed_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Workflow Executions
CREATE TABLE IF NOT EXISTS workflow_executions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workflow_id UUID NOT NULL REFERENCES workflows(id),
    trigger_event VARCHAR(100) NOT NULL,
    trigger_data JSONB DEFAULT '{}',
    status VARCHAR(50) DEFAULT 'running', -- 'running', 'completed', 'failed', 'waiting'
    current_step INTEGER DEFAULT 0,
    steps JSONB DEFAULT '[]',
    result JSONB DEFAULT '{}',
    error TEXT,
    started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    completed_at TIMESTAMP WITH TIME ZONE
);

-- Follow-ups
CREATE TABLE IF NOT EXISTS follow_ups (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    lead_id UUID REFERENCES leads(id),
    conversation_id UUID REFERENCES conversations(id),
    type VARCHAR(100) NOT NULL,
    description TEXT,
    assigned_to UUID,
    due_at TIMESTAMP WITH TIME ZONE NOT NULL,
    completed_at TIMESTAMP WITH TIME ZONE,
    status VARCHAR(50) DEFAULT 'pending', -- 'pending', 'completed', 'overdue', 'cancelled'
    reminder_sent BOOLEAN DEFAULT false,
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Audit Log
CREATE TABLE IF NOT EXISTS communication_audit_log (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    actor_type VARCHAR(50) NOT NULL, -- 'user', 'system', 'agent', 'workflow'
    actor_id UUID,
    action VARCHAR(100) NOT NULL,
    object_type VARCHAR(100) NOT NULL, -- 'contact', 'lead', 'conversation', 'message', 'workflow'
    object_id UUID NOT NULL,
    previous_state JSONB,
    new_state JSONB,
    source VARCHAR(100),
    correlation_id UUID,
    ip_address INET,
    user_agent TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Indexes
CREATE INDEX IF NOT EXISTS idx_contacts_tenant ON contacts(tenant_id);
CREATE INDEX IF NOT EXISTS idx_contacts_email ON contacts(email);
CREATE INDEX IF NOT EXISTS idx_contacts_phone ON contacts(phone);
CREATE INDEX IF NOT EXISTS idx_contacts_merged ON contacts(merged_into);

CREATE INDEX IF NOT EXISTS idx_contact_links_contact ON contact_identity_links(contact_id);
CREATE INDEX IF NOT EXISTS idx_contact_links_channel ON contact_identity_links(channel, channel_id);

CREATE INDEX IF NOT EXISTS idx_conversations_tenant ON conversations(tenant_id);
CREATE INDEX IF NOT EXISTS idx_conversations_contact ON conversations(contact_id);
CREATE INDEX IF NOT EXISTS idx_conversations_status ON conversations(status);
CREATE INDEX IF NOT EXISTS idx_conversations_assigned ON conversations(assigned_to);
CREATE INDEX IF NOT EXISTS idx_conversations_lead ON conversations(lead_id);

CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id);
CREATE INDEX IF NOT EXISTS idx_messages_created ON messages(created_at);

CREATE INDEX IF NOT EXISTS idx_leads_tenant ON leads(tenant_id);
CREATE INDEX IF NOT EXISTS idx_leads_contact ON leads(contact_id);
CREATE INDEX IF NOT EXISTS idx_leads_status ON leads(status);
CREATE INDEX IF NOT EXISTS idx_leads_owner ON leads(owner);
CREATE INDEX IF NOT EXISTS idx_leads_score ON leads(lead_score DESC);

CREATE INDEX IF NOT EXISTS idx_workflows_tenant ON workflows(tenant_id);
CREATE INDEX IF NOT EXISTS idx_workflows_trigger ON workflows(trigger);

CREATE INDEX IF NOT EXISTS idx_followups_lead ON follow_ups(lead_id);
CREATE INDEX IF NOT EXISTS idx_followups_due ON follow_ups(due_at);
CREATE INDEX IF NOT EXISTS idx_followups_status ON follow_ups(status);

CREATE INDEX IF NOT EXISTS idx_audit_tenant ON communication_audit_log(tenant_id);
CREATE INDEX IF NOT EXISTS idx_audit_object ON communication_audit_log(object_type, object_id);
CREATE INDEX IF NOT EXISTS idx_audit_correlation ON communication_audit_log(correlation_id);
CREATE INDEX IF NOT EXISTS idx_audit_created ON communication_audit_log(created_at);
