import { Page, expect } from '@playwright/test';
import { BasePage } from './BasePage';
import { Config } from '../utils/Config';

/**
 * AttendeeFilterPage
 * 
 * A focused page object for handling attendee filtering functionality
 * in the certificate reports page. This is designed as a minimal,
 * reusable component that can be easily incorporated into existing tests.
 */
export class AttendeeFilterPage extends BasePage {
    // Selectors for certificate filters
    private readonly pageTitle = 'h1:has-text("Certificate Reports")';
    private readonly filterForm = 'form.hvac-certificate-filters';
    private readonly eventFilterSelect = '#filter_event';
    private readonly attendeeSearchInput = '#search_attendee';
    private readonly revokedFilterSelect = '#filter_revoked';
    private readonly filterSubmitButton = 'button[type="submit"]';
    private readonly clearFiltersLink = 'a.hvac-clear-filters';
    private readonly certificateTable = '.hvac-certificate-table';
    private readonly certificateCount = '.hvac-total-count';
    private readonly noResultsMessage = '.hvac-no-certificates';
    private readonly pagination = '.hvac-pagination';
    
    // Selectors for certificate table columns
    private readonly eventColumn = 'td.certificate-event';
    private readonly attendeeColumn = 'td.certificate-attendee';
    private readonly emailColumn = 'td.certificate-email';
    private readonly statusColumn = 'td.certificate-status';
    
    constructor(page: Page) {
        super(page);
    }
    
    /**
     * Navigate to the certificate reports page
     */
    async navigate(): Promise<void> {
        await this.page.goto(Config.certificateReportsUrl);
        await this.page.waitForLoadState('networkidle');
    }
    
    /**
     * Check if the certificate reports page is visible
     */
    async isPageVisible(): Promise<boolean> {
        return this.page.locator(this.pageTitle).isVisible();
    }
    
    /**
     * Clear all existing filters
     */
    async clearFilters(): Promise<void> {
        const clearLink = this.page.locator(this.clearFiltersLink);
        if (await clearLink.isVisible()) {
            await clearLink.click();
            await this.page.waitForTimeout(Config.shortWait);
            await this.page.waitForSelector(this.certificateTable);
        }
    }
    
    /**
     * Filter certificates by event
     * @param eventId The event ID to filter by
     */
    async filterByEvent(eventId: string): Promise<void> {
        await this.clearFilters();
        await this.page.selectOption(this.eventFilterSelect, eventId);
        await this.page.click(this.filterSubmitButton);
        await this.page.waitForSelector(this.certificateTable);
    }
    
    /**
     * Filter certificates by attendee name or email
     * @param searchTerm The attendee name or email to search for
     */
    async filterByAttendee(searchTerm: string): Promise<void> {
        await this.clearFilters();
        await this.page.fill(this.attendeeSearchInput, searchTerm);
        await this.page.click(this.filterSubmitButton);
        await this.page.waitForSelector(this.certificateTable);
    }
    
    /**
     * Filter certificates by revocation status
     * @param revoked Whether to show revoked (true) or non-revoked (false) certificates
     */
    async filterByRevoked(revoked: boolean): Promise<void> {
        await this.clearFilters();
        await this.page.selectOption(this.revokedFilterSelect, revoked ? '1' : '0');
        await this.page.click(this.filterSubmitButton);
        await this.page.waitForSelector(this.certificateTable);
    }
    
    /**
     * Apply multiple filters at once
     * @param filters An object containing filter criteria
     */
    async applyFilters(filters: {
        eventId?: string;
        attendeeSearch?: string;
        revoked?: boolean;
    }): Promise<void> {
        await this.clearFilters();
        
        if (filters.eventId) {
            await this.page.selectOption(this.eventFilterSelect, filters.eventId);
        }
        
        if (filters.attendeeSearch) {
            await this.page.fill(this.attendeeSearchInput, filters.attendeeSearch);
        }
        
        if (filters.revoked !== undefined) {
            await this.page.selectOption(this.revokedFilterSelect, filters.revoked ? '1' : '0');
        }
        
        await this.page.click(this.filterSubmitButton);
        await this.page.waitForSelector(this.certificateTable);
    }
    
    /**
     * Get the total number of certificates matching the current filters
     */
    async getCertificateCount(): Promise<number> {
        // Check for no results message
        if (await this.page.locator(this.noResultsMessage).isVisible()) {
            return 0;
        }
        
        // Extract count from text like "Showing 1-20 of 54 certificates"
        const countText = await this.page.locator(this.certificateCount).textContent();
        const match = countText?.match(/of (\d+) certificates/);
        return match ? parseInt(match[1]) : 0;
    }
    
    /**
     * Check if any certificates match the current filters
     */
    async hasCertificates(): Promise<boolean> {
        return !(await this.page.locator(this.noResultsMessage).isVisible());
    }
    
    /**
     * Get all event names from the current certificate table
     */
    async getEventNames(): Promise<string[]> {
        return this.page.locator(this.eventColumn).allTextContents();
    }
    
    /**
     * Get all attendee names from the current certificate table
     */
    async getAttendeeNames(): Promise<string[]> {
        return this.page.locator(this.attendeeColumn).allTextContents();
    }
    
    /**
     * Get all email addresses from the current certificate table
     */
    async getEmails(): Promise<string[]> {
        return this.page.locator(this.emailColumn).allTextContents();
    }
    
    /**
     * Get all status values from the current certificate table
     */
    async getStatuses(): Promise<string[]> {
        return this.page.locator(this.statusColumn).allTextContents();
    }
    
    /**
     * Check if pagination is available
     */
    async hasPagination(): Promise<boolean> {
        return this.page.locator(this.pagination).isVisible();
    }
    
    /**
     * Navigate to the next page of results
     */
    async goToNextPage(): Promise<boolean> {
        const nextPageLink = this.page.locator(`${this.pagination} a.next`);
        if (await nextPageLink.isVisible()) {
            await nextPageLink.click();
            await this.page.waitForSelector(this.certificateTable);
            return true;
        }
        return false;
    }
    
    /**
     * Take a screenshot of the current filter results
     * @param name Name to include in the screenshot filename
     */
    async screenshotResults(name: string): Promise<void> {
        await this.page.screenshot({ 
            path: `certificate-filter-${name}.png`,
            fullPage: true
        });
    }
}