package de.votian.services.service;

import de.votian.services.entity.Address;
import de.votian.services.entity.Company;
import de.votian.services.entity.CostCenter;
import de.votian.services.entity.CostCenterAddress;
import de.votian.services.entity.Customer;
import de.votian.services.entity.Employee;
import de.votian.services.entity.Job;
import de.votian.services.entity.User;
import de.votian.services.repository.AddressRepository;
import de.votian.services.repository.CompanyRepository;
import de.votian.services.repository.CostCenterAddressRepository;
import de.votian.services.repository.CostCenterRepository;
import de.votian.services.repository.CustomerRepository;
import de.votian.services.repository.EmployeeRepository;
import de.votian.services.repository.JobRepository;
import de.votian.services.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.JdbcTemplate;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@SuppressWarnings("null")
class LegacyXmlSystemIntegrationServiceTest {

    private LegacyXmlSystemAuthService authService;
    private CustomerRepository customerRepository;
    private CompanyRepository companyRepository;
    private EmployeeRepository employeeRepository;
    private UserRepository userRepository;
    private CostCenterRepository costCenterRepository;
    private CostCenterAddressRepository costCenterAddressRepository;
    private AddressRepository addressRepository;
    private JobRepository jobRepository;
    private JdbcTemplate jdbcTemplate;
    private LegacyXmlSystemIntegrationService service;

    @BeforeEach
    void setUp() {
        authService = mock(LegacyXmlSystemAuthService.class);
        customerRepository = mock(CustomerRepository.class);
        companyRepository = mock(CompanyRepository.class);
        employeeRepository = mock(EmployeeRepository.class);
        userRepository = mock(UserRepository.class);
        costCenterRepository = mock(CostCenterRepository.class);
        costCenterAddressRepository = mock(CostCenterAddressRepository.class);
        addressRepository = mock(AddressRepository.class);
        jobRepository = mock(JobRepository.class);
        jdbcTemplate = mock(JdbcTemplate.class);
        service = new LegacyXmlSystemIntegrationService(
                authService,
                customerRepository,
                companyRepository,
                employeeRepository,
                userRepository,
                costCenterRepository,
                costCenterAddressRepository,
                addressRepository,
                jobRepository,
                jdbcTemplate
        );
    }

    @Test
    void customerRequestBuildsLegacyCustomerXml() {
        Customer customer = new Customer();
        customer.setId(7L);
        customer.setEid("AG-100");
        customer.setSid("REMOTE-7");
        customer.setHeadquartersId(1L);
        customer.setCompanyId(20L);
        customer.setAdminEmployeeId(30L);
        customer.setMarkup(new java.math.BigDecimal("12.50"));
        customer.setDiscount(new java.math.BigDecimal("5.00"));
        customer.setInvoiceMode(1);
        customer.setJobStatusMail("done@example.org");

        Company company = new Company();
        company.setId(20L);
        company.setType(2);
        company.setComp("Muster GmbH");
        company.setHsno("12a");
        company.setAddressId(40L);
        company.setIln("123");

        Address companyAddress = new Address();
        companyAddress.setId(40L);
        companyAddress.setStreet("Testweg");
        companyAddress.setZipcode("10115");
        companyAddress.setCity("Berlin");
        companyAddress.setCountry("DE");

        Employee employee = new Employee();
        employee.setId(30L);
        employee.setUserId(50L);

        User user = new User();
        user.setId(50L);
        user.setAccount("customer-root");
        user.setName("Mustermann");
        user.setFirstname("Max");
        user.setBirthdate(LocalDate.of(1980, 1, 2));
        user.setEmail("max@example.org");
        user.setInvoiceEmail("invoice@example.org");
        user.setPhone("0301234");

        CostCenter root = new CostCenter();
        root.setId(60L);
        root.setCustomerId(7L);
        root.setName("Root");

        CostCenterAddress rootAddress = new CostCenterAddress();
        rootAddress.setAddressTypeId(4);
        rootAddress.setAddressId(61L);
        rootAddress.setComp("Root GmbH");

        Address costcenterAddress = new Address();
        costcenterAddress.setId(61L);
        costcenterAddress.setStreet("Lagerstrasse");
        costcenterAddress.setZipcode("04109");
        costcenterAddress.setCity("Leipzig");
        costcenterAddress.setCountry("DE");

        Job lastJob = new Job();
        lastJob.setId(99L);

        when(customerRepository.findByEid("AG-100")).thenReturn(Optional.of(customer));
        when(companyRepository.findById(20L)).thenReturn(Optional.of(company));
        when(employeeRepository.findById(30L)).thenReturn(Optional.of(employee));
        when(userRepository.findById(50L)).thenReturn(Optional.of(user));
        when(costCenterRepository.findByCustomerId(7L)).thenReturn(List.of(root));
        when(costCenterAddressRepository.findByCostCenterId(60L)).thenReturn(List.of(rootAddress));
        when(addressRepository.findById(40L)).thenReturn(Optional.of(companyAddress));
        when(addressRepository.findById(61L)).thenReturn(Optional.of(costcenterAddress));
        when(jobRepository.findByPayerCostCenters(List.of(60L))).thenReturn(List.of(lastJob));
        when(jdbcTemplate.queryForList(anyString(), anyLong())).thenReturn(List.of(Map.of("gc_lat", "52.5", "gc_long", "13.4")));
        when(jdbcTemplate.queryForList(anyString(), anyLong(), anyString()))
                .thenReturn(List.of(Map.of("cr_id", 77L, "cr_eid", "CR-77")))
                .thenReturn(List.of());

        String response = service.handleCustomerRequest("""
                <xml><customer><auth><session_id>SESSION</session_id><passphrase>PASS</passphrase></auth><cs_eid>AG-100</cs_eid><cs_last_job>YES</cs_last_job></customer></xml>
                """);

        verify(authService).authenticate("SESSION", "PASS");
        assertThat(response).contains("<state>OK</state>");
        assertThat(response).contains("<cs_id>7</cs_id>");
        assertThat(response).contains("<cs_eid><![CDATA[AG-100]]></cs_eid>");
        assertThat(response).contains("<cmp_comp><![CDATA[Muster GmbH]]></cmp_comp>");
        assertThat(response).contains("<usr_account><![CDATA[customer-root]]></usr_account>");
        assertThat(response).contains("<csc_id>60</csc_id>");
        assertThat(response).contains("<cr_eid><![CDATA[CR-77]]></cr_eid>");
        assertThat(response).contains("<cs_last_job>99</cs_last_job>");
    }
}
