#!/usr/bin/env node
/**
 * CRUD Operations UI Tests
 *
 * Tests for create, update, delete operations on collections, subscriptions, and documents.
 *
 * Run: node test_crud_operations_ci.js
 */

const { setupTest, teardownTest, TestResults, log, delay, navigateTo, withTimeout } = require('./test_lib');

// ============================================================================
// Collection CRUD Tests
// ============================================================================
const CollectionCrudTests = {
    async createCollectionFormOpens(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/collections`);

        // Find and click create button
        const clicked = await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn, .btn'));
            const createBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('create') || text.includes('new') || text.includes('add');
            });

            if (createBtn) {
                createBtn.click();
                return true;
            }
            return false;
        });

        if (!clicked) {
            return { passed: null, skipped: true, message: 'No create collection button found' };
        }

        await delay(500);

        const result = await page.evaluate(() => {
            const modal = document.querySelector('.modal, .dialog, [role="dialog"], .form-modal');
            const form = document.querySelector('form.collection-form, form[action*="collection"], .create-form');

            return {
                hasModal: !!modal && (modal.style.display !== 'none'),
                hasForm: !!form,
                hasNameInput: !!document.querySelector('input[name*="name"], input[placeholder*="name"], #collection-name'),
                hasSubmitBtn: !!document.querySelector('button[type="submit"], .btn-primary, .save-btn')
            };
        });

        const passed = result.hasModal || result.hasForm;
        return {
            passed,
            message: passed
                ? `Create collection form opens (modal=${result.hasModal}, nameInput=${result.hasNameInput})`
                : 'Create collection form did not open'
        };
    },

    async createCollectionFormValidation(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/collections`);

        // Click create button
        await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn, .btn'));
            const createBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('create') || text.includes('new') || text.includes('add');
            });
            if (createBtn) createBtn.click();
        });

        await delay(500);

        // Try to submit empty form
        const result = await page.evaluate(() => {
            const submitBtn = document.querySelector('button[type="submit"], .btn-primary, .save-btn');
            if (submitBtn) submitBtn.click();

            // Check for validation errors
            return new Promise(resolve => {
                setTimeout(() => {
                    const hasValidationError = !!document.querySelector(
                        '.error, .invalid-feedback, .form-error, [class*="error"], .validation-message'
                    );
                    const hasRequiredIndicator = !!document.querySelector(
                        'input:invalid, .required, [required]'
                    );
                    resolve({ hasValidationError, hasRequiredIndicator });
                }, 300);
            });
        });

        if (!result.hasValidationError && !result.hasRequiredIndicator) {
            return { passed: null, skipped: true, message: 'No form validation detected (may submit empty)' };
        }

        return {
            passed: true,
            message: `Form validation works (error=${result.hasValidationError}, required=${result.hasRequiredIndicator})`
        };
    },

    async collectionEditButton(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/collections`);

        const result = await page.evaluate(() => {
            const cards = document.querySelectorAll('.collection-card, .collection-item, [data-collection-id]');
            if (cards.length === 0) return { hasCards: false };

            const firstCard = cards[0];
            const editBtn = firstCard.querySelector(
                'button[class*="edit"], ' +
                'a[class*="edit"], ' +
                '.edit-btn, ' +
                '[title*="edit"], ' +
                '.fa-edit, .fa-pencil'
            );

            return {
                hasCards: true,
                cardCount: cards.length,
                hasEditButton: !!editBtn,
                editBtnText: editBtn?.textContent?.trim() || editBtn?.title
            };
        });

        if (!result.hasCards) {
            return { passed: null, skipped: true, message: 'No collections to test edit button' };
        }

        if (!result.hasEditButton) {
            return { passed: null, skipped: true, message: 'No edit button found on collection cards' };
        }

        return {
            passed: true,
            message: `Edit button found on ${result.cardCount} collections`
        };
    },

    async collectionDeleteConfirmation(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/collections`);

        const result = await page.evaluate(() => {
            const cards = document.querySelectorAll('.collection-card, .collection-item, [data-collection-id]');
            if (cards.length === 0) return { hasCards: false };

            const firstCard = cards[0];
            const deleteBtn = firstCard.querySelector(
                'button[class*="delete"], ' +
                'button[class*="remove"], ' +
                '.delete-btn, ' +
                '.btn-danger, ' +
                '.fa-trash, .fa-times'
            );

            if (!deleteBtn) return { hasCards: true, hasDeleteButton: false };

            // Click delete to check for confirmation
            deleteBtn.click();

            return new Promise(resolve => {
                setTimeout(() => {
                    const confirmModal = document.querySelector(
                        '.modal, .confirm-dialog, [role="alertdialog"], .confirmation'
                    );
                    const confirmText = document.body.textContent?.toLowerCase() || '';
                    const hasConfirmText = confirmText.includes('are you sure') ||
                                           confirmText.includes('confirm') ||
                                           confirmText.includes('delete');

                    resolve({
                        hasCards: true,
                        hasDeleteButton: true,
                        hasConfirmModal: !!confirmModal,
                        hasConfirmText
                    });
                }, 300);
            });
        });

        if (!result.hasCards) {
            return { passed: null, skipped: true, message: 'No collections to test delete' };
        }

        if (!result.hasDeleteButton) {
            return { passed: null, skipped: true, message: 'No delete button found on collections' };
        }

        return {
            passed: result.hasConfirmModal || result.hasConfirmText,
            message: result.hasConfirmModal
                ? 'Delete confirmation modal appears'
                : (result.hasConfirmText ? 'Delete confirmation text shown' : 'No delete confirmation found')
        };
    }
};

// ============================================================================
// Subscription CRUD Tests
// ============================================================================
const SubscriptionCrudTests = {
    async createSubscriptionFormOpens(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/news/subscriptions`);

        // Find and click create button
        const clicked = await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn, .btn'));
            const createBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('create') || text.includes('new') || text.includes('add') || text.includes('subscribe');
            });

            if (createBtn) {
                createBtn.click();
                return true;
            }
            return false;
        });

        if (!clicked) {
            return { passed: null, skipped: true, message: 'No create subscription button found' };
        }

        await delay(500);

        const result = await page.evaluate(() => {
            const modal = document.querySelector('.modal, .dialog, [role="dialog"], .form-modal');
            const form = document.querySelector('form.subscription-form, form[action*="subscription"], .create-form');

            return {
                hasModal: !!modal && (modal.style.display !== 'none'),
                hasForm: !!form,
                hasQueryInput: !!document.querySelector('input[name*="query"], textarea[name*="query"], #subscription-query'),
                hasSubmitBtn: !!document.querySelector('button[type="submit"], .btn-primary, .save-btn')
            };
        });

        const passed = result.hasModal || result.hasForm || result.hasQueryInput;
        return {
            passed,
            message: passed
                ? `Create subscription form opens (modal=${result.hasModal}, queryInput=${result.hasQueryInput})`
                : 'Create subscription form did not open'
        };
    },

    async subscriptionFormValidation(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/news/subscriptions`);

        // Click create button
        await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn, .btn'));
            const createBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('create') || text.includes('new') || text.includes('add');
            });
            if (createBtn) createBtn.click();
        });

        await delay(500);

        // Try to submit empty form
        const result = await page.evaluate(() => {
            const submitBtn = document.querySelector('button[type="submit"], .btn-primary, .save-btn');
            if (submitBtn) submitBtn.click();

            return new Promise(resolve => {
                setTimeout(() => {
                    const hasValidationError = !!document.querySelector(
                        '.error, .invalid-feedback, .form-error, [class*="error"]'
                    );
                    const hasRequiredIndicator = !!document.querySelector(
                        'input:invalid, .required, [required]'
                    );
                    resolve({ hasValidationError, hasRequiredIndicator });
                }, 300);
            });
        });

        if (!result.hasValidationError && !result.hasRequiredIndicator) {
            return { passed: null, skipped: true, message: 'No form validation detected' };
        }

        return {
            passed: true,
            message: `Subscription form validation works`
        };
    },

    async subscriptionFrequencyOptions(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/news/subscriptions`);

        // Open create form first
        await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn, .btn'));
            const createBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('create') || text.includes('new') || text.includes('add');
            });
            if (createBtn) createBtn.click();
        });

        await delay(500);

        const result = await page.evaluate(() => {
            const frequencySelect = document.querySelector(
                'select[name*="frequency"], ' +
                '#frequency, ' +
                '.frequency-select'
            );

            if (!frequencySelect) return { exists: false };

            const options = Array.from(frequencySelect.options).map(o => o.text);
            return {
                exists: true,
                optionCount: options.length,
                options: options.slice(0, 6)
            };
        });

        if (!result.exists) {
            return { passed: null, skipped: true, message: 'No frequency dropdown found' };
        }

        return {
            passed: result.optionCount > 0,
            message: `Frequency options: ${result.options.join(', ')}`
        };
    },

    async subscriptionTypeOptions(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/news/subscriptions`);

        // Open create form first
        await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn, .btn'));
            const createBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('create') || text.includes('new') || text.includes('add');
            });
            if (createBtn) createBtn.click();
        });

        await delay(500);

        const result = await page.evaluate(() => {
            const typeSelect = document.querySelector(
                'select[name*="type"], ' +
                '#type, ' +
                '.type-select, ' +
                'select[name*="category"]'
            );

            if (!typeSelect) return { exists: false };

            const options = Array.from(typeSelect.options).map(o => o.text);
            return {
                exists: true,
                optionCount: options.length,
                options: options.slice(0, 6)
            };
        });

        if (!result.exists) {
            return { passed: null, skipped: true, message: 'No type dropdown found' };
        }

        return {
            passed: result.optionCount > 0,
            message: `Type options: ${result.options.join(', ')}`
        };
    },

    async subscriptionToggleStatus(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/news/subscriptions`);

        const result = await page.evaluate(() => {
            const cards = document.querySelectorAll('.subscription-card, .subscription-item, [data-subscription-id]');
            if (cards.length === 0) return { hasCards: false };

            const firstCard = cards[0];
            const toggleBtn = firstCard.querySelector(
                'button[class*="toggle"], ' +
                'button[class*="pause"], ' +
                'button[class*="resume"], ' +
                '.toggle-status, ' +
                'input[type="checkbox"]'
            );

            return {
                hasCards: true,
                cardCount: cards.length,
                hasToggle: !!toggleBtn,
                toggleType: toggleBtn?.tagName.toLowerCase()
            };
        });

        if (!result.hasCards) {
            return { passed: null, skipped: true, message: 'No subscriptions to test toggle' };
        }

        if (!result.hasToggle) {
            return { passed: null, skipped: true, message: 'No status toggle found on subscriptions' };
        }

        return {
            passed: true,
            message: `Status toggle found (type: ${result.toggleType})`
        };
    },

    async subscriptionDeleteConfirmation(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/news/subscriptions`);

        const result = await page.evaluate(() => {
            const cards = document.querySelectorAll('.subscription-card, .subscription-item, [data-subscription-id]');
            if (cards.length === 0) return { hasCards: false };

            const firstCard = cards[0];
            const deleteBtn = firstCard.querySelector(
                'button[class*="delete"], ' +
                'button[class*="remove"], ' +
                '.delete-btn, ' +
                '.btn-danger'
            );

            if (!deleteBtn) return { hasCards: true, hasDeleteButton: false };

            deleteBtn.click();

            return new Promise(resolve => {
                setTimeout(() => {
                    const confirmModal = document.querySelector('.modal, .confirm-dialog, [role="alertdialog"]');
                    resolve({
                        hasCards: true,
                        hasDeleteButton: true,
                        hasConfirmModal: !!confirmModal
                    });
                }, 300);
            });
        });

        if (!result.hasCards) {
            return { passed: null, skipped: true, message: 'No subscriptions to test delete' };
        }

        if (!result.hasDeleteButton) {
            return { passed: null, skipped: true, message: 'No delete button found' };
        }

        return {
            passed: result.hasConfirmModal,
            message: result.hasConfirmModal
                ? 'Delete confirmation modal appears'
                : 'No delete confirmation found'
        };
    }
};

// ============================================================================
// Document CRUD Tests
// ============================================================================
const DocumentCrudTests = {
    async documentUploadFormExists(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/library`);

        const result = await page.evaluate(() => {
            const uploadBtn = document.querySelector(
                'button[class*="upload"], ' +
                'a[href*="upload"], ' +
                '.upload-btn, ' +
                'input[type="file"]'
            );

            const uploadText = Array.from(document.querySelectorAll('button, a.btn')).find(b =>
                b.textContent?.toLowerCase().includes('upload')
            );

            return {
                hasUploadButton: !!uploadBtn || !!uploadText,
                hasFileInput: !!document.querySelector('input[type="file"]'),
                buttonText: (uploadBtn || uploadText)?.textContent?.trim()
            };
        });

        if (!result.hasUploadButton && !result.hasFileInput) {
            return { passed: null, skipped: true, message: 'No upload functionality found' };
        }

        return {
            passed: true,
            message: result.hasFileInput
                ? 'File upload input found'
                : `Upload button found: "${result.buttonText}"`
        };
    },

    async documentDeleteConfirmation(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/library`);

        const result = await page.evaluate(() => {
            const documents = document.querySelectorAll('.document-item, .library-item, tr[data-id], [data-document-id]');
            if (documents.length === 0) return { hasDocs: false };

            const firstDoc = documents[0];
            const deleteBtn = firstDoc.querySelector(
                'button[class*="delete"], ' +
                '.delete-btn, ' +
                '.btn-danger, ' +
                '.fa-trash'
            );

            if (!deleteBtn) return { hasDocs: true, hasDeleteButton: false };

            deleteBtn.click();

            return new Promise(resolve => {
                setTimeout(() => {
                    const confirmModal = document.querySelector('.modal, .confirm-dialog, [role="alertdialog"]');
                    resolve({
                        hasDocs: true,
                        hasDeleteButton: true,
                        hasConfirmModal: !!confirmModal
                    });
                }, 300);
            });
        });

        if (!result.hasDocs) {
            return { passed: null, skipped: true, message: 'No documents to test delete' };
        }

        if (!result.hasDeleteButton) {
            return { passed: null, skipped: true, message: 'No delete button found on documents' };
        }

        return {
            passed: result.hasConfirmModal,
            message: result.hasConfirmModal
                ? 'Document delete confirmation modal appears'
                : 'No delete confirmation found'
        };
    },

    async bulkDeleteSelection(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/library`);

        const result = await page.evaluate(() => {
            const checkboxes = document.querySelectorAll(
                'input[type="checkbox"][name*="select"], ' +
                '.bulk-select, ' +
                '.select-all, ' +
                'th input[type="checkbox"]'
            );

            const bulkDeleteBtn = document.querySelector(
                'button[class*="bulk-delete"], ' +
                '.bulk-actions button, ' +
                '.delete-selected'
            );

            return {
                hasCheckboxes: checkboxes.length > 0,
                checkboxCount: checkboxes.length,
                hasBulkDeleteBtn: !!bulkDeleteBtn
            };
        });

        if (!result.hasCheckboxes) {
            return { passed: null, skipped: true, message: 'No bulk selection checkboxes found' };
        }

        return {
            passed: true,
            message: `Bulk selection: ${result.checkboxCount} checkboxes, bulkDelete=${result.hasBulkDeleteBtn}`
        };
    }
};

// ============================================================================
// Research History CRUD Tests
// ============================================================================
const HistoryCrudTests = {
    async historyItemDelete(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/history`);

        const result = await page.evaluate(() => {
            const items = document.querySelectorAll('.history-item, .research-item, tr[data-id]');
            if (items.length === 0) return { hasItems: false };

            const firstItem = items[0];
            const deleteBtn = firstItem.querySelector(
                'button[class*="delete"], ' +
                '.delete-btn, ' +
                '.btn-danger'
            );

            return {
                hasItems: true,
                itemCount: items.length,
                hasDeleteButton: !!deleteBtn
            };
        });

        if (!result.hasItems) {
            return { passed: null, skipped: true, message: 'No history items to test delete' };
        }

        if (!result.hasDeleteButton) {
            return { passed: null, skipped: true, message: 'No delete button found on history items' };
        }

        return {
            passed: true,
            message: `Delete button found on ${result.itemCount} history items`
        };
    },

    async clearAllHistoryButton(page, baseUrl) {
        await navigateTo(page, `${baseUrl}/history`);

        const result = await page.evaluate(() => {
            const buttons = Array.from(document.querySelectorAll('button, a.btn'));
            const clearBtn = buttons.find(b => {
                const text = b.textContent?.toLowerCase() || '';
                return text.includes('clear') || text.includes('delete all') || text.includes('remove all');
            });

            return {
                hasClearButton: !!clearBtn,
                buttonText: clearBtn?.textContent?.trim()
            };
        });

        if (!result.hasClearButton) {
            return { passed: null, skipped: true, message: 'No clear all history button found' };
        }

        return {
            passed: true,
            message: `Clear history button found: "${result.buttonText}"`
        };
    }
};

// ============================================================================
// Main Test Runner
// ============================================================================
async function main() {
    log.section('CRUD Operations Tests');

    const ctx = await setupTest({ authenticate: true });
    const results = new TestResults('CRUD Operations Tests');
    const { page } = ctx;
    const { baseUrl } = ctx.config;

    const subTestTimeout = ctx.config.isCI ? 60000 : 30000;
    async function run(category, name, testFn) {
        try {
            const result = await withTimeout(
                testFn(page, baseUrl),
                subTestTimeout,
                `${category}/${name}`
            );
            if (result.skipped) {
                results.skip(category, name, result.message);
            } else {
                results.add(category, name, result.passed, result.message);
            }
        } catch (error) {
            results.add(category, name, false, `Error: ${error.message}`);
        }
    }

    try {
        // Collection CRUD Tests
        log.section('Collection CRUD');
        await run('Collections', 'Create Collection Form Opens', (p, u) => CollectionCrudTests.createCollectionFormOpens(p, u));
        await run('Collections', 'Create Collection Form Validation', (p, u) => CollectionCrudTests.createCollectionFormValidation(p, u));
        await run('Collections', 'Collection Edit Button', (p, u) => CollectionCrudTests.collectionEditButton(p, u));
        await run('Collections', 'Collection Delete Confirmation', (p, u) => CollectionCrudTests.collectionDeleteConfirmation(p, u));

        // Subscription CRUD Tests
        log.section('Subscription CRUD');
        await run('Subscriptions', 'Create Subscription Form Opens', (p, u) => SubscriptionCrudTests.createSubscriptionFormOpens(p, u));
        await run('Subscriptions', 'Subscription Form Validation', (p, u) => SubscriptionCrudTests.subscriptionFormValidation(p, u));
        await run('Subscriptions', 'Subscription Frequency Options', (p, u) => SubscriptionCrudTests.subscriptionFrequencyOptions(p, u));
        await run('Subscriptions', 'Subscription Type Options', (p, u) => SubscriptionCrudTests.subscriptionTypeOptions(p, u));
        await run('Subscriptions', 'Subscription Toggle Status', (p, u) => SubscriptionCrudTests.subscriptionToggleStatus(p, u));
        await run('Subscriptions', 'Subscription Delete Confirmation', (p, u) => SubscriptionCrudTests.subscriptionDeleteConfirmation(p, u));

        // Document CRUD Tests
        log.section('Document CRUD');
        await run('Documents', 'Document Upload Form Exists', (p, u) => DocumentCrudTests.documentUploadFormExists(p, u));
        await run('Documents', 'Document Delete Confirmation', (p, u) => DocumentCrudTests.documentDeleteConfirmation(p, u));
        await run('Documents', 'Bulk Delete Selection', (p, u) => DocumentCrudTests.bulkDeleteSelection(p, u));

        // History CRUD Tests
        log.section('History CRUD');
        await run('History', 'History Item Delete', (p, u) => HistoryCrudTests.historyItemDelete(p, u));
        await run('History', 'Clear All History Button', (p, u) => HistoryCrudTests.clearAllHistoryButton(p, u));

    } catch (error) {
        log.error(`Fatal error: ${error.message}`);
        console.error(error.stack);
    } finally {
        results.print();
        results.save();
        await teardownTest(ctx);
        process.exit(results.exitCode());
    }
}

// Run if executed directly
if (require.main === module) {
    main().catch(error => {
        console.error('Test runner failed:', error);
        process.exit(1);
    });
}

module.exports = { CollectionCrudTests, SubscriptionCrudTests, DocumentCrudTests, HistoryCrudTests };
