// app/modules/dev_tools/static/admin/js/sql-query.js

const sqlLog = window.LogConfig.createLogger('SQL_QUERY');

/**
 * SQL Query Tool Alpine.js Component
 * Execute ad-hoc SQL queries and manage saved queries.
 */
function sqlQueryTool() {
    return {
        // Inherit base layout functionality
        ...data(),

        // Page identifier
        currentPage: 'sql-query',

        // Editor state
        sql: '',
        running: false,
        error: null,

        // Results
        columns: [],
        rows: [],
        rowCount: 0,
        truncated: false,
        executionTimeMs: null,

        // Saved queries
        savedQueries: [],
        loadingSaved: false,
        activeSavedId: null,

        // Save modal
        showSaveModal: false,
        saveName: '',
        saveDescription: '',
        saving: false,

        // Schema explorer
        showPresets: true,
        expandedCategories: {},
        presetQueries: [
            {
                category: 'Schema',
                items: [
                    { name: 'All tables', sql: "SELECT table_name, pg_size_pretty(pg_total_relation_size(quote_ident(table_name))) AS size\nFROM information_schema.tables\nWHERE table_schema = 'public'\nORDER BY table_name;" },
                    { name: 'Columns for table', sql: "SELECT column_name, data_type, is_nullable, column_default,\n  character_maximum_length\nFROM information_schema.columns\nWHERE table_schema = 'public'\n  AND table_name = 'REPLACE_TABLE_NAME'\nORDER BY ordinal_position;" },
                    { name: 'Foreign keys', sql: "SELECT\n  tc.table_name, kcu.column_name,\n  ccu.table_name AS foreign_table,\n  ccu.column_name AS foreign_column\nFROM information_schema.table_constraints tc\nJOIN information_schema.key_column_usage kcu\n  ON tc.constraint_name = kcu.constraint_name\nJOIN information_schema.constraint_column_usage ccu\n  ON ccu.constraint_name = tc.constraint_name\nWHERE tc.constraint_type = 'FOREIGN KEY'\nORDER BY tc.table_name, kcu.column_name;" },
                    { name: 'Indexes', sql: "SELECT tablename, indexname, indexdef\nFROM pg_indexes\nWHERE schemaname = 'public'\nORDER BY tablename, indexname;" },
                ]
            },
            {
                category: 'Statistics',
                items: [
                    { name: 'Table row counts', sql: "SELECT relname AS table_name,\n  n_live_tup AS row_count\nFROM pg_stat_user_tables\nORDER BY n_live_tup DESC;" },
                    { name: 'Table sizes', sql: "SELECT relname AS table_name,\n  pg_size_pretty(pg_total_relation_size(relid)) AS total_size,\n  pg_size_pretty(pg_relation_size(relid)) AS data_size,\n  pg_size_pretty(pg_indexes_size(relid)) AS index_size\nFROM pg_catalog.pg_statio_user_tables\nORDER BY pg_total_relation_size(relid) DESC;" },
                    { name: 'Database size', sql: "SELECT pg_size_pretty(pg_database_size(current_database())) AS db_size,\n  current_database() AS db_name,\n  version() AS pg_version;" },
                ]
            },
            {
                category: 'Tenancy',
                items: [
                    { name: 'Users', sql: "SELECT id, email, username, role, is_active,\n  last_login, created_at\nFROM users\nORDER BY id\nLIMIT 50;" },
                    { name: 'Merchants', sql: "SELECT m.id, m.name,\n  u.email AS owner_email, m.contact_email,\n  m.is_active, m.is_verified, m.created_at\nFROM merchants m\nJOIN users u ON u.id = m.owner_user_id\nORDER BY m.id\nLIMIT 50;" },
                    { name: 'Stores', sql: "SELECT id, store_code, name, merchant_id,\n  subdomain, is_active, is_verified\nFROM stores\nORDER BY id\nLIMIT 50;" },
                    { name: 'Platforms', sql: "SELECT id, code, name, domain, path_prefix,\n  default_language, is_active, is_public\nFROM platforms\nORDER BY id;" },
                    { name: 'Customers', sql: "SELECT id, store_id, email, first_name, last_name,\n  is_active, created_at\nFROM customers\nORDER BY id\nLIMIT 50;" },
                ]
            },
            {
                category: 'Permissions',
                items: [
                    { name: 'Roles per store', sql: "SELECT r.id, r.store_id, s.name AS store_name,\n  r.name AS role_name, r.permissions\nFROM roles r\nJOIN stores s ON s.id = r.store_id\nORDER BY s.name, r.name;" },
                    { name: 'Store team members', sql: "SELECT su.id, su.store_id, s.name AS store_name,\n  u.email, u.username, r.name AS role_name,\n  su.is_active, su.invitation_accepted_at\nFROM store_users su\nJOIN stores s ON s.id = su.store_id\nJOIN users u ON u.id = su.user_id\nLEFT JOIN roles r ON r.id = su.role_id\nORDER BY s.name, u.email\nLIMIT 100;" },
                    { name: 'Admin platform assignments', sql: "SELECT ap.id, u.email, u.username, u.role,\n  p.code AS platform_code, p.name AS platform_name,\n  ap.is_active, ap.assigned_at\nFROM admin_platforms ap\nJOIN users u ON u.id = ap.user_id\nJOIN platforms p ON p.id = ap.platform_id\nORDER BY u.email, p.code;" },
                    { name: 'Platform modules', sql: "SELECT pm.id, p.code AS platform_code,\n  pm.module_code, pm.is_enabled,\n  pm.enabled_at, pm.disabled_at\nFROM platform_modules pm\nJOIN platforms p ON p.id = pm.platform_id\nORDER BY p.code, pm.module_code;" },
                    { name: 'Store platforms', sql: "SELECT sp.id, s.name AS store_name,\n  p.code AS platform_code,\n  sp.is_active, sp.custom_subdomain, sp.joined_at\nFROM store_platforms sp\nJOIN stores s ON s.id = sp.store_id\nJOIN platforms p ON p.id = sp.platform_id\nORDER BY s.name, p.code;" },
                ]
            },
            {
                category: 'System',
                items: [
                    { name: 'Alembic versions', sql: "SELECT * FROM alembic_version\nORDER BY version_num;" },
                ]
            },
            {
                category: 'Loyalty',
                items: [
                    { name: 'Programs', sql: "SELECT lp.id, lp.merchant_id, lp.loyalty_type,\n  lp.stamps_target, lp.points_per_euro, lp.is_active,\n  lp.activated_at, lp.created_at\nFROM loyalty_programs lp\nORDER BY lp.id DESC;" },
                    { name: 'Cards', sql: "SELECT lc.id, lc.card_number, c.email AS customer_email,\n  lc.stamp_count, lc.points_balance, lc.is_active,\n  lc.last_activity_at, lc.created_at\nFROM loyalty_cards lc\nJOIN customers c ON c.id = lc.customer_id\nORDER BY lc.id DESC\nLIMIT 100;" },
                    { name: 'Transactions', sql: "SELECT lt.id, lt.transaction_type, lc.card_number,\n  lt.stamps_delta, lt.points_delta,\n  lt.purchase_amount_cents, lt.transaction_at\nFROM loyalty_transactions lt\nJOIN loyalty_cards lc ON lc.id = lt.card_id\nORDER BY lt.transaction_at DESC\nLIMIT 100;" },
                    { name: 'Staff PINs', sql: "SELECT sp.id, sp.name, sp.staff_id,\n  s.name AS store_name, sp.is_active,\n  sp.last_used_at, sp.created_at\nFROM staff_pins sp\nJOIN stores s ON s.id = sp.store_id\nORDER BY sp.id DESC;" },
                ]
            },
            {
                category: 'Billing',
                items: [
                    { name: 'Subscription tiers', sql: "SELECT st.id, p.code AS platform_code,\n  st.code, st.name, st.price_monthly_cents,\n  st.price_annual_cents, st.is_active, st.is_public\nFROM subscription_tiers st\nJOIN platforms p ON p.id = st.platform_id\nORDER BY p.code, st.display_order;" },
                    { name: 'Merchant subscriptions', sql: "SELECT ms.id, m.name AS merchant_name,\n  p.code AS platform_code, st.name AS tier_name,\n  ms.status, ms.is_annual,\n  ms.stripe_customer_id, ms.stripe_subscription_id\nFROM merchant_subscriptions ms\nJOIN merchants m ON m.id = ms.merchant_id\nJOIN platforms p ON p.id = ms.platform_id\nLEFT JOIN subscription_tiers st ON st.id = ms.tier_id\nORDER BY ms.id DESC;" },
                    { name: 'Billing history', sql: "SELECT bh.id, s.name AS store_name,\n  bh.invoice_number, bh.total_cents,\n  bh.currency, bh.status, bh.invoice_date\nFROM billing_history bh\nJOIN stores s ON s.id = bh.store_id\nORDER BY bh.invoice_date DESC\nLIMIT 50;" },
                    { name: 'Add-on products', sql: "SELECT id, code, name, category,\n  price_cents, billing_period, is_active\nFROM addon_products\nORDER BY display_order;" },
                ]
            },
            {
                category: 'Orders',
                items: [
                    { name: 'Recent orders', sql: "SELECT o.id, s.name AS store_name,\n  o.order_number, o.status, o.total_amount_cents,\n  o.customer_email, o.order_date\nFROM orders o\nJOIN stores s ON s.id = o.store_id\nORDER BY o.order_date DESC\nLIMIT 50;" },
                    { name: 'Order items', sql: "SELECT oi.id, o.order_number, oi.product_name,\n  oi.product_sku, oi.quantity, oi.unit_price_cents,\n  oi.item_state\nFROM order_items oi\nJOIN orders o ON o.id = oi.order_id\nORDER BY oi.id DESC\nLIMIT 100;" },
                    { name: 'Invoices', sql: "SELECT i.id, s.name AS store_name,\n  i.invoice_number, i.status,\n  i.total_cents, i.invoice_date\nFROM invoices i\nJOIN stores s ON s.id = i.store_id\nORDER BY i.invoice_date DESC\nLIMIT 50;" },
                ]
            },
            {
                category: 'Catalog',
                items: [
                    { name: 'Products', sql: "SELECT p.id, s.name AS store_name,\n  p.store_sku, p.gtin, p.price_cents,\n  p.availability, p.is_active\nFROM products p\nJOIN stores s ON s.id = p.store_id\nORDER BY p.id DESC\nLIMIT 50;" },
                    { name: 'Product translations', sql: "SELECT pt.id, p.store_sku,\n  pt.language, pt.title\nFROM product_translations pt\nJOIN products p ON p.id = pt.product_id\nORDER BY pt.id DESC\nLIMIT 50;" },
                    { name: 'Product media', sql: "SELECT pm.id, p.store_sku,\n  pm.usage_type, pm.display_order\nFROM product_media pm\nJOIN products p ON p.id = pm.product_id\nORDER BY pm.id DESC\nLIMIT 50;" },
                ]
            },
            {
                category: 'Customers',
                items: [
                    { name: 'Customers', sql: "SELECT c.id, s.name AS store_name,\n  c.email, c.first_name, c.last_name,\n  c.customer_number, c.is_active\nFROM customers c\nJOIN stores s ON s.id = c.store_id\nORDER BY c.id DESC\nLIMIT 50;" },
                    { name: 'Customer addresses', sql: "SELECT ca.id, c.email AS customer_email,\n  ca.address_type, ca.city, ca.country_iso,\n  ca.is_default\nFROM customer_addresses ca\nJOIN customers c ON c.id = ca.customer_id\nORDER BY ca.id DESC\nLIMIT 50;" },
                ]
            },
            {
                category: 'Inventory',
                items: [
                    { name: 'Stock levels', sql: "SELECT inv.id, s.name AS store_name,\n  p.store_sku, inv.quantity,\n  inv.reserved_quantity, inv.warehouse\nFROM inventory inv\nJOIN products p ON p.id = inv.product_id\nJOIN stores s ON s.id = inv.store_id\nORDER BY inv.id DESC;" },
                    { name: 'Recent transactions', sql: "SELECT it.id, p.store_sku,\n  it.transaction_type, it.quantity_change,\n  it.order_number, it.created_at\nFROM inventory_transactions it\nJOIN products p ON p.id = it.product_id\nORDER BY it.created_at DESC\nLIMIT 100;" },
                ]
            },
            {
                category: 'CMS',
                items: [
                    { name: 'Content pages', sql: "SELECT cp.id, cp.slug, cp.title,\n  cp.is_published, cp.is_platform_page,\n  s.name AS store_name, p.code AS platform_code\nFROM content_pages cp\nLEFT JOIN stores s ON s.id = cp.store_id\nLEFT JOIN platforms p ON p.id = cp.platform_id\nORDER BY cp.id DESC\nLIMIT 50;" },
                    { name: 'Media files', sql: "SELECT mf.id, s.name AS store_name,\n  mf.filename, mf.media_type,\n  mf.file_size, mf.usage_count\nFROM media_files mf\nJOIN stores s ON s.id = mf.store_id\nORDER BY mf.id DESC\nLIMIT 50;" },
                    { name: 'Store themes', sql: "SELECT st.id, s.name AS store_name,\n  st.theme_name, st.is_active, st.layout_style\nFROM store_themes st\nJOIN stores s ON s.id = st.store_id\nORDER BY st.id DESC;" },
                ]
            },
            {
                category: 'Messaging',
                items: [
                    { name: 'Email templates', sql: "SELECT id, code, language, name,\n  category, is_active\nFROM email_templates\nORDER BY category, code, language;" },
                    { name: 'Email logs', sql: "SELECT id, recipient_email, subject,\n  status, sent_at, provider\nFROM email_logs\nORDER BY sent_at DESC\nLIMIT 50;" },
                    { name: 'Admin notifications', sql: "SELECT id, type, priority, title,\n  is_read, action_required, created_at\nFROM admin_notifications\nORDER BY created_at DESC\nLIMIT 50;" },
                ]
            },
            {
                category: 'Marketplace',
                items: [
                    { name: 'Import jobs', sql: "SELECT mij.id, s.name AS store_name,\n  mij.marketplace, mij.status,\n  mij.imported_count, mij.error_count,\n  mij.created_at\nFROM marketplace_import_jobs mij\nJOIN stores s ON s.id = mij.store_id\nORDER BY mij.created_at DESC\nLIMIT 50;" },
                    { name: 'Marketplace products', sql: "SELECT id, marketplace, brand, gtin,\n  price_cents, availability, is_active\nFROM marketplace_products\nORDER BY id DESC\nLIMIT 50;" },
                    { name: 'Fulfillment queue', sql: "SELECT fq.id, s.name AS store_name,\n  fq.operation, fq.status, fq.attempts,\n  fq.error_message, fq.created_at\nFROM letzshop_fulfillment_queue fq\nJOIN stores s ON s.id = fq.store_id\nORDER BY fq.created_at DESC\nLIMIT 50;" },
                ]
            },
        ],

        toggleCategory(category) {
            this.expandedCategories[category] = !this.expandedCategories[category];
        },

        isCategoryExpanded(category) {
            return this.expandedCategories[category] || false;
        },

        async init() {
            if (window._sqlQueryInitialized) return;
            window._sqlQueryInitialized = true;

            this.$nextTick(() => {
                if (typeof this.initBase === 'function') this.initBase();
            });

            try {
                await this.loadSavedQueries();
            } catch (e) {
                sqlLog.error('Failed to initialize:', e);
            }

            // Ctrl+Enter shortcut
            document.addEventListener('keydown', (e) => {
                if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
                    e.preventDefault();
                    this.executeQuery();
                }
            });
        },

        async executeQuery() {
            if (!this.sql.trim() || this.running) return;
            this.running = true;
            this.error = null;
            this.columns = [];
            this.rows = [];
            this.rowCount = 0;
            this.truncated = false;
            this.executionTimeMs = null;

            try {
                const payload = { sql: this.sql };
                if (this.activeSavedId) {
                    payload.saved_query_id = this.activeSavedId;
                }
                const data = await apiClient.post('/admin/sql-query/execute', payload);
                this.columns = data.columns;
                this.rows = data.rows;
                this.rowCount = data.row_count;
                this.truncated = data.truncated;
                this.executionTimeMs = data.execution_time_ms;

                // Refresh saved queries to update run_count
                if (this.activeSavedId) {
                    await this.loadSavedQueries();
                }
            } catch (e) {
                this.error = e.message;
            } finally {
                this.running = false;
            }
        },

        async loadSavedQueries() {
            this.loadingSaved = true;
            try {
                this.savedQueries = await apiClient.get('/admin/sql-query/saved');
            } catch (e) {
                sqlLog.error('Failed to load saved queries:', e);
            } finally {
                this.loadingSaved = false;
            }
        },

        loadQuery(q) {
            this.sql = q.sql_text;
            this.activeSavedId = q.id;
            this.error = null;
        },

        loadPreset(preset) {
            this.sql = preset.sql;
            this.activeSavedId = null;
            this.error = null;
        },

        openSaveModal() {
            this.saveName = '';
            this.saveDescription = '';
            this.showSaveModal = true;
        },

        async saveQuery() {
            if (!this.saveName.trim() || !this.sql.trim()) return;
            this.saving = true;
            try {
                const saved = await apiClient.post('/admin/sql-query/saved', {
                    name: this.saveName,
                    sql_text: this.sql,
                    description: this.saveDescription || null,
                });
                this.activeSavedId = saved.id;
                this.showSaveModal = false;
                await this.loadSavedQueries();
            } catch (e) {
                this.error = e.message;
            } finally {
                this.saving = false;
            }
        },

        async deleteSavedQuery(id) {
            if (!confirm('Delete this saved query?')) return;
            try {
                await apiClient.delete(`/admin/sql-query/saved/${id}`);
                if (this.activeSavedId === id) {
                    this.activeSavedId = null;
                }
                await this.loadSavedQueries();
            } catch (e) {
                sqlLog.error('Failed to delete:', e);
            }
        },

        exportCsv() {
            if (!this.columns.length || !this.rows.length) return;

            const escape = (val) => {
                if (val === null || val === undefined) return '';
                const s = String(val);
                if (s.includes(',') || s.includes('"') || s.includes('\n')) {
                    return '"' + s.replace(/"/g, '""') + '"';
                }
                return s;
            };

            const lines = [this.columns.map(escape).join(',')];
            for (const row of this.rows) {
                lines.push(row.map(escape).join(','));
            }

            const blob = new Blob([lines.join('\n')], { type: 'text/csv' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'query-results.csv';
            a.click();
            URL.revokeObjectURL(url);
        },

        formatCell(val) {
            if (val === null || val === undefined) return 'NULL';
            return String(val);
        },

        isNull(val) {
            return val === null || val === undefined;
        },
    };
}
