interface LexOfficeContact {
  id?: string;
  organizationId: string;
  version: number;
  roles: {
    customer?: {
      number?: number;
    };
  };
  company?: {
    name: string;
    taxNumber?: string;
    vatRegistrationId?: string;
    allowTaxFreeInvoices?: boolean;
    contactPersons?: Array<{
      salutation?: string;
      firstName?: string;
      lastName?: string;
      primary?: boolean;
      emailAddress?: string;
      phoneNumber?: string;
    }>;
  };
  person?: {
    salutation?: string;
    firstName?: string;
    lastName?: string;
  };
  addresses?: {
    billing?: Array<{
      supplement?: string;
      street?: string;
      zip?: string;
      city?: string;
      countryCode?: string;
    }>;
  };
  emailAddresses?: {
    business?: Array<string>;
    office?: Array<string>;
    private?: Array<string>;
    other?: Array<string>;
  };
  phoneNumbers?: {
    business?: Array<string>;
    office?: Array<string>;
    mobile?: Array<string>;
    private?: Array<string>;
    fax?: Array<string>;
    other?: Array<string>;
  };
  note?: string;
}

interface LexOfficeQuotation {
  id?: string;
  organizationId?: string;
  createdDate?: string;
  updatedDate?: string;
  voucherNumber?: string;
  voucherDate: string;
  address: {
    contactId?: string;
    name?: string;
    supplement?: string;
    street?: string;
    city?: string;
    zip?: string;
    countryCode: string;
  };
  lineItems: Array<{
    type: 'custom' | 'text';
    name?: string;
    description?: string;
    quantity?: number;
    unitName?: string;
    unitPrice?: {
      currency: string;
      netAmount: number;
      taxRatePercentage: number;
    };
  }>;
  totalPrice?: {
    currency: string;
  };
  taxConditions?: {
    taxType: 'net' | 'gross' | 'vatfree';
  };
  title?: string;
  introduction?: string;
  remark?: string;
}

interface LexOfficeInvoice extends Omit<LexOfficeQuotation, 'id'> {
  voucherStatus?: string;
  shippingConditions?: {
    shippingDate?: string;
    shippingType?: string;
  };
  paymentConditions?: {
    paymentTermLabel?: string;
    paymentTermDuration?: number;
  };
}

export class LexOfficeService {
  private apiKey: string;
  private baseUrl = 'https://api.lexoffice.io/v1';

  constructor() {
    this.apiKey = process.env.LEXOFFICE_API_KEY || '';
    if (!this.apiKey) {
      console.warn('LexOffice API Key nicht konfiguriert');
    }
  }

  private async request(method: string, endpoint: string, data?: any) {
    try {
      const response = await fetch(`${this.baseUrl}${endpoint}`, {
        method,
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: data ? JSON.stringify(data) : undefined,
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`LexOffice API Error: ${response.status} - ${errorText}`);
      }

      return await response.json();
    } catch (error) {
      console.error('LexOffice API Request failed:', error);
      throw error;
    }
  }

  async createContact(contact: Partial<LexOfficeContact>): Promise<{ id: string; resourceUri: string }> {
    return this.request('POST', '/contacts', contact);
  }

  async getContact(contactId: string): Promise<LexOfficeContact> {
    return this.request('GET', `/contacts/${contactId}`);
  }

  async createQuotation(quotation: LexOfficeQuotation, finalize: boolean = false): Promise<{ id: string; resourceUri: string; createdDate: string; updatedDate: string; voucherNumber: string }> {
    const url = finalize ? '/quotations?finalize=true' : '/quotations';
    console.log(`📍 Creating quotation with URL: ${this.baseUrl}${url}, finalize=${finalize}`);
    return this.request('POST', url, quotation);
  }

  async getQuotation(quotationId: string): Promise<LexOfficeQuotation> {
    return this.request('GET', `/quotations/${quotationId}`);
  }

  async finalizeQuotation(quotationId: string): Promise<{ id: string; resourceUri: string }> {
    return this.request('PUT', `/quotations/${quotationId}/pursue`, {
      precedingSalesVoucherId: null,
    });
  }

  async createInvoice(invoice: LexOfficeInvoice): Promise<{ id: string; resourceUri: string; createdDate: string; updatedDate: string; voucherNumber: string }> {
    return this.request('POST', '/invoices', invoice);
  }

  async getInvoice(invoiceId: string): Promise<LexOfficeInvoice> {
    return this.request('GET', `/invoices/${invoiceId}`);
  }

  async finalizeInvoice(invoiceId: string): Promise<{ id: string; resourceUri: string }> {
    return this.request('PUT', `/invoices/${invoiceId}/pursue`, {
      precedingSalesVoucherId: null,
      preserveVoucherNumber: false,
    });
  }

  async getQuotationPDF(quotationId: string): Promise<Buffer> {
    try {
      const response = await fetch(`${this.baseUrl}/quotations/${quotationId}/document`, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Accept': 'application/pdf',
        },
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`LexOffice PDF Error: ${response.status} - ${errorText}`);
      }

      const arrayBuffer = await response.arrayBuffer();
      return Buffer.from(arrayBuffer);
    } catch (error) {
      console.error('LexOffice PDF download failed:', error);
      throw error;
    }
  }

  async getInvoicePDF(invoiceId: string): Promise<Buffer> {
    try {
      const response = await fetch(`${this.baseUrl}/invoices/${invoiceId}/document`, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Accept': 'application/pdf',
        },
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`LexOffice PDF Error: ${response.status} - ${errorText}`);
      }

      const arrayBuffer = await response.arrayBuffer();
      return Buffer.from(arrayBuffer);
    } catch (error) {
      console.error('LexOffice PDF download failed:', error);
      throw error;
    }
  }

  async createContactFromBooking(booking: any): Promise<string> {
    const contact: Partial<LexOfficeContact> = {
      roles: {
        customer: {},
      },
      addresses: {
        billing: [{
          street: booking.customerAddress,
          zip: booking.customerZip,
          city: booking.customerCity,
          countryCode: 'DE',
        }],
      },
      emailAddresses: {
        business: [booking.customerEmail],
      },
      phoneNumbers: {
        business: [booking.customerPhone],
      },
    };

    if (booking.invoiceType === 'BUSINESS' && booking.companyName) {
      const nameParts = booking.customerName.trim().split(' ');
      const firstName = nameParts[0] || '';
      const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : nameParts[0] || 'Ansprechpartner';
      contact.company = {
        name: booking.companyName,
        contactPersons: [{
          firstName: firstName,
          lastName: lastName,
          primary: true,
          emailAddress: booking.customerEmail,
          phoneNumber: booking.customerPhone,
        }],
      };
    } else {
      const nameParts = booking.customerName.trim().split(' ');
      const firstName = nameParts[0] || '';
      const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : nameParts[0] || 'Unbekannt';
      contact.person = {
        firstName: firstName,
        lastName: lastName,
      };
    }

    const result = await this.createContact(contact);
    return result.id;
  }

  async createQuotationFromBooking(booking: any, contactId: string): Promise<string> {
    const lineItems: Array<any> = [];

    console.log('📊 Booking Data:', {
      id: booking.id,
      bookingNumber: booking.bookingNumber,
      hasPhotobox: !!booking.photobox,
      photoboxModel: booking.photobox?.model,
      locationId: booking.locationId,
      withPrintFlat: booking.withPrintFlat,
    });

    // WICHTIG: priceConfig separat laden, da keine direkte Relation existiert
    let priceConfig = booking.priceConfig;
    
    if (!priceConfig && booking.photobox?.model && booking.locationId) {
      console.log('🔍 Lade PriceConfig nach...');
      const { prisma } = await import('./prisma');
      priceConfig = await prisma.priceConfig.findUnique({
        where: {
          locationId_model: {
            locationId: booking.locationId,
            model: booking.photobox.model,
          },
        },
      });
      console.log('📊 PriceConfig geladen:', priceConfig);
    }

    if (!priceConfig) {
      throw new Error('Keine Preiskonfiguration gefunden. Bitte konfiguriere zuerst die Preise für dieses Fotobox-Modell.');
    }

    // 1. Fotobox als Hauptposition (IMMER als custom lineItem)
    const withPrintFlat = booking.withPrintFlat !== false; // Default: true
    const boxName = booking.photobox?.model || 'Fotobox';
    const flatSuffix = withPrintFlat ? ' mit Druckflatrate' : ' (nur digital)';

    const photoboxItem: any = {
      type: 'custom',
      name: `${boxName}${flatSuffix}`,
      description: `Event am ${new Date(booking.eventDate).toLocaleDateString('de-DE')} in ${booking.eventCity}`,
      quantity: 1,
      unitName: 'Stück',
      unitPrice: {
        currency: 'EUR',
        netAmount: priceConfig?.basePrice || 1,
        taxRatePercentage: 19,
      },
    };

    lineItems.push(photoboxItem);

    console.log('📦 Photobox LineItem (custom):', photoboxItem);

    // 2. Kilometerpauschale (falls Distanz vorhanden)
    if (booking.distance && booking.distance > 0) {
      // 2a. Kilometer-Pauschale (bis X km) - IMMER als custom lineItem
      if (priceConfig?.kmFlatRate && priceConfig.kmFlatRate > 0) {
        const kmFlatItem: any = {
          type: 'custom',
          name: `Kilometerpauschale (bis ${priceConfig.kmFlatRateUpTo}km)`,
          description: `Entfernung: ${booking.distance.toFixed(1)}km`,
          quantity: 1,
          unitName: 'Pauschale',
          unitPrice: {
            currency: 'EUR',
            netAmount: priceConfig.kmFlatRate / 1.19,
            taxRatePercentage: 19,
          },
        };

        lineItems.push(kmFlatItem);
      }

      // 2b. Zusätzliche Kilometer (wenn über Flatrate) - IMMER als custom lineItem
      if (priceConfig && booking.distance > priceConfig.kmFlatRateUpTo) {
        const extraKm = booking.distance - priceConfig.kmFlatRateUpTo;
        const totalExtraKm = extraKm * priceConfig.kmMultiplier;

        const kmExtraItem: any = {
          type: 'custom',
          name: `Zusatzkilometer`,
          description: `${extraKm.toFixed(1)}km × ${priceConfig.kmMultiplier} Strecken = ${totalExtraKm.toFixed(1)}km`,
          quantity: totalExtraKm,
          unitName: 'km',
          unitPrice: {
            currency: 'EUR',
            netAmount: priceConfig.pricePerKm,
            taxRatePercentage: 19,
          },
        };

        lineItems.push(kmExtraItem);
      }
    }

    // 3. Equipment/Extras (wenn vorhanden) - IMMER als custom lineItem
    if (booking.bookingEquipment && booking.bookingEquipment.length > 0) {
      for (const eq of booking.bookingEquipment) {
        const equipmentItem: any = {
          type: 'custom',
          name: eq.equipment.name,
          quantity: eq.quantity || 1,
          unitName: 'Stück',
          unitPrice: {
            currency: 'EUR',
            netAmount: eq.equipment.price || 1,
            taxRatePercentage: 19,
          },
        };

        lineItems.push(equipmentItem);
      }
    }

    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    
    const isDST = (date: Date) => {
      const jan = new Date(date.getFullYear(), 0, 1).getTimezoneOffset();
      const jul = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
      return Math.max(jan, jul) !== date.getTimezoneOffset();
    };
    
    const timezone = isDST(now) ? '+02:00' : '+01:00';
    const voucherDate = `${year}-${month}-${day}T00:00:00.000${timezone}`;

    const expirationDateObj = new Date(now);
    expirationDateObj.setDate(expirationDateObj.getDate() + 14);
    const expYear = expirationDateObj.getFullYear();
    const expMonth = String(expirationDateObj.getMonth() + 1).padStart(2, '0');
    const expDay = String(expirationDateObj.getDate()).padStart(2, '0');
    const expirationDate = `${expYear}-${expMonth}-${expDay}T00:00:00.000${timezone}`;

    const quotation: LexOfficeQuotation = {
      voucherDate,
      expirationDate,
      address: {
        contactId: contactId,
        name: booking.customerName,
        street: booking.customerAddress || undefined,
        zip: booking.customerZip || undefined,
        city: booking.customerCity || undefined,
        countryCode: 'DE',
      },
      lineItems,
      totalPrice: {
        currency: 'EUR',
      },
      taxConditions: {
        taxType: 'net',
      },
      introduction: 'Vielen Dank für Ihre Anfrage! Gerne erstellen wir Ihnen folgendes Angebot:',
      remark: 'Wir freuen uns auf Ihre Bestellung!',
    };

    console.log('📤 Sending to LexOffice:', JSON.stringify(quotation, null, 2));

    // Schritt 1: Erstelle Quotation als Draft
    const result = await this.createQuotation(quotation, false);
    console.log('✅ Quotation created (draft):', result.id);
    
    // Schritt 2: Finalisiere Quotation sofort
    try {
      console.log('🔄 Finalizing quotation...');
      await this.finalizeQuotation(result.id);
      console.log('✅ Quotation finalized to OPEN status');
    } catch (error: any) {
      console.error('⚠️  Quotation finalization failed:', error.message);
      console.log('ℹ️  Quotation bleibt im DRAFT status');
    }
    
    return result.id;
  }

  async createConfirmationFromBooking(booking: any, contactId: string): Promise<string> {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    
    const isDST = (date: Date) => {
      const jan = new Date(date.getFullYear(), 0, 1).getTimezoneOffset();
      const jul = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
      return Math.max(jan, jul) !== date.getTimezoneOffset();
    };
    
    const timezone = isDST(now) ? '+02:00' : '+01:00';
    const voucherDate = `${year}-${month}-${day}T00:00:00.000${timezone}`;

    const invoice: LexOfficeInvoice = {
      voucherDate,
      address: {
        contactId: contactId,
        name: booking.customerName,
        countryCode: 'DE',
      },
      lineItems: [
        {
          type: 'custom',
          name: 'Fotobox-Vermietung',
          description: `Event am ${new Date(booking.eventDate).toLocaleDateString('de-DE')} in ${booking.eventCity}\nAufbau: ${new Date(booking.setupTimeStart).toLocaleString('de-DE')}\nOrt: ${booking.eventAddress}, ${booking.eventZip} ${booking.eventCity}`,
          quantity: 1,
          unitName: 'Stück',
          unitPrice: {
            currency: 'EUR',
            netAmount: booking.calculatedPrice || 0,
            taxRatePercentage: 19,
          },
        },
      ],
      totalPrice: {
        currency: 'EUR',
      },
      taxConditions: {
        taxType: 'net',
      },
      title: `AB ${booking.bookingNumber}`,
      introduction: 'Vielen Dank für Ihre Bestellung! Hiermit bestätigen wir Ihren Auftrag:',
      remark: 'Wir freuen uns auf Ihre Veranstaltung!',
      shippingConditions: {
        shippingDate: new Date(booking.eventDate).toISOString().split('T')[0],
        shippingType: 'service',
      },
      paymentConditions: {
        paymentTermLabel: 'Zahlung bei Lieferung',
        paymentTermDuration: 0,
      },
    };

    const result = await this.createInvoice(invoice);
    
    await this.finalizeInvoice(result.id);
    
    return result.id;
  }
}

export const lexofficeService = new LexOfficeService();
