import { BaseEncoder } from '../base/base.encoder.js';
import type { TInvoice, TCreditNote, TDebitNote } from '../../interfaces/common.js';
import { CII_NAMESPACES, CIIProfile } from './cii.types.js';

/**
 * Base encoder for CII-based invoice formats
 */
export abstract class CIIBaseEncoder extends BaseEncoder {
  protected profile: CIIProfile = CIIProfile.EN16931;

  /**
   * Sets the CII profile to use for encoding
   * @param profile CII profile
   */
  public setProfile(profile: CIIProfile): void {
    this.profile = profile;
  }

  /**
   * Encodes a TInvoice object into CII XML
   * @param invoice TInvoice object to encode
   * @returns CII XML string
   */
  public async encode(invoice: TInvoice): Promise<string> {
    // Determine if it's a credit note or debit note
    if (invoice.invoiceType === 'creditnote') {
      return this.encodeCreditNote(invoice as TCreditNote);
    } else {
      return this.encodeDebitNote(invoice as TDebitNote);
    }
  }

  /**
   * Encodes a TCreditNote object into CII XML
   * @param creditNote TCreditNote object to encode
   * @returns CII XML string
   */
  protected abstract encodeCreditNote(creditNote: TCreditNote): Promise<string>;

  /**
   * Encodes a TDebitNote object into CII XML
   * @param debitNote TDebitNote object to encode
   * @returns CII XML string
   */
  protected abstract encodeDebitNote(debitNote: TDebitNote): Promise<string>;

  /**
   * Creates the XML declaration and root element
   * @returns XML string with declaration and root element
   */
  protected createXmlRoot(): string {
    return `<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice xmlns:rsm="${CII_NAMESPACES.RSM}"
  xmlns:ram="${CII_NAMESPACES.RAM}"
  xmlns:udt="${CII_NAMESPACES.UDT}">
</rsm:CrossIndustryInvoice>`;
  }

  /**
   * Formats a date as an ISO string (YYYY-MM-DD)
   * @param timestamp Timestamp to format
   * @returns Formatted date string
   */
  protected formatDate(timestamp: number): string {
    const date = new Date(timestamp);
    return date.toISOString().split('T')[0];
  }
}
