import * as plugins from '../plugins.js';
import * as xmldom from 'xmldom';
import { BaseDecoder } from './base.decoder.js';

/**
 * A decoder for Factur-X/ZUGFeRD XML format (based on UN/CEFACT CII).
 * Converts XML into structured ILetter with invoice data.
 */
export class FacturXDecoder extends BaseDecoder {
  private xmlDoc: Document | null = null;

  constructor(xmlString: string) {
    super(xmlString);
    
    // Parse XML to DOM for easier element extraction
    try {
      const parser = new xmldom.DOMParser();
      this.xmlDoc = parser.parseFromString(this.xmlString, 'text/xml');
    } catch (error) {
      console.error('Error parsing Factur-X XML:', error);
    }
  }

  /**
   * Extracts text from the first element matching the tag name
   */
  private getElementText(tagName: string): string {
    if (!this.xmlDoc) {
      return '';
    }
    
    try {
      // Basic handling for namespaced tags
      let namespace = '';
      let localName = tagName;
      
      if (tagName.includes(':')) {
        const parts = tagName.split(':');
        namespace = parts[0];
        localName = parts[1];
      }
      
      // Find all elements with this name
      const elements = this.xmlDoc.getElementsByTagName(tagName);
      if (elements.length > 0) {
        return elements[0].textContent || '';
      }
      
      // Try with just the local name if we didn't find it with the namespace
      if (namespace) {
        const elements = this.xmlDoc.getElementsByTagName(localName);
        if (elements.length > 0) {
          return elements[0].textContent || '';
        }
      }
      
      return '';
    } catch (error) {
      console.error(`Error extracting element ${tagName}:`, error);
      return '';
    }
  }

  /**
   * Converts Factur-X/ZUGFeRD XML to a structured letter object
   */
  public async getLetterData(): Promise<plugins.tsclass.business.ILetter> {
    try {
      // Extract invoice ID
      let invoiceId = this.getElementText('ram:ID');
      if (!invoiceId) {
        // Try alternative locations
        invoiceId = this.getElementText('rsm:ExchangedDocument ram:ID') || 'Unknown';
      }
      
      // Extract seller name
      let sellerName = this.getElementText('ram:Name');
      if (!sellerName) {
        sellerName = this.getElementText('ram:SellerTradeParty ram:Name') || 'Unknown Seller';
      }
      
      // Extract buyer name
      let buyerName = '';
      // Try to find BuyerTradeParty Name specifically
      if (this.xmlDoc) {
        const buyerParties = this.xmlDoc.getElementsByTagName('ram:BuyerTradeParty');
        if (buyerParties.length > 0) {
          const nameElements = buyerParties[0].getElementsByTagName('ram:Name');
          if (nameElements.length > 0) {
            buyerName = nameElements[0].textContent || '';
          }
        }
      }
      
      if (!buyerName) {
        buyerName = 'Unknown Buyer';
      }
      
      // Create seller
      const seller: plugins.tsclass.business.IContact = {
        name: sellerName,
        type: 'company',
        description: sellerName,
        address: {
          streetName: this.getElementText('ram:LineOne') || 'Unknown',
          houseNumber: '0',  // Required by IAddress interface
          city: this.getElementText('ram:CityName') || 'Unknown',
          country: this.getElementText('ram:CountryID') || 'Unknown',
          postalCode: this.getElementText('ram:PostcodeCode') || 'Unknown',
        },
      };
      
      // Create buyer
      const buyer: plugins.tsclass.business.IContact = {
        name: buyerName,
        type: 'company',
        description: buyerName,
        address: {
          streetName: 'Unknown',
          houseNumber: '0',
          city: 'Unknown',
          country: 'Unknown',
          postalCode: 'Unknown',
        },
      };
      
      // Extract invoice type
      let invoiceType = 'debitnote';
      const typeCode = this.getElementText('ram:TypeCode');
      if (typeCode === '381') {
        invoiceType = 'creditnote';
      }
      
      // Create invoice data
      const invoiceData: plugins.tsclass.finance.IInvoice = {
        id: invoiceId,
        status: null,
        type: invoiceType as 'debitnote' | 'creditnote',
        billedBy: seller,
        billedTo: buyer,
        deliveryDate: Date.now(),
        dueInDays: 30,
        periodOfPerformance: null,
        printResult: null,
        currency: (this.getElementText('ram:InvoiceCurrencyCode') || 'EUR') as plugins.tsclass.finance.TCurrency,
        notes: [],
        items: [
          {
            name: 'Item from Factur-X XML',
            unitQuantity: 1,
            unitNetPrice: 0,
            vatPercentage: 0,
            position: 0,
            unitType: 'units',
          }
        ],
        reverseCharge: false,
      };
      
      // Return a letter
      return {
        versionInfo: {
          type: 'draft',
          version: '1.0.0',
        },
        type: 'invoice',
        date: Date.now(),
        subject: `Invoice: ${invoiceId}`,
        from: seller,
        to: buyer,
        content: {
          invoiceData: invoiceData,
          textData: null,
          timesheetData: null,
          contractData: null,
        },
        needsCoverSheet: false,
        objectActions: [],
        pdf: null,
        incidenceId: null,
        language: null,
        legalContact: null,
        logoUrl: null,
        pdfAttachments: null,
        accentColor: null,
      };
    } catch (error) {
      console.error('Error converting Factur-X XML to letter data:', error);
      return this.createDefaultLetter();
    }
  }
}