import { InvoiceType } from '@prisma/client';
import prisma from '../lib/prisma.js';
import fs from 'fs';
import path from 'path';

export interface CreateInvoiceData {
  invoiceDate: Date;
  invoiceType: InvoiceType;
  documentPath?: string;
  notes?: string;
}

export interface UpdateInvoiceData {
  invoiceDate?: Date;
  invoiceType?: InvoiceType;
  documentPath?: string;
  notes?: string;
}

/**
 * Alle Rechnungen für ein EnergyContractDetails abrufen
 */
export async function getInvoices(energyContractDetailsId: number) {
  return prisma.invoice.findMany({
    where: { energyContractDetailsId },
    orderBy: { invoiceDate: 'desc' },
  });
}

/**
 * Einzelne Rechnung abrufen
 */
export async function getInvoice(energyContractDetailsId: number, invoiceId: number) {
  return prisma.invoice.findFirst({
    where: { id: invoiceId, energyContractDetailsId },
  });
}

/**
 * Neue Rechnung hinzufügen
 *
 * Hinweis: Die Validierung ob ein Dokument vorhanden ist, erfolgt NICHT hier,
 * da der typische Flow so aussieht:
 * 1. Invoice erstellen (ohne Dokument) → Invoice-ID zurückbekommen
 * 2. Dokument hochladen mit der Invoice-ID
 *
 * Die Validierung ob alle Rechnungen Dokumente haben, erfolgt im Cockpit.
 */
export async function addInvoice(energyContractDetailsId: number, data: CreateInvoiceData) {
  // Prüfen ob EnergyContractDetails existiert
  const energyDetails = await prisma.energyContractDetails.findUnique({
    where: { id: energyContractDetailsId },
  });

  if (!energyDetails) {
    throw new Error('Energievertrag nicht gefunden');
  }

  return prisma.invoice.create({
    data: {
      energyContractDetailsId,
      contractId: energyDetails.contractId,
      invoiceDate: data.invoiceDate,
      invoiceType: data.invoiceType,
      documentPath: data.documentPath,
      notes: data.notes,
    },
  });
}

/**
 * Rechnung direkt über contractId hinzufügen (für alle Vertragstypen)
 */
export async function addInvoiceByContract(contractId: number, data: CreateInvoiceData) {
  return prisma.invoice.create({
    data: {
      contractId,
      invoiceDate: data.invoiceDate,
      invoiceType: data.invoiceType,
      documentPath: data.documentPath,
      notes: data.notes,
    },
  });
}

export async function getInvoicesByContract(contractId: number) {
  return prisma.invoice.findMany({
    where: { contractId },
    orderBy: { invoiceDate: 'desc' },
  });
}

/**
 * Rechnung aktualisieren
 */
export async function updateInvoice(
  energyContractDetailsId: number,
  invoiceId: number,
  data: UpdateInvoiceData
) {
  // Prüfen ob Rechnung existiert und zum EnergyContractDetails gehört
  const invoice = await prisma.invoice.findFirst({
    where: { id: invoiceId, energyContractDetailsId },
  });

  if (!invoice) {
    throw new Error('Rechnung nicht gefunden');
  }

  // Validierung bei Typ-Änderung
  const newType = data.invoiceType ?? invoice.invoiceType;
  const newPath = data.documentPath !== undefined ? data.documentPath : invoice.documentPath;

  if (newType !== 'NOT_AVAILABLE' && !newPath) {
    throw new Error('Dokument ist Pflicht (außer bei Typ "Nicht verfügbar")');
  }

  return prisma.invoice.update({
    where: { id: invoiceId },
    data: {
      invoiceDate: data.invoiceDate,
      invoiceType: data.invoiceType,
      documentPath: data.documentPath,
      notes: data.notes,
    },
  });
}

/**
 * Rechnung löschen
 */
export async function deleteInvoice(energyContractDetailsId: number, invoiceId: number) {
  const invoice = await prisma.invoice.findFirst({
    where: { id: invoiceId, energyContractDetailsId },
  });

  if (!invoice) {
    throw new Error('Rechnung nicht gefunden');
  }

  // Datei löschen falls vorhanden
  if (invoice.documentPath) {
    const filePath = path.join(process.cwd(), invoice.documentPath);
    if (fs.existsSync(filePath)) {
      fs.unlinkSync(filePath);
    }
  }

  return prisma.invoice.delete({ where: { id: invoiceId } });
}

/**
 * Rechnung direkt erstellen (für E-Mail-Integration)
 * Erstellt eine Rechnung mit bereits vorhandenem Dokument
 */
export async function createInvoiceWithDocument(
  energyContractDetailsId: number,
  invoiceDate: Date,
  invoiceType: InvoiceType,
  documentPath: string,
  notes?: string
) {
  // Prüfen ob EnergyContractDetails existiert
  const energyDetails = await prisma.energyContractDetails.findUnique({
    where: { id: energyContractDetailsId },
  });

  if (!energyDetails) {
    throw new Error('Energievertrag nicht gefunden');
  }

  return prisma.invoice.create({
    data: {
      energyContractDetailsId,
      invoiceDate,
      invoiceType,
      documentPath,
      notes,
    },
  });
}
