-- =====================================================
-- 009_ai_features.sql
-- AI-related schema for Template Manager: keywords, recommendations, queue, triggers
-- Safe for existing monorepo by using IF EXISTS/OR REPLACE and drop-if-exists for triggers
-- =====================================================

-- =====================================================
-- 1. CORE TABLES
-- NOTE: templates and custom_templates are already managed by existing migrations.
-- This migration intentionally does NOT create or modify those core tables.

-- =====================================================
-- 2. AI FEATURES TABLES
-- =====================================================

CREATE TABLE IF NOT EXISTS tech_stack_recommendations (
    id SERIAL PRIMARY KEY,
    template_id UUID NOT NULL,
    stack_name VARCHAR(255) NOT NULL,
    monthly_cost DECIMAL(10,2) NOT NULL,
    setup_cost DECIMAL(10,2) NOT NULL,
    team_size VARCHAR(50) NOT NULL,
    development_time INTEGER NOT NULL,
    satisfaction INTEGER NOT NULL CHECK (satisfaction >= 0 AND satisfaction <= 100),
    success_rate INTEGER NOT NULL CHECK (success_rate >= 0 AND success_rate <= 100),
    frontend VARCHAR(255) NOT NULL,
    backend VARCHAR(255) NOT NULL,
    database VARCHAR(255) NOT NULL,
    cloud VARCHAR(255) NOT NULL,
    testing VARCHAR(255) NOT NULL,
    mobile VARCHAR(255) NOT NULL,
    devops VARCHAR(255) NOT NULL,
    ai_ml VARCHAR(255) NOT NULL,
    recommended_tool VARCHAR(255) NOT NULL,
    recommendation_score DECIMAL(5,2) NOT NULL CHECK (recommendation_score >= 0 AND recommendation_score <= 100),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS extracted_keywords (
    id SERIAL PRIMARY KEY,
    template_id UUID NOT NULL,
    template_source VARCHAR(20) NOT NULL CHECK (template_source IN ('templates', 'custom_templates')),
    keywords_json JSONB NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(template_id, template_source)
);

CREATE TABLE IF NOT EXISTS migration_queue (
    id SERIAL PRIMARY KEY,
    template_id UUID NOT NULL,
    migration_type VARCHAR(50) NOT NULL,
    status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
    created_at TIMESTAMP DEFAULT NOW(),
    processed_at TIMESTAMP,
    error_message TEXT,
    UNIQUE(template_id, migration_type)
);

-- =====================================================
-- 3. INDEXES (idempotent)
-- =====================================================

-- (No new indexes on templates/custom_templates here)

CREATE INDEX IF NOT EXISTS idx_tech_stack_recommendations_template_id ON tech_stack_recommendations(template_id);
CREATE INDEX IF NOT EXISTS idx_tech_stack_recommendations_score ON tech_stack_recommendations(recommendation_score);

CREATE INDEX IF NOT EXISTS idx_extracted_keywords_template_id ON extracted_keywords(template_id);
CREATE INDEX IF NOT EXISTS idx_extracted_keywords_template_source ON extracted_keywords(template_source);

CREATE INDEX IF NOT EXISTS idx_migration_queue_status ON migration_queue(status);
CREATE INDEX IF NOT EXISTS idx_migration_queue_template_id ON migration_queue(template_id);

-- =====================================================
-- 4. FUNCTIONS (OR REPLACE)
-- =====================================================

CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION extract_keywords_for_template()
RETURNS TRIGGER AS $$
DECLARE
    keywords_list TEXT[];
    title_keywords TEXT[];
    desc_keywords TEXT[];
    final_keywords TEXT[];
    word TEXT;
    clean_word TEXT;
BEGIN
    IF NEW.type IN ('_system', '_migration', '_test', '_auto_tech_stack_migration', '_extracted_keywords_fix', '_migration_test', '_automation_fix', '_migration_queue_fix', '_workflow_fix', '_sql_ambiguity_fix', '_consolidated_schema') THEN
        RETURN NEW;
    END IF;

    IF EXISTS (SELECT 1 FROM extracted_keywords WHERE template_id = NEW.id AND template_source = 'templates') THEN
        RETURN NEW;
    END IF;

    keywords_list := ARRAY[]::TEXT[];

    IF NEW.title IS NOT NULL AND LENGTH(TRIM(NEW.title)) > 0 THEN
        title_keywords := string_to_array(LOWER(REGEXP_REPLACE(NEW.title, '[^a-zA-Z0-9\s]', ' ', 'g')), ' ');
        FOREACH word IN ARRAY title_keywords LOOP
            clean_word := TRIM(word);
            IF LENGTH(clean_word) > 2 AND clean_word NOT IN ('the','and','for','are','but','not','you','all','can','had','her','was','one','our','out','day','get','has','him','his','how','its','may','new','now','old','see','two','way','who','boy','did','man','men','put','say','she','too','use') THEN
                keywords_list := array_append(keywords_list, clean_word);
            END IF;
        END LOOP;
    END IF;

    IF NEW.description IS NOT NULL AND LENGTH(TRIM(NEW.description)) > 0 THEN
        desc_keywords := string_to_array(LOWER(REGEXP_REPLACE(NEW.description, '[^a-zA-Z0-9\s]', ' ', 'g')), ' ');
        FOREACH word IN ARRAY desc_keywords LOOP
            clean_word := TRIM(word);
            IF LENGTH(clean_word) > 2 AND clean_word NOT IN ('the','and','for','are','but','not','you','all','can','had','her','was','one','our','out','day','get','has','him','his','how','its','may','new','now','old','see','two','way','who','boy','did','man','men','put','say','she','too','use') THEN
                keywords_list := array_append(keywords_list, clean_word);
            END IF;
        END LOOP;
    END IF;

    IF NEW.category IS NOT NULL THEN
        keywords_list := array_append(keywords_list, LOWER(REGEXP_REPLACE(NEW.category, '[^a-zA-Z0-9]', '_', 'g')));
    END IF;

    IF NEW.type IS NOT NULL THEN
        keywords_list := array_append(keywords_list, LOWER(REGEXP_REPLACE(NEW.type, '[^a-zA-Z0-9]', '_', 'g')));
    END IF;

    SELECT ARRAY(
        SELECT DISTINCT unnest(keywords_list)
        ORDER BY 1
        LIMIT 15
    ) INTO final_keywords;

    WHILE array_length(final_keywords, 1) < 8 LOOP
        final_keywords := array_append(final_keywords, 'business_enterprise');
    END LOOP;

    INSERT INTO extracted_keywords (template_id, template_source, keywords_json)
    VALUES (NEW.id, 'templates', to_jsonb(final_keywords));

    RETURN NEW;
EXCEPTION WHEN OTHERS THEN
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION extract_keywords_for_custom_template()
RETURNS TRIGGER AS $$
DECLARE
    keywords_list TEXT[];
    title_keywords TEXT[];
    desc_keywords TEXT[];
    final_keywords TEXT[];
    word TEXT;
    clean_word TEXT;
BEGIN
    IF EXISTS (SELECT 1 FROM extracted_keywords WHERE template_id = NEW.id AND template_source = 'custom_templates') THEN
        RETURN NEW;
    END IF;

    keywords_list := ARRAY[]::TEXT[];

    IF NEW.title IS NOT NULL AND LENGTH(TRIM(NEW.title)) > 0 THEN
        title_keywords := string_to_array(LOWER(REGEXP_REPLACE(NEW.title, '[^a-zA-Z0-9\s]', ' ', 'g')), ' ');
        FOREACH word IN ARRAY title_keywords LOOP
            clean_word := TRIM(word);
            IF LENGTH(clean_word) > 2 AND clean_word NOT IN ('the','and','for','are','but','not','you','all','can','had','her','was','one','our','out','day','get','has','him','his','how','its','may','new','now','old','see','two','way','who','boy','did','man','men','put','say','she','too','use') THEN
                keywords_list := array_append(keywords_list, clean_word);
            END IF;
        END LOOP;
    END IF;

    IF NEW.description IS NOT NULL AND LENGTH(TRIM(NEW.description)) > 0 THEN
        desc_keywords := string_to_array(LOWER(REGEXP_REPLACE(NEW.description, '[^a-zA-Z0-9\s]', ' ', 'g')), ' ');
        FOREACH word IN ARRAY desc_keywords LOOP
            clean_word := TRIM(word);
            IF LENGTH(clean_word) > 2 AND clean_word NOT IN ('the','and','for','are','but','not','you','all','can','had','her','was','one','our','out','day','get','has','him','his','how','its','may','new','now','old','see','two','way','who','boy','did','man','men','put','say','she','too','use') THEN
                keywords_list := array_append(keywords_list, clean_word);
            END IF;
        END LOOP;
    END IF;

    IF NEW.category IS NOT NULL THEN
        keywords_list := array_append(keywords_list, LOWER(REGEXP_REPLACE(NEW.category, '[^a-zA-Z0-9]', '_', 'g')));
    END IF;

    IF NEW.type IS NOT NULL THEN
        keywords_list := array_append(keywords_list, LOWER(REGEXP_REPLACE(NEW.type, '[^a-zA-Z0-9]', '_', 'g')));
    END IF;

    SELECT ARRAY(
        SELECT DISTINCT unnest(keywords_list)
        ORDER BY 1
        LIMIT 15
    ) INTO final_keywords;

    WHILE array_length(final_keywords, 1) < 8 LOOP
        final_keywords := array_append(final_keywords, 'business_enterprise');
    END LOOP;

    INSERT INTO extracted_keywords (template_id, template_source, keywords_json)
    VALUES (NEW.id, 'custom_templates', to_jsonb(final_keywords));

    RETURN NEW;
EXCEPTION WHEN OTHERS THEN
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION generate_tech_stack_recommendation()
RETURNS TRIGGER AS $$
DECLARE
    keywords_json_data JSONB;
    keywords_list TEXT[];
    stack_name TEXT;
    monthly_cost DECIMAL(10,2);
    setup_cost DECIMAL(10,2);
    team_size TEXT;
    development_time INTEGER;
    satisfaction INTEGER;
    success_rate INTEGER;
    frontend TEXT;
    backend TEXT;
    database_tech TEXT;
    cloud TEXT;
    testing TEXT;
    mobile TEXT;
    devops TEXT;
    ai_ml TEXT;
    recommended_tool TEXT;
    recommendation_score DECIMAL(5,2);
BEGIN
    IF NEW.type IN ('_system', '_migration', '_test', '_auto_tech_stack_migration', '_extracted_keywords_fix', '_migration_test', '_automation_fix', '_migration_queue_fix', '_workflow_fix', '_sql_ambiguity_fix', '_consolidated_schema') THEN
        RETURN NEW;
    END IF;

    IF EXISTS (SELECT 1 FROM tech_stack_recommendations WHERE template_id = NEW.id) THEN
        RETURN NEW;
    END IF;

    SELECT ek.keywords_json INTO keywords_json_data
    FROM extracted_keywords ek
    WHERE ek.template_id = NEW.id AND ek.template_source = 'templates'
    ORDER BY ek.created_at DESC LIMIT 1;

    IF keywords_json_data IS NULL THEN
        INSERT INTO tech_stack_recommendations (
            template_id, stack_name, monthly_cost, setup_cost, team_size,
            development_time, satisfaction, success_rate, frontend, backend,
            database, cloud, testing, mobile, devops, ai_ml, recommended_tool,
            recommendation_score
        ) VALUES (
            NEW.id, NEW.title || ' Tech Stack', 100.0, 2000.0, '3-5',
            6, 85, 90, 'React.js', 'Node.js',
            'PostgreSQL', 'AWS', 'Jest', 'React Native', 'Docker', 'TensorFlow', 'Custom Tool',
            85.0
        );

        INSERT INTO migration_queue (template_id, migration_type, status, created_at)
        VALUES (NEW.id, 'tech_stack_recommendation', 'pending', NOW())
        ON CONFLICT (template_id, migration_type) DO UPDATE SET
            status = 'pending', created_at = NOW(), processed_at = NULL, error_message = NULL;

        RETURN NEW;
    END IF;

    SELECT ARRAY(SELECT jsonb_array_elements_text(keywords_json_data)) INTO keywords_list;

    stack_name := NEW.title || ' AI-Recommended Tech Stack';

    CASE NEW.category
        WHEN 'Healthcare' THEN
            monthly_cost := 200.0; setup_cost := 5000.0; team_size := '6-8'; development_time := 10;
            satisfaction := 92; success_rate := 90; frontend := 'React.js'; backend := 'Java Spring Boot';
            database_tech := 'MongoDB'; cloud := 'AWS'; testing := 'JUnit'; mobile := 'Flutter'; devops := 'Jenkins';
            ai_ml := 'TensorFlow'; recommended_tool := 'Salesforce Health Cloud'; recommendation_score := 94.0;
        WHEN 'E-commerce' THEN
            monthly_cost := 150.0; setup_cost := 3000.0; team_size := '4-6'; development_time := 8;
            satisfaction := 88; success_rate := 92; frontend := 'Next.js'; backend := 'Node.js';
            database_tech := 'MongoDB'; cloud := 'AWS'; testing := 'Jest'; mobile := 'React Native'; devops := 'Docker';
            ai_ml := 'TensorFlow'; recommended_tool := 'Shopify'; recommendation_score := 90.0;
        ELSE
            monthly_cost := 100.0; setup_cost := 2000.0; team_size := '3-5'; development_time := 6;
            satisfaction := 85; success_rate := 90; frontend := 'React.js'; backend := 'Node.js';
            database_tech := 'PostgreSQL'; cloud := 'AWS'; testing := 'Jest'; mobile := 'React Native'; devops := 'Docker';
            ai_ml := 'TensorFlow'; recommended_tool := 'Custom Tool'; recommendation_score := 85.0;
    END CASE;

    INSERT INTO tech_stack_recommendations (
        template_id, stack_name, monthly_cost, setup_cost, team_size,
        development_time, satisfaction, success_rate, frontend, backend,
        database, cloud, testing, mobile, devops, ai_ml, recommended_tool,
        recommendation_score
    ) VALUES (
        NEW.id, stack_name, monthly_cost, setup_cost, team_size,
        development_time, satisfaction, success_rate, frontend, backend,
        database_tech, cloud, testing, mobile, devops, ai_ml, recommended_tool,
        recommendation_score
    );

    INSERT INTO migration_queue (template_id, migration_type, status, created_at)
    VALUES (NEW.id, 'tech_stack_recommendation', 'pending', NOW())
    ON CONFLICT (template_id, migration_type) DO UPDATE SET
        status = 'pending', created_at = NOW(), processed_at = NULL, error_message = NULL;

    RETURN NEW;
EXCEPTION WHEN OTHERS THEN
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION generate_tech_stack_recommendation_custom()
RETURNS TRIGGER AS $$
DECLARE
    keywords_json_data JSONB;
    keywords_list TEXT[];
    stack_name TEXT;
    monthly_cost DECIMAL(10,2);
    setup_cost DECIMAL(10,2);
    team_size TEXT;
    development_time INTEGER;
    satisfaction INTEGER;
    success_rate INTEGER;
    frontend TEXT;
    backend TEXT;
    database_tech TEXT;
    cloud TEXT;
    testing TEXT;
    mobile TEXT;
    devops TEXT;
    ai_ml TEXT;
    recommended_tool TEXT;
    recommendation_score DECIMAL(5,2);
BEGIN
    IF EXISTS (SELECT 1 FROM tech_stack_recommendations WHERE template_id = NEW.id) THEN
        RETURN NEW;
    END IF;

    SELECT ek.keywords_json INTO keywords_json_data
    FROM extracted_keywords ek
    WHERE ek.template_id = NEW.id AND ek.template_source = 'custom_templates'
    ORDER BY ek.created_at DESC LIMIT 1;

    IF keywords_json_data IS NULL THEN
        INSERT INTO tech_stack_recommendations (
            template_id, stack_name, monthly_cost, setup_cost, team_size,
            development_time, satisfaction, success_rate, frontend, backend,
            database, cloud, testing, mobile, devops, ai_ml, recommended_tool,
            recommendation_score
        ) VALUES (
            NEW.id, NEW.title || ' Custom Tech Stack', 180.0, 3500.0, '5-7',
            9, 88, 92, 'Vue.js', 'Python Django',
            'MongoDB', 'Google Cloud', 'Cypress', 'Flutter', 'Kubernetes', 'PyTorch', 'Custom Business Tool',
            90.0
        );

        INSERT INTO migration_queue (template_id, migration_type, status, created_at)
        VALUES (NEW.id, 'tech_stack_recommendation', 'pending', NOW())
        ON CONFLICT (template_id, migration_type) DO UPDATE SET
            status = 'pending', created_at = NOW(), processed_at = NULL, error_message = NULL;

        RETURN NEW;
    END IF;

    SELECT ARRAY(SELECT jsonb_array_elements_text(keywords_json_data)) INTO keywords_list;

    stack_name := NEW.title || ' Custom AI-Recommended Tech Stack';

    CASE NEW.category
        WHEN 'Healthcare' THEN
            monthly_cost := 250.0; setup_cost := 6000.0; team_size := '7-9'; development_time := 12;
            satisfaction := 94; success_rate := 92; frontend := 'React.js'; backend := 'Java Spring Boot';
            database_tech := 'MongoDB'; cloud := 'AWS'; testing := 'JUnit'; mobile := 'Flutter'; devops := 'Jenkins';
            ai_ml := 'TensorFlow'; recommended_tool := 'Custom Healthcare Tool'; recommendation_score := 95.0;
        WHEN 'E-commerce' THEN
            monthly_cost := 200.0; setup_cost := 4000.0; team_size := '5-7'; development_time := 10;
            satisfaction := 90; success_rate := 94; frontend := 'Next.js'; backend := 'Node.js';
            database_tech := 'MongoDB'; cloud := 'AWS'; testing := 'Jest'; mobile := 'React Native'; devops := 'Docker';
            ai_ml := 'TensorFlow'; recommended_tool := 'Custom E-commerce Tool'; recommendation_score := 92.0;
        ELSE
            monthly_cost := 180.0; setup_cost := 3500.0; team_size := '5-7'; development_time := 9;
            satisfaction := 88; success_rate := 92; frontend := 'Vue.js'; backend := 'Python Django';
            database_tech := 'MongoDB'; cloud := 'Google Cloud'; testing := 'Cypress'; mobile := 'Flutter'; devops := 'Kubernetes';
            ai_ml := 'PyTorch'; recommended_tool := 'Custom Business Tool'; recommendation_score := 90.0;
    END CASE;

    INSERT INTO tech_stack_recommendations (
        template_id, stack_name, monthly_cost, setup_cost, team_size,
        development_time, satisfaction, success_rate, frontend, backend,
        database, cloud, testing, mobile, devops, ai_ml, recommended_tool,
        recommendation_score
    ) VALUES (
        NEW.id, stack_name, monthly_cost, setup_cost, team_size,
        development_time, satisfaction, success_rate, frontend, backend,
        database_tech, cloud, testing, mobile, devops, ai_ml, recommended_tool,
        recommendation_score
    );

    INSERT INTO migration_queue (template_id, migration_type, status, created_at)
    VALUES (NEW.id, 'tech_stack_recommendation', 'pending', NOW())
    ON CONFLICT (template_id, migration_type) DO UPDATE SET
        status = 'pending', created_at = NOW(), processed_at = NULL, error_message = NULL;

    RETURN NEW;
EXCEPTION WHEN OTHERS THEN
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- =====================================================
-- 5. TRIGGERS (conditionally create AI-related triggers only)
-- =====================================================

-- Keyword extraction triggers (create if not exists)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_trigger WHERE tgname = 'auto_extract_keywords'
    ) THEN
        CREATE TRIGGER auto_extract_keywords
            AFTER INSERT ON templates
            FOR EACH ROW
            EXECUTE FUNCTION extract_keywords_for_template();
    END IF;
END $$;

DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_trigger WHERE tgname = 'auto_extract_keywords_custom'
    ) THEN
        CREATE TRIGGER auto_extract_keywords_custom
            AFTER INSERT ON custom_templates
            FOR EACH ROW
            EXECUTE FUNCTION extract_keywords_for_custom_template();
    END IF;
END $$;

-- AI recommendation triggers (create if not exists)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_trigger WHERE tgname = 'auto_generate_tech_stack_recommendation'
    ) THEN
        CREATE TRIGGER auto_generate_tech_stack_recommendation
            AFTER INSERT ON templates
            FOR EACH ROW
            EXECUTE FUNCTION generate_tech_stack_recommendation();
    END IF;
END $$;

DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_trigger WHERE tgname = 'auto_generate_tech_stack_recommendation_custom'
    ) THEN
        CREATE TRIGGER auto_generate_tech_stack_recommendation_custom
            AFTER INSERT ON custom_templates
            FOR EACH ROW
            EXECUTE FUNCTION generate_tech_stack_recommendation_custom();
    END IF;
END $$;

-- Success marker (idempotent)
DO $$ BEGIN
    INSERT INTO templates (type, title, description, category)
    VALUES ('_consolidated_schema', 'Consolidated Schema', 'AI features added via 009_ai_features', 'System')
    ON CONFLICT (type) DO NOTHING;
END $$;


