package de.votian.services.service;

import de.votian.services.entity.Employee;
import de.votian.services.entity.EmployeeCostCenter;
import de.votian.services.entity.EmployeeRights;
import de.votian.services.repository.EmployeeCostCenterRepository;
import de.votian.services.entity.User;
import de.votian.services.repository.EmployeeRepository;
import de.votian.services.repository.EmployeeRightsRepository;
import de.votian.services.repository.UserRepository;
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 EmployeeService {

    private final EmployeeRepository employeeRepository;
    private final EmployeeRightsRepository employeeRightsRepository;
    private final EmployeeCostCenterRepository employeeCostCenterRepository;
    private final UserRepository userRepository;

    public EmployeeService(EmployeeRepository employeeRepository,
                           EmployeeRightsRepository employeeRightsRepository,
                           EmployeeCostCenterRepository employeeCostCenterRepository,
                           UserRepository userRepository) {
        this.employeeRepository = employeeRepository;
        this.employeeRightsRepository = employeeRightsRepository;
        this.employeeCostCenterRepository = employeeCostCenterRepository;
        this.userRepository = userRepository;
    }

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

    public List<Employee> findAll() {
        return employeeRepository.findAll();
    }

    @Transactional
    public Employee createEmployee(Employee employee, User user, String password) {
        if (user.getType() == null) {
            user.setType(1);
        }
        if (password != null && !password.isEmpty()) {
            user.setPassword(password);
            user.setPasswordModify(LocalDateTime.now());
        }
        User savedUser = userRepository.save(user);

        employee.setUserId(savedUser.getId());
        if (employee.getHeadquartersId() == null) {
            employee.setHeadquartersId(savedUser.getHeadquartersId());
        }
        if (employee.getRights() == null || employee.getRights().isBlank()) {
            employee.setRights(defaultRightsForType(user.getType()));
        }
        return employeeRepository.save(employee);
    }

    @Transactional
    public Employee updateEmployee(Long empId, Employee updates, User userUpdates) {
        Employee employee = employeeRepository.findById(Objects.requireNonNull(empId))
                .orElseThrow(() -> new RuntimeException("Employee not found: " + empId));

        userRepository.findById(Objects.requireNonNull(employee.getUserId())).ifPresent(user -> {
            if (userUpdates.getAccount() != null) user.setAccount(userUpdates.getAccount());
            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.getBirthdate() != null) user.setBirthdate(userUpdates.getBirthdate());
            if (userUpdates.getType() != null) user.setType(userUpdates.getType());
            if (userUpdates.getHeadquartersId() != null) user.setHeadquartersId(userUpdates.getHeadquartersId());
            userRepository.save(Objects.requireNonNull(user));
        });

        if (userUpdates.getType() != null && userUpdates.getType() != 2) {
            employee.setCostCenterId(null);
        } else if (updates.getCostCenterId() != null) {
            employee.setCostCenterId(updates.getCostCenterId());
        }
        if (updates.getHeadquarters() != null) employee.setHeadquarters(updates.getHeadquarters());
        if (updates.getHeadquartersId() != null) employee.setHeadquartersId(updates.getHeadquartersId());
        if (updates.getRights() != null) employee.setRights(updates.getRights());
        if (updates.getGroup() != null) employee.setGroup(updates.getGroup());

        return employeeRepository.save(employee);
    }

    // Rights management
    public List<EmployeeRights> getRights(Long empId) {
        return employeeRightsRepository.findByEmployeeId(empId);
    }

    @Transactional
    public void setRights(Long empId, List<EmployeeRights> rights) {
        employeeRightsRepository.deleteByEmployeeId(empId);
        employeeRightsRepository.saveAll(Objects.requireNonNull(rights));
    }

    @Transactional
    public void setRightsForHqs(Long empId, List<Long> hqIds, List<EmployeeRights> rights) {
        employeeRightsRepository.deleteByEmployeeIdAndHqIds(empId, hqIds);
        employeeRightsRepository.saveAll(Objects.requireNonNull(rights));
    }

    public List<EmployeeCostCenter> getCostCenterAccess(Long empId) {
        return employeeCostCenterRepository.findByEmployeeIdOrderByCostCenterIdAsc(empId);
    }

    @Transactional
    public void setCostCenterAccess(Long empId, List<EmployeeCostCenter> costCenters) {
        employeeCostCenterRepository.deleteByEmployeeId(empId);
        employeeCostCenterRepository.saveAll(Objects.requireNonNull(costCenters));
    }

    private String defaultRightsForType(Integer userType) {
        if (Integer.valueOf(2).equals(userType)) {
            return "11111100001000000000000000000000000000000000000000";
        }
        if (Integer.valueOf(4).equals(userType)) {
            return "00000000000000000000000000000000000000000000000000";
        }
        return "11111111111111101111111111111111111111111111111111";
    }
}
