import type { DisruptionData } from '../types/index.js';
import { HttpClient } from './http-client.js';

/**
 * Client for interacting with the BODS Disruptions API
 * 
 * The Disruptions API provides information about current and planned 
 * disruptions to bus services in SIRI-SX format (XML).
 * Data is updated as new information becomes available.
 */
export class DisruptionsClient {
  constructor(private httpClient: HttpClient) {}

  /**
   * Get all current service disruptions in SIRI-SX format
   * 
   * @returns Promise resolving to SIRI-SX XML data containing all disruptions
   * 
   * @example
   * ```typescript
   * // Get all current disruptions
   * const disruptions = await client.disruptions.getAll();
   * console.log('Disruptions XML:', disruptions.xmlData);
   * 
   * // You would typically parse the XML to extract specific disruption details
   * const parser = new DOMParser();
   * const doc = parser.parseFromString(disruptions.xmlData, 'text/xml');
   * ```
   */
  async getAll(): Promise<DisruptionData> {
    const response = await this.httpClient.get<string>('/api/v1/siri-sx');
    return { xmlData: response.data };
  }

  /**
   * Get current service disruptions (alias for getAll)
   * 
   * @returns Promise resolving to SIRI-SX XML data containing current disruptions
   * 
   * @example
   * ```typescript
   * const currentDisruptions = await client.disruptions.getCurrent();
   * ```
   */
  async getCurrent(): Promise<DisruptionData> {
    return this.getAll();
  }

  /**
   * Helper method to parse SIRI-SX XML and extract basic disruption information
   * Note: This is a basic parser. For production use, consider a more robust XML parsing solution.
   * Requires a DOM environment (browser) or a polyfill like jsdom in Node.js.
   * 
   * @param xmlData - Raw SIRI-SX XML data
   * @returns Array of parsed disruption objects
   * 
   * @example
   * ```typescript
   * const disruptions = await client.disruptions.getAll();
   * const parsed = client.disruptions.parseDisruptions(disruptions.xmlData);
   * 
   * parsed.forEach(disruption => {
   *   console.log(`${disruption.summary}: ${disruption.description}`);
   * });
   * ```
   */
  parseDisruptions(xmlData: string): Array<{
    situationNumber?: string;
    participantRef?: string;
    summary?: string;
    description?: string;
    severity?: string;
    startTime?: string;
    endTime?: string;
    planned?: boolean;
  }> {
    try {
      // Check if DOMParser is available (browser environment)
      if (typeof DOMParser === 'undefined') {
        console.warn('DOMParser not available. XML parsing requires a DOM environment or polyfill.');
        return [];
      }
      
      const parser = new DOMParser();
      const doc = parser.parseFromString(xmlData, 'text/xml');
      
      const situations = doc.querySelectorAll('PtSituationElement');
      const results: Array<{
        situationNumber?: string;
        participantRef?: string;
        summary?: string;
        description?: string;
        severity?: string;
        startTime?: string;
        endTime?: string;
        planned?: boolean;
      }> = [];
      
      situations.forEach((situation: Element) => {
        const situationNumber = situation.querySelector('SituationNumber')?.textContent || undefined;
        const participantRef = situation.querySelector('ParticipantRef')?.textContent || undefined;
        const summary = situation.querySelector('Summary')?.textContent || undefined;
        const description = situation.querySelector('Description')?.textContent || undefined;
        const severity = situation.querySelector('Severity')?.textContent || undefined;
        const startTime = situation.querySelector('ValidityPeriod StartTime')?.textContent || undefined;
        const endTime = situation.querySelector('ValidityPeriod EndTime')?.textContent || undefined;
        const plannedText = situation.querySelector('Planned')?.textContent;
        const planned = plannedText ? plannedText.toLowerCase() === 'true' : undefined;
        
        results.push({
          situationNumber,
          participantRef,
          summary,
          description,
          severity,
          startTime,
          endTime,
          planned
        });
      });
      
      return results;
    } catch (error) {
      console.warn('Failed to parse SIRI-SX XML:', error);
      return [];
    }
  }

  /**
   * Get and parse current disruptions in one call
   * 
   * @returns Promise resolving to array of parsed disruption objects
   * 
   * @example
   * ```typescript
   * const disruptions = await client.disruptions.getCurrentParsed();
   * 
   * disruptions.forEach(disruption => {
   *   if (disruption.planned) {
   *     console.log(`Planned disruption: ${disruption.summary}`);
   *   } else {
   *     console.log(`Unplanned disruption: ${disruption.summary}`);
   *   }
   * });
   * ```
   */
  async getCurrentParsed(): Promise<Array<{
    situationNumber?: string;
    participantRef?: string;
    summary?: string;
    description?: string;
    severity?: string;
    startTime?: string;
    endTime?: string;
    planned?: boolean;
  }>> {
    const disruptions = await this.getAll();
    return this.parseDisruptions(disruptions.xmlData);
  }

  /**
   * Filter parsed disruptions by criteria
   * 
   * @param disruptions - Array of parsed disruptions
   * @param filters - Filter criteria
   * @returns Filtered array of disruptions
   * 
   * @example
   * ```typescript
   * const allDisruptions = await client.disruptions.getCurrentParsed();
   * 
   * // Get only unplanned disruptions
   * const unplanned = client.disruptions.filterDisruptions(allDisruptions, {
   *   planned: false
   * });
   * 
   * // Get disruptions from specific participant
   * const tfgmDisruptions = client.disruptions.filterDisruptions(allDisruptions, {
   *   participantRef: 'TfGM'
   * });
   * ```
   */
  filterDisruptions(
    disruptions: Array<{
      situationNumber?: string;
      participantRef?: string;
      summary?: string;
      description?: string;
      severity?: string;
      startTime?: string;
      endTime?: string;
      planned?: boolean;
    }>,
    filters: {
      planned?: boolean;
      participantRef?: string;
      severity?: string;
    }
  ): Array<{
    situationNumber?: string;
    participantRef?: string;
    summary?: string;
    description?: string;
    severity?: string;
    startTime?: string;
    endTime?: string;
    planned?: boolean;
  }> {
    return disruptions.filter(disruption => {
      if (filters.planned !== undefined && disruption.planned !== filters.planned) {
        return false;
      }
      if (filters.participantRef && disruption.participantRef !== filters.participantRef) {
        return false;
      }
      if (filters.severity && disruption.severity !== filters.severity) {
        return false;
      }
      return true;
    });
  }
}
