package de.assecutor.votianlt.model.invoices;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Document(collection = "customerInvoices")
public class CustomerInvoice {

    @Id
    private String id;

    // Lebenszyklus und Belegtyp gemäß invoices_rules R-01 bis R-22
    private InvoiceStatus status = InvoiceStatus.DRAFT;
    private InvoiceType type = InvoiceType.INVOICE;

    // Verknüpfung auf die Originalrechnung bei Korrektur- oder Stornobelegen (R-10, R-13, R-19, R-22, R-30)
    private String originalInvoiceId;
    private String originalInvoiceNumber;
    private LocalDate originalInvoiceDate;

    // Verkettung: bei stornierten/korrigierten Originalen Verweise auf die erzeugten Folgebelege.
    private String cancellationInvoiceId;
    private String correctionInvoiceId;
    private String replacementInvoiceId;

    // Zeitstempel für Statusübergänge
    private LocalDateTime issuedAt;
    private LocalDateTime sentAt;
    private LocalDateTime cancelledAt;

    // Änderungsprotokoll (R-36 bis R-39)
    private List<InvoiceAuditEntry> auditLog = new ArrayList<>();

    // Zahlungsstatus gemäß R-23 bis R-26
    private PaymentStatus paymentStatus = PaymentStatus.UNPAID;
    private BigDecimal paidAmount;
    private LocalDateTime lastPaymentAt;

    // Pflichtangaben nach §14 UStG (German VAT law)
    private String invoiceNumber; // Fortlaufende Rechnungsnummer
    private LocalDate invoiceDate; // Rechnungsdatum
    private LocalDate deliveryDate; // Leistungsdatum

    // Rechnungssteller (Sender)
    private String senderName;
    private String senderAddress;
    private String senderPostcode;
    private String senderCity;
    private String senderCountry;
    private String senderTaxNumber; // Steuernummer
    private String senderVatId; // USt-IdNr.
    private String senderPhone;
    private String senderEmail;
    private String senderWebsite;

    // Rechnungsempfänger (Recipient)
    private String recipientName;
    private String recipientCompany;
    private String recipientAddress;
    private String recipientPostcode;
    private String recipientCity;
    private String recipientCountry;
    private String recipientVatId; // USt-IdNr. des Empfängers (falls vorhanden)
    private String recipientEmail; // E-Mail für den Rechnungsversand

    // Rechnungsdetails
    private String description; // Beschreibung der Leistung
    private List<CustomerInvoiceItem> items;

    // Beträge
    private BigDecimal netAmount; // Nettobetrag
    private BigDecimal vatRate; // Steuersatz (z.B. 19% = 0.19)
    private BigDecimal vatAmount; // Steuerbetrag
    private BigDecimal totalAmount; // Bruttobetrag

    // Zahlungsdetails
    private String paymentTerms; // Zahlungsbedingungen
    private LocalDate paymentDueDate; // Fälligkeitsdatum
    private String bankAccount; // Bankverbindung
    private String iban;
    private String bic;

    // Zusätzliche rechtliche Angaben
    private String legalNotes; // Rechtliche Hinweise
    private String reverseChargeNote; // Hinweis auf Reverse Charge (falls zutreffend)

    // Verknüpfung mit Auftrag und Benutzer
    private String jobId; // Referenz auf den Auftrag
    private String userId; // Referenz auf den Benutzer (Rechnungsersteller)

    // Gespeicherte PDF-Daten (Base64-kodiert)
    private byte[] pdfData;

    // Constructors
    public CustomerInvoice() {
    }

    public CustomerInvoice(String invoiceNumber, LocalDate invoiceDate, String description) {
        this.invoiceNumber = invoiceNumber;
        this.invoiceDate = invoiceDate;
        this.description = description;
    }

    // Getters and Setters
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getInvoiceNumber() {
        return invoiceNumber;
    }

    public void setInvoiceNumber(String invoiceNumber) {
        this.invoiceNumber = invoiceNumber;
    }

    public LocalDate getInvoiceDate() {
        return invoiceDate;
    }

    public void setInvoiceDate(LocalDate invoiceDate) {
        this.invoiceDate = invoiceDate;
    }

    public LocalDate getDeliveryDate() {
        return deliveryDate;
    }

    public void setDeliveryDate(LocalDate deliveryDate) {
        this.deliveryDate = deliveryDate;
    }

    public String getSenderName() {
        return senderName;
    }

    public void setSenderName(String senderName) {
        this.senderName = senderName;
    }

    public String getSenderAddress() {
        return senderAddress;
    }

    public void setSenderAddress(String senderAddress) {
        this.senderAddress = senderAddress;
    }

    public String getSenderPostcode() {
        return senderPostcode;
    }

    public void setSenderPostcode(String senderPostcode) {
        this.senderPostcode = senderPostcode;
    }

    public String getSenderCity() {
        return senderCity;
    }

    public void setSenderCity(String senderCity) {
        this.senderCity = senderCity;
    }

    public String getSenderCountry() {
        return senderCountry;
    }

    public void setSenderCountry(String senderCountry) {
        this.senderCountry = senderCountry;
    }

    public String getSenderTaxNumber() {
        return senderTaxNumber;
    }

    public void setSenderTaxNumber(String senderTaxNumber) {
        this.senderTaxNumber = senderTaxNumber;
    }

    public String getSenderVatId() {
        return senderVatId;
    }

    public void setSenderVatId(String senderVatId) {
        this.senderVatId = senderVatId;
    }

    public String getSenderPhone() {
        return senderPhone;
    }

    public void setSenderPhone(String senderPhone) {
        this.senderPhone = senderPhone;
    }

    public String getSenderEmail() {
        return senderEmail;
    }

    public void setSenderEmail(String senderEmail) {
        this.senderEmail = senderEmail;
    }

    public String getSenderWebsite() {
        return senderWebsite;
    }

    public void setSenderWebsite(String senderWebsite) {
        this.senderWebsite = senderWebsite;
    }

    public String getRecipientName() {
        return recipientName;
    }

    public void setRecipientName(String recipientName) {
        this.recipientName = recipientName;
    }

    public String getRecipientCompany() {
        return recipientCompany;
    }

    public void setRecipientCompany(String recipientCompany) {
        this.recipientCompany = recipientCompany;
    }

    public String getRecipientAddress() {
        return recipientAddress;
    }

    public void setRecipientAddress(String recipientAddress) {
        this.recipientAddress = recipientAddress;
    }

    public String getRecipientPostcode() {
        return recipientPostcode;
    }

    public void setRecipientPostcode(String recipientPostcode) {
        this.recipientPostcode = recipientPostcode;
    }

    public String getRecipientCity() {
        return recipientCity;
    }

    public void setRecipientCity(String recipientCity) {
        this.recipientCity = recipientCity;
    }

    public String getRecipientCountry() {
        return recipientCountry;
    }

    public void setRecipientCountry(String recipientCountry) {
        this.recipientCountry = recipientCountry;
    }

    public String getRecipientVatId() {
        return recipientVatId;
    }

    public void setRecipientVatId(String recipientVatId) {
        this.recipientVatId = recipientVatId;
    }

    public String getRecipientEmail() {
        return recipientEmail;
    }

    public void setRecipientEmail(String recipientEmail) {
        this.recipientEmail = recipientEmail;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<CustomerInvoiceItem> getItems() {
        return items;
    }

    public void setItems(List<CustomerInvoiceItem> items) {
        this.items = items;
    }

    public BigDecimal getNetAmount() {
        return netAmount;
    }

    public void setNetAmount(BigDecimal netAmount) {
        this.netAmount = netAmount;
    }

    public BigDecimal getVatRate() {
        return vatRate;
    }

    public void setVatRate(BigDecimal vatRate) {
        this.vatRate = vatRate;
    }

    public BigDecimal getVatAmount() {
        return vatAmount;
    }

    public void setVatAmount(BigDecimal vatAmount) {
        this.vatAmount = vatAmount;
    }

    public BigDecimal getTotalAmount() {
        return totalAmount;
    }

    public void setTotalAmount(BigDecimal totalAmount) {
        this.totalAmount = totalAmount;
    }

    public String getPaymentTerms() {
        return paymentTerms;
    }

    public void setPaymentTerms(String paymentTerms) {
        this.paymentTerms = paymentTerms;
    }

    public LocalDate getPaymentDueDate() {
        return paymentDueDate;
    }

    public void setPaymentDueDate(LocalDate paymentDueDate) {
        this.paymentDueDate = paymentDueDate;
    }

    public String getBankAccount() {
        return bankAccount;
    }

    public void setBankAccount(String bankAccount) {
        this.bankAccount = bankAccount;
    }

    public String getIban() {
        return iban;
    }

    public void setIban(String iban) {
        this.iban = iban;
    }

    public String getBic() {
        return bic;
    }

    public void setBic(String bic) {
        this.bic = bic;
    }

    public String getLegalNotes() {
        return legalNotes;
    }

    public void setLegalNotes(String legalNotes) {
        this.legalNotes = legalNotes;
    }

    public String getReverseChargeNote() {
        return reverseChargeNote;
    }

    public void setReverseChargeNote(String reverseChargeNote) {
        this.reverseChargeNote = reverseChargeNote;
    }

    public String getJobId() {
        return jobId;
    }

    public void setJobId(String jobId) {
        this.jobId = jobId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public byte[] getPdfData() {
        return pdfData;
    }

    public void setPdfData(byte[] pdfData) {
        this.pdfData = pdfData;
    }

    public InvoiceStatus getStatus() {
        return status;
    }

    public void setStatus(InvoiceStatus status) {
        this.status = status;
    }

    public InvoiceType getType() {
        return type;
    }

    public void setType(InvoiceType type) {
        this.type = type;
    }

    public String getOriginalInvoiceId() {
        return originalInvoiceId;
    }

    public void setOriginalInvoiceId(String originalInvoiceId) {
        this.originalInvoiceId = originalInvoiceId;
    }

    public String getOriginalInvoiceNumber() {
        return originalInvoiceNumber;
    }

    public void setOriginalInvoiceNumber(String originalInvoiceNumber) {
        this.originalInvoiceNumber = originalInvoiceNumber;
    }

    public LocalDate getOriginalInvoiceDate() {
        return originalInvoiceDate;
    }

    public void setOriginalInvoiceDate(LocalDate originalInvoiceDate) {
        this.originalInvoiceDate = originalInvoiceDate;
    }

    public String getCancellationInvoiceId() {
        return cancellationInvoiceId;
    }

    public void setCancellationInvoiceId(String cancellationInvoiceId) {
        this.cancellationInvoiceId = cancellationInvoiceId;
    }

    public String getCorrectionInvoiceId() {
        return correctionInvoiceId;
    }

    public void setCorrectionInvoiceId(String correctionInvoiceId) {
        this.correctionInvoiceId = correctionInvoiceId;
    }

    public String getReplacementInvoiceId() {
        return replacementInvoiceId;
    }

    public void setReplacementInvoiceId(String replacementInvoiceId) {
        this.replacementInvoiceId = replacementInvoiceId;
    }

    public LocalDateTime getIssuedAt() {
        return issuedAt;
    }

    public void setIssuedAt(LocalDateTime issuedAt) {
        this.issuedAt = issuedAt;
    }

    public LocalDateTime getSentAt() {
        return sentAt;
    }

    public void setSentAt(LocalDateTime sentAt) {
        this.sentAt = sentAt;
    }

    public LocalDateTime getCancelledAt() {
        return cancelledAt;
    }

    public void setCancelledAt(LocalDateTime cancelledAt) {
        this.cancelledAt = cancelledAt;
    }

    public List<InvoiceAuditEntry> getAuditLog() {
        if (auditLog == null) {
            auditLog = new ArrayList<>();
        }
        return auditLog;
    }

    public void setAuditLog(List<InvoiceAuditEntry> auditLog) {
        this.auditLog = auditLog != null ? auditLog : new ArrayList<>();
    }

    public void addAuditEntry(InvoiceAuditEntry entry) {
        if (entry == null) {
            return;
        }
        getAuditLog().add(entry);
    }

    public PaymentStatus getPaymentStatus() {
        return paymentStatus;
    }

    public void setPaymentStatus(PaymentStatus paymentStatus) {
        this.paymentStatus = paymentStatus;
    }

    public BigDecimal getPaidAmount() {
        return paidAmount;
    }

    public void setPaidAmount(BigDecimal paidAmount) {
        this.paidAmount = paidAmount;
    }

    public LocalDateTime getLastPaymentAt() {
        return lastPaymentAt;
    }

    public void setLastPaymentAt(LocalDateTime lastPaymentAt) {
        this.lastPaymentAt = lastPaymentAt;
    }
}
