import { Page } from '@playwright/test';
import { BasePage } from './BasePage';

export class DashboardPage extends BasePage {
    private readonly createEventButton = 'a:has-text("Create Event")';
    private readonly viewProfileButton = 'a:has-text("View Profile")';
    private readonly logoutButton = 'a:has-text("Logout")';
    private readonly generateCertificatesButton = 'a:has-text("Generate Certificates")';
    private readonly certificateReportsButton = 'a:has-text("Certificate Reports")';
    private readonly eventsTable = 'table';
    
    // Updated Stats row layout selectors
    private readonly statsSection = '.hvac-stats-row';
    private readonly statsColumns = '.hvac-stat-col';
    private readonly totalEventsCard = '.hvac-stat-card:has-text("Total Events")';
    private readonly upcomingEventsCard = '.hvac-stat-card:has-text("Upcoming Events")';
    private readonly pastEventsCard = '.hvac-stat-card:has-text("Past Events")';
    private readonly totalRevenueCard = '.hvac-stat-card:has-text("Total Revenue")';
    
    // Event filters selectors
    private readonly filterButtons = '.hvac-event-filters a';
    private readonly allFilterButton = '.hvac-event-filters a:has-text("All")';
    private readonly publishFilterButton = '.hvac-event-filters a:has-text("Publish")';
    private readonly draftFilterButton = '.hvac-event-filters a:has-text("Draft")';
    private readonly pendingFilterButton = '.hvac-event-filters a:has-text("Pending")';
    private readonly privateFilterButton = '.hvac-event-filters a:has-text("Private")';
    private readonly activeFilterClass = 'hvac-filter-active';
    private readonly loadingIndicator = '.hvac-loading';

    constructor(page: Page) {
        super(page);
    }

    async navigate(): Promise<void> {
        const STAGING_URL = 'https://wordpress-974670-5399585.cloudwaysapps.com';
        await this.page.goto(`${STAGING_URL}/hvac-dashboard/`);
        await this.page.waitForLoadState('networkidle');
    }

    async navigateToDashboard(): Promise<void> {
        await this.navigate('/hvac-dashboard/');
    }

    async clickCreateEvent(): Promise<void> {
        await this.click(this.createEventButton);
        await this.waitForNavigation();
    }

    async clickViewProfile(): Promise<void> {
        await this.click(this.viewProfileButton);
        await this.waitForNavigation();
    }

    async clickGenerateCertificates(): Promise<void> {
        await this.page.click(this.generateCertificatesButton);
        await this.page.waitForLoadState('networkidle');
    }

    async clickCertificateReports(): Promise<void> {
        await this.page.click(this.certificateReportsButton);
        await this.page.waitForLoadState('networkidle');
    }

    async logout(): Promise<void> {
        await this.click(this.logoutButton);
        await this.waitForNavigation();
    }

    async getStatistics(): Promise<{
        totalEvents: string;
        upcomingEvents: string;
        pastEvents: string;
        revenue: string;
    }> {
        return {
            totalEvents: await this.page.locator(this.totalEventsCard).locator('p').textContent() || '0',
            upcomingEvents: await this.page.locator(this.upcomingEventsCard).locator('p').textContent() || '0',
            pastEvents: await this.page.locator(this.pastEventsCard).locator('p').textContent() || '0',
            revenue: await this.page.locator(this.totalRevenueCard).locator('p').textContent() || '$0.00'
        };
    }
    
    /**
     * Get the number of stat columns in the row layout
     */
    async getStatsColumnCount(): Promise<number> {
        return await this.page.locator(this.statsColumns).count();
    }
    
    /**
     * Check if the stats are displayed in a row layout
     */
    async areStatsInRowLayout(): Promise<boolean> {
        // First check if the row container exists
        const statsRow = await this.isVisible(this.statsSection);
        if (!statsRow) return false;
        
        // Get columns
        const columns = await this.page.locator(this.statsColumns);
        const count = await columns.count();
        
        // Need at least 2 columns to verify row layout
        if (count < 2) return false;
        
        // Get bounding boxes to verify horizontal layout
        const box1 = await columns.nth(0).boundingBox();
        const box2 = await columns.nth(1).boundingBox();
        
        if (!box1 || !box2) return false;
        
        // In a row layout, the second column should be to the right of the first
        // (This may not be true on very narrow screens where they would wrap)
        return box2.x > box1.x;
    }

    async isEventsTableVisible(): Promise<boolean> {
        return await this.isVisible(this.eventsTable);
    }
    
    /**
     * Get the count of filter buttons
     */
    async getFilterButtonCount(): Promise<number> {
        return await this.page.locator(this.filterButtons).count();
    }
    
    /**
     * Get the currently active filter
     */
    async getActiveFilter(): Promise<string> {
        const activeFilter = await this.page.locator(`${this.filterButtons}.${this.activeFilterClass}`);
        if (await activeFilter.count() === 0) {
            return 'All'; // Default filter is All
        }
        return (await activeFilter.textContent() || '').trim();
    }
    
    /**
     * Filter events by status
     * @param status The filter status: 'All', 'Publish', 'Draft', 'Pending', or 'Private'
     */
    async filterEvents(status: 'All' | 'Publish' | 'Draft' | 'Pending' | 'Private'): Promise<void> {
        this.verbosity.log(`Filtering events by status: ${status}`);
        
        // Get the appropriate selector based on status
        let selector: string;
        switch (status) {
            case 'All':
                selector = this.allFilterButton;
                break;
            case 'Publish':
                selector = this.publishFilterButton;
                break;
            case 'Draft':
                selector = this.draftFilterButton;
                break;
            case 'Pending':
                selector = this.pendingFilterButton;
                break;
            case 'Private':
                selector = this.privateFilterButton;
                break;
            default:
                throw new Error(`Invalid filter status: ${status}`);
        }
        
        // Click the filter button
        await this.click(selector);
        
        // Wait for the loading indicator to disappear if it appears
        const loadingElement = this.page.locator(this.loadingIndicator);
        if (await loadingElement.isVisible()) {
            await loadingElement.waitFor({ state: 'hidden', timeout: 5000 });
        }
        
        // Wait a moment for the AJAX content to update
        await this.page.waitForTimeout(500);
    }
    
    /**
     * Check if filter status appears in URL
     */
    async doesUrlContainFilterStatus(status: string): Promise<boolean> {
        const url = await this.getUrl();
        
        // 'All' filter should not have event_status in URL
        if (status.toLowerCase() === 'all') {
            return !url.includes('event_status=');
        }
        
        // Other filters should have event_status=status in URL
        return url.includes(`event_status=${status.toLowerCase()}`);
    }
    
    /**
     * Check if table has been filtered by the given status
     * If status is 'All', it checks if the table exists and has any events
     * Otherwise it verifies that all visible events have the expected status
     */
    async isTableFilteredByStatus(status: 'All' | 'Publish' | 'Draft' | 'Pending' | 'Private'): Promise<boolean> {
        // First check if the table exists
        if (!await this.isEventsTableVisible()) {
            return false;
        }
        
        // If status is 'All', just check that the table exists
        if (status === 'All') {
            return true;
        }
        
        // Get all event rows
        const rows = await this.page.locator(`${this.eventsTable} tbody tr`);
        const count = await rows.count();
        
        // If no events, can't verify status
        if (count === 0) {
            return false;
        }
        
        // Check for "No events found" message
        if (count === 1) {
            const firstRowText = await rows.first().textContent() || '';
            if (firstRowText.includes('No events found')) {
                // This is acceptable if we've filtered to a status with no events
                return true;
            }
        }
        
        // For each row, check if the status column matches the expected status
        for (let i = 0; i < count; i++) {
            const rowData = await this.getEventRowData(i);
            
            // If the status doesn't match, the filter isn't working correctly
            if (rowData.status.toLowerCase() !== status.toLowerCase()) {
                return false;
            }
        }
        
        // All rows have the expected status
        return true;
    }

    async getEventRowData(index: number): Promise<{
        status: string;
        name: string;
        date: string;
        organizer: string;
        capacity: string;
        soldTickets: string;
        revenue: string;
    }> {
        const row = await this.page.locator(`${this.eventsTable} tbody tr`).nth(index);
        
        // Check if this is a "No events found" row
        const cellCount = await row.locator('td').count();
        if (cellCount === 1) {
            const text = await row.locator('td').textContent();
            if (text?.includes('No events found')) {
                return {
                    status: '',
                    name: text,
                    date: '',
                    organizer: '',
                    capacity: '',
                    soldTickets: '',
                    revenue: ''
                };
            }
        }
        
        return {
            status: await row.locator('td:nth-child(1)').textContent() || '',
            name: await row.locator('td:nth-child(2)').textContent() || '',
            date: await row.locator('td:nth-child(3)').textContent() || '',
            organizer: await row.locator('td:nth-child(4)').textContent() || '',
            capacity: await row.locator('td:nth-child(5)').textContent() || '',
            soldTickets: await row.locator('td:nth-child(6)').textContent() || '',
            revenue: await row.locator('td:nth-child(7)').textContent() || ''
        };
    }

    async getEventCount(): Promise<number> {
        const rows = await this.page.locator(`${this.eventsTable} tbody tr`).count();
        // Check if the only row is "No events found"
        if (rows === 1) {
            const firstRow = await this.page.locator(`${this.eventsTable} tbody tr`).first();
            const cellCount = await firstRow.locator('td').count();
            if (cellCount === 1) {
                const text = await firstRow.locator('td').textContent();
                if (text?.includes('No events found')) {
                    return 0;
                }
            }
        }
        return rows;
    }

    async clickEventName(eventName: string): Promise<void> {
        await this.page.click(`${this.eventsTable} a:has-text("${eventName}")`);
        await this.waitForNavigation();
    }
}