package de.votian.services.service;

import de.votian.services.entity.*;
import de.votian.services.repository.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Service
@Transactional
public class CustomerService {

    private final CustomerRepository customerRepository;
    private final CompanyRepository companyRepository;
    private final UserRepository userRepository;
    private final EmployeeRepository employeeRepository;
    private final CostCenterRepository costCenterRepository;
    private final CostCenterAddressRepository costCenterAddressRepository;
    private final AddressRepository addressRepository;

    public CustomerService(CustomerRepository customerRepository, CompanyRepository companyRepository,
                           UserRepository userRepository, EmployeeRepository employeeRepository,
                           CostCenterRepository costCenterRepository,
                           CostCenterAddressRepository costCenterAddressRepository,
                           AddressRepository addressRepository) {
        this.customerRepository = customerRepository;
        this.companyRepository = companyRepository;
        this.userRepository = userRepository;
        this.employeeRepository = employeeRepository;
        this.costCenterRepository = costCenterRepository;
        this.costCenterAddressRepository = costCenterAddressRepository;
        this.addressRepository = addressRepository;
    }

    public Optional<Customer> findById(Long id) {
        return customerRepository.findById(Objects.requireNonNull(id));
    }

    public List<Customer> findByHeadquarters(Long hqId) {
        return customerRepository.findByHeadquartersId(hqId);
    }

    public List<Customer> search(Long hqId, String searchTerm) {
        return customerRepository.searchCustomers(hqId, searchTerm);
    }

    public Optional<Customer> findByEid(String eid) {
        return customerRepository.findByEid(eid);
    }

    @Transactional
    public Customer createCustomer(Customer customer, Company company, User user, String password) {
        // Save address
        Address address = addressRepository.findByStreetAndZipcodeAndCityAndCountry(
                "", "", "", "DE").orElseGet(() -> {
            Address addr = new Address();
            addr.setCountry("DE");
            return addressRepository.save(addr);
        });

        // Save company
        company.setAddressId(address.getId());
        company.setType(2);
        company.setArchived("0");
        company.setModifyStatus("0");
        Company savedCompany = companyRepository.save(company);

        // Save user
        user.setType(2);
        user.setHeadquartersId(customer.getHeadquartersId());
        if (password != null && !password.isEmpty()) {
            user.setPassword(password);
            user.setPasswordModify(LocalDateTime.now());
        }
        User savedUser = userRepository.save(user);

        // Save employee
        Employee emp = new Employee();
        emp.setUserId(savedUser.getId());
        emp.setHeadquartersId(customer.getHeadquartersId());
        Employee savedEmployee = employeeRepository.save(emp);

        // Save customer
        customer.setCompanyId(savedCompany.getId());
        customer.setAdminEmployeeId(savedEmployee.getId());
        Customer savedCustomer = customerRepository.save(customer);

        // Create default cost center
        CostCenter csc = new CostCenter();
        csc.setCustomerId(savedCustomer.getId());
        csc.setName(savedCompany.getComp());
        csc.setVisible("1");
        csc.setPath("//" + savedCompany.getComp() + "//");
        costCenterRepository.save(csc);

        return savedCustomer;
    }

    @Transactional
    public Customer updateCustomer(Long customerId, Customer updates, Company companyUpdates, User userUpdates) {
        Customer customer = customerRepository.findById(Objects.requireNonNull(customerId))
                .orElseThrow(() -> new RuntimeException("Customer not found: " + customerId));

        // Update company
        companyRepository.findById(Objects.requireNonNull(customer.getCompanyId())).ifPresent(company -> {
            if (companyUpdates.getComp() != null) company.setComp(companyUpdates.getComp());
            if (companyUpdates.getComp2() != null) company.setComp2(companyUpdates.getComp2());
            if (companyUpdates.getComp3() != null) company.setComp3(companyUpdates.getComp3());
            if (companyUpdates.getComp4() != null) company.setComp4(companyUpdates.getComp4());
            if (companyUpdates.getHsno() != null) company.setHsno(companyUpdates.getHsno());
            if (companyUpdates.getIln() != null) company.setIln(companyUpdates.getIln());
            if (companyUpdates.getTaxIdNo() != null) company.setTaxIdNo(companyUpdates.getTaxIdNo());
            if (companyUpdates.getStaxIdNo() != null) company.setStaxIdNo(companyUpdates.getStaxIdNo());
            company.setModifyStatus("2");
            companyRepository.save(company);
        });

        // Update user via employee
        employeeRepository.findById(Objects.requireNonNull(customer.getAdminEmployeeId())).ifPresent(emp -> {
            userRepository.findById(Objects.requireNonNull(emp.getUserId())).ifPresent(user -> {
                if (userUpdates.getName() != null) user.setName(userUpdates.getName());
                if (userUpdates.getFirstname() != null) user.setFirstname(userUpdates.getFirstname());
                if (userUpdates.getEmail() != null) user.setEmail(userUpdates.getEmail());
                if (userUpdates.getPhone() != null) user.setPhone(userUpdates.getPhone());
                if (userUpdates.getPhone2() != null) user.setPhone2(userUpdates.getPhone2());
                if (userUpdates.getFax() != null) user.setFax(userUpdates.getFax());
                userRepository.save(Objects.requireNonNull(user));
            });
        });

        // Update customer fields
        if (updates.getDiscount() != null) customer.setDiscount(updates.getDiscount());
        if (updates.getGroup() != null) customer.setGroup(updates.getGroup());
        if (updates.getFilter() != null) customer.setFilter(updates.getFilter());
        if (updates.getCommissionNo() != null) customer.setCommissionNo(updates.getCommissionNo());
        if (updates.getTracking() != null) customer.setTracking(updates.getTracking());
        if (updates.getJobStatusMail() != null) customer.setJobStatusMail(updates.getJobStatusMail());

        return customerRepository.save(customer);
    }

    public void updateCostCenterAddress(Long cscId, Long addressId, String hsno) {
        costCenterAddressRepository.findByCostCenterIdAndAddressTypeId(cscId, 1).ifPresent(cscad -> {
            cscad.setAddressId(addressId);
            cscad.setHsno(hsno);
            costCenterAddressRepository.save(cscad);
        });
    }

    public void updateCostCenterCompany(Long cscId, String comp, String comp2, String comp3, String comp4) {
        costCenterAddressRepository.findByCostCenterIdAndAddressTypeId(cscId, 1).ifPresent(cscad -> {
            cscad.setComp(comp);
            cscad.setComp2(comp2);
            cscad.setComp3(comp3);
            cscad.setComp4(comp4);
            costCenterAddressRepository.save(cscad);
        });
    }

    public List<CostCenter> getCostCenters(Long customerId) {
        return costCenterRepository.findByCustomerId(customerId);
    }

    public List<CostCenter> getVisibleCostCenters(Long customerId) {
        return costCenterRepository.findVisibleByCustomerId(customerId);
    }
}
