-- Migration 013: Email System for Invoice and Time Confirmation Processing
-- Based on OmniSync email architecture adapted for BMC Hub

-- Drop existing tables if any (clean slate)
DROP TABLE IF EXISTS email_analysis CASCADE;
DROP TABLE IF EXISTS email_attachments CASCADE;
DROP TABLE IF EXISTS email_messages CASCADE;
DROP TABLE IF EXISTS email_rules CASCADE;
DROP VIEW IF EXISTS v_unprocessed_emails;
DROP VIEW IF EXISTS v_email_activity;
DROP FUNCTION IF EXISTS update_email_messages_updated_at();
DROP FUNCTION IF EXISTS update_email_rules_updated_at();

-- Email Rules Table (create first - referenced by email_messages)
CREATE TABLE email_rules (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    
    -- Rule Conditions (JSON for flexibility)
    conditions JSONB NOT NULL,
    
    -- Rule Actions
    action_type VARCHAR(50) NOT NULL,
    action_params JSONB,
    
    -- Priority and Status
    priority INTEGER DEFAULT 100,
    enabled BOOLEAN DEFAULT true,
    
    -- Statistics
    match_count INTEGER DEFAULT 0,
    last_matched_at TIMESTAMP,
    
    -- Audit
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by_user_id INTEGER,
    
    FOREIGN KEY (created_by_user_id) REFERENCES users(user_id) ON DELETE SET NULL
);

-- Email Messages Table (main storage)
CREATE TABLE email_messages (
    id SERIAL PRIMARY KEY,
    message_id VARCHAR(500) UNIQUE NOT NULL,
    subject TEXT,
    sender_email VARCHAR(255),
    sender_name VARCHAR(255),
    recipient_email VARCHAR(255),
    cc TEXT,
    body_text TEXT,
    body_html TEXT,
    received_date TIMESTAMP,
    folder VARCHAR(100) DEFAULT 'INBOX',
    
    -- AI Classification
    classification VARCHAR(50),
    confidence_score DECIMAL(3,2),
    classification_date TIMESTAMP,
    
    -- Rule Matching
    rule_id INTEGER,
    auto_processed BOOLEAN DEFAULT false,
    
    -- Linking
    supplier_id INTEGER,
    customer_id INTEGER,
    linked_case_id INTEGER,
    linked_time_entry_id INTEGER,
    linked_purchase_id INTEGER,
    
    -- Metadata
    has_attachments BOOLEAN DEFAULT false,
    attachment_count INTEGER DEFAULT 0,
    is_read BOOLEAN DEFAULT false,
    status VARCHAR(50) DEFAULT 'new',
    approval_status VARCHAR(50),
    
    -- Extraction Fields
    extracted_invoice_number VARCHAR(100),
    extracted_order_number VARCHAR(100),
    extracted_tracking_number VARCHAR(100),
    extracted_amount DECIMAL(15,2),
    extracted_due_date DATE,
    
    -- Audit
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    processed_at TIMESTAMP,
    processed_by_user_id INTEGER,
    
    -- Soft Delete
    deleted_at TIMESTAMP,
    deleted_by_user_id INTEGER
);

-- Email Attachments Table
CREATE TABLE email_attachments (
    id SERIAL PRIMARY KEY,
    email_id INTEGER NOT NULL,
    filename VARCHAR(255) NOT NULL,
    content_type VARCHAR(100),
    size_bytes INTEGER,
    file_path TEXT,  -- Path in filesystem or object storage
    
    -- Extraction Status
    extracted BOOLEAN DEFAULT false,
    extraction_error TEXT,
    
    -- Metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (email_id) REFERENCES email_messages(id) ON DELETE CASCADE
);

-- Email Analysis Cache (for AI classifications)
CREATE TABLE email_analysis (
    id SERIAL PRIMARY KEY,
    email_id INTEGER NOT NULL,
    analysis_type VARCHAR(50) NOT NULL,  -- classification, extraction, summary
    
    -- AI Results
    result_json JSONB,
    confidence_score DECIMAL(3,2),
    model_used VARCHAR(100),
    
    -- Performance
    processing_time_ms INTEGER,
    
    -- Metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (email_id) REFERENCES email_messages(id) ON DELETE CASCADE,
    UNIQUE(email_id, analysis_type)
);

-- Indexes for Performance
CREATE INDEX idx_email_messages_sender ON email_messages(sender_email) WHERE deleted_at IS NULL;
CREATE INDEX idx_email_messages_classification ON email_messages(classification) WHERE deleted_at IS NULL;
CREATE INDEX idx_email_messages_status ON email_messages(status) WHERE deleted_at IS NULL;
CREATE INDEX idx_email_messages_received_date ON email_messages(received_date DESC) WHERE deleted_at IS NULL;
CREATE INDEX idx_email_messages_message_id ON email_messages(message_id);
CREATE INDEX idx_email_messages_supplier ON email_messages(supplier_id) WHERE supplier_id IS NOT NULL;
CREATE INDEX idx_email_messages_customer ON email_messages(customer_id) WHERE customer_id IS NOT NULL;
CREATE INDEX idx_email_messages_linked_case ON email_messages(linked_case_id) WHERE linked_case_id IS NOT NULL;
CREATE INDEX idx_email_attachments_email_id ON email_attachments(email_id);
CREATE INDEX idx_email_analysis_email_id ON email_analysis(email_id);
CREATE INDEX idx_email_rules_priority ON email_rules(priority) WHERE enabled = true;

-- Update Trigger for email_messages
CREATE OR REPLACE FUNCTION update_email_messages_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_email_messages_updated_at
    BEFORE UPDATE ON email_messages
    FOR EACH ROW
    EXECUTE FUNCTION update_email_messages_updated_at();

-- Update Trigger for email_rules
CREATE OR REPLACE FUNCTION update_email_rules_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_email_rules_updated_at
    BEFORE UPDATE ON email_rules
    FOR EACH ROW
    EXECUTE FUNCTION update_email_rules_updated_at();

-- View for unprocessed emails
CREATE OR REPLACE VIEW v_unprocessed_emails AS
SELECT 
    em.*,
    COUNT(ea.id) as attachment_count_actual,
    er.name as rule_name,
    v.name as supplier_name,
    tc.name as customer_name,
    tcase.title as case_title
FROM email_messages em
LEFT JOIN email_attachments ea ON em.id = ea.email_id
LEFT JOIN email_rules er ON em.rule_id = er.id
LEFT JOIN vendors v ON em.supplier_id = v.id
LEFT JOIN tmodule_customers tc ON em.customer_id = tc.id
LEFT JOIN tmodule_cases tcase ON em.linked_case_id = tcase.id
WHERE em.deleted_at IS NULL 
    AND em.status IN ('new', 'error')
GROUP BY em.id, er.name, v.name, tc.name, tcase.title
ORDER BY em.received_date DESC;

-- View for recent email activity
CREATE OR REPLACE VIEW v_email_activity AS
SELECT 
    DATE(em.received_date) as activity_date,
    em.classification,
    COUNT(*) as email_count,
    COUNT(CASE WHEN em.auto_processed THEN 1 END) as auto_processed_count,
    AVG(em.confidence_score) as avg_confidence
FROM email_messages em
WHERE em.deleted_at IS NULL
    AND em.received_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY DATE(em.received_date), em.classification
ORDER BY activity_date DESC, email_count DESC;

-- Sample email rules for common scenarios
INSERT INTO email_rules (name, description, conditions, action_type, action_params, priority, created_by_user_id)
VALUES 
    ('Mark Spam - Known Domains', 
     'Automatically mark emails from known spam domains as spam',
     '{"sender_domain": ["spamsite.com", "marketing-spam.net"], "action": "mark_spam"}',
     'mark_spam',
     '{}',
     10,
     1),
    
    ('Link Supplier Invoices', 
     'Automatically link invoices from known supplier email domains',
     '{"classification": "invoice", "sender_domain_match": "supplier"}',
     'link_supplier',
     '{"auto_match_domain": true}',
     50,
     1),
    
    ('Time Confirmation Auto-Link', 
     'Link time confirmation emails to cases based on case number in subject',
     '{"classification": "time_confirmation", "subject_regex": "CC[0-9]{4}"}',
     'link_case',
     '{"extract_case_from_subject": true}',
     30,
     1)
ON CONFLICT DO NOTHING;

COMMENT ON TABLE email_messages IS 'Main email storage with AI classification and linking';
COMMENT ON TABLE email_attachments IS 'Email attachment metadata and file references';
COMMENT ON TABLE email_analysis IS 'Cache for AI analysis results (classification, extraction)';
COMMENT ON TABLE email_rules IS 'Automatic email processing rules with priority matching';
