package de.assecutor.votianlt.pages.service;

import de.assecutor.votianlt.model.Customer;
import de.assecutor.votianlt.pages.domain.AddCustomerRepository;
import de.assecutor.votianlt.security.SecurityService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class AddCustomerService {
    private final AddCustomerRepository addCustomerRepository;
    private final SecurityService securityService;
    private final SequenceGeneratorService sequenceGeneratorService;

    AddCustomerService(AddCustomerRepository addCustomerRepository, SecurityService securityService,
            SequenceGeneratorService sequenceGeneratorService) {
        this.addCustomerRepository = addCustomerRepository;
        this.securityService = securityService;
        this.sequenceGeneratorService = sequenceGeneratorService;
    }

    /**
     * Creates the customer unless a completely identical entry already exists
     * for the current owner. Returns false if the duplicate was skipped.
     */
    public boolean addCustomer(Customer customer) {
        validateCustomer(customer);

        // Setze den aktuellen Benutzer als Ersteller - jetzt direkt aus der Session
        de.assecutor.votianlt.model.User currentUser = securityService.getCurrentDatabaseUser();
        customer.setCreatedBy(currentUser.getId());
        customer.setOwner(currentUser.getId());

        // Keine komplett identischen Einträge anlegen
        if (identicalCustomerExists(customer)) {
            return false;
        }

        if (customer.getUsrId() == null) {
            customer.setUsrId(sequenceGeneratorService.nextCustomerNumber());
        }

        addCustomerRepository.save(customer);
        return true;
    }

    public void addInternalCustomer(Customer customer) {
        if (customer == null) {
            return;
        }
        customer.setId(null);
        customer.setInternal(true);
        addCustomer(customer);
    }

    private boolean identicalCustomerExists(Customer customer) {
        return addCustomerRepository.findByOwnerAndInternal(customer.getOwner(), customer.isInternal()).stream()
                .anyMatch(existing -> isIdentical(existing, customer));
    }

    private boolean isIdentical(Customer a, Customer b) {
        return equalsNormalized(a.getCompanyName(), b.getCompanyName()) && equalsNormalized(a.getTitle(), b.getTitle())
                && equalsNormalized(a.getFirstname(), b.getFirstname())
                && equalsNormalized(a.getLastName(), b.getLastName())
                && equalsNormalized(a.getTelephone(), b.getTelephone()) && equalsNormalized(a.getMail(), b.getMail())
                && equalsNormalized(a.getStreet(), b.getStreet())
                && equalsNormalized(a.getHouseNumber(), b.getHouseNumber())
                && equalsNormalized(a.getAddressAddition(), b.getAddressAddition())
                && equalsNormalized(a.getZip(), b.getZip()) && equalsNormalized(a.getCity(), b.getCity());
    }

    private boolean equalsNormalized(String first, String second) {
        String left = first != null ? first.trim() : "";
        String right = second != null ? second.trim() : "";
        return left.equalsIgnoreCase(right);
    }

    public void updateCustomer(Customer customer) {
        if (customer == null || customer.getId() == null) {
            throw new IllegalArgumentException("Kunden-ID fehlt");
        }
        validateCustomer(customer);

        Customer existing = addCustomerRepository.findById(customer.getId())
                .orElseThrow(() -> new IllegalArgumentException("Kunde nicht gefunden"));
        customer.setCreatedBy(existing.getCreatedBy());
        customer.setOwner(existing.getOwner());
        if (customer.getUsrId() == null) {
            customer.setUsrId(existing.getUsrId());
        }

        addCustomerRepository.save(customer);
    }

    private void validateCustomer(Customer customer) {
        if (customer == null) {
            throw new IllegalArgumentException("Kunde darf nicht leer sein");
        }

        String mail = customer.getMail() != null ? customer.getMail().trim() : "";
        if (!mail.isEmpty() && !mail.contains("@")) {
            throw new IllegalArgumentException("Bitte geben Sie eine gültige E-Mail-Adresse ein");
        }

        customer.setMail(mail.isEmpty() ? null : mail);
    }
}
