package com.ikon.projectmanagement.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.ikon.projectmanagement.dto.response.EmployeeResponseDto;
import com.ikon.projectmanagement.dto.request.EmployeeRequestDto;
import com.ikon.projectmanagement.dto.response.EmployeeResponseDto;
import com.ikon.projectmanagement.entity.Employee;
import com.ikon.projectmanagement.repository.EmployeeRepository;
import com.ikon.projectmanagement.mapper.EmployeeMapper;
import com.ikon.projectmanagement.service.ImportEmployeeService;
import com.ikon.webservice.WebService;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class ImportEmployeeServiceImpl extends WebService implements ImportEmployeeService {

    private final EmployeeMapper employeeMapper;

    private final RestTemplate restTemplate;
    private final EmployeeRepository employeeRepository;

    @Value("${salescrm.api.base-url}")
    private String salesCrmBaseUrl;

    private HttpHeaders createHeaders(String accessToken) {
        HttpHeaders headers = new HttpHeaders();
        if (accessToken != null && !accessToken.isEmpty()) {
            headers.set("Authorization", accessToken);
        }
        headers.set("Content-Type", "application/json");
        return headers;
    }

    private static final int PAGE_SIZE = 200;

    @Override
    @Transactional
    public List<EmployeeResponseDto> importEmployees(String accessToken) {
        String baseUrl = salesCrmBaseUrl + "/employee";
        UUID accountId = getActiveAccountId();
        log.info("Fetching all employees from Sales CRM: {}", baseUrl);
        try {
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders(accessToken));
            List<EmployeeRequestDto> allDtos = new ArrayList<>();
            List<EmployeeResponseDto> savedResponses = new ArrayList<>();
            int page = 0;
            int totalPages = 1;

            while (page < totalPages) {
                String url = baseUrl + "?page=" + page + "&size=" + PAGE_SIZE;
                ResponseEntity<PageResponse<EmployeeRequestDto>> response = restTemplate.exchange(
                        url, HttpMethod.GET, entity, new ParameterizedTypeReference<PageResponse<EmployeeRequestDto>>() {});

                if (response.getBody() == null || response.getBody().getContent() == null) {
                    break;
                }

                PageResponse<EmployeeRequestDto> body = response.getBody();
                allDtos.addAll(body.getContent());
                totalPages = body.getTotalPages();
                log.info("Fetched employees page {}/{}", page + 1, totalPages);
                page++;
            }

            for (EmployeeRequestDto dto : allDtos) {
                Optional<Employee> existingOpt = employeeRepository.findByEmpId(dto.getEmpId());
                Employee emp;
                if (existingOpt.isPresent()) {
                    emp = existingOpt.get();
                    emp.setAccountId(accountId);
                    emp.setName(dto.getName());
                    emp.setEmail(dto.getEmail());
                    emp.setOrganizationEmail(dto.getOrganizationEmail());
                    emp.setRole(dto.getRole());
                    emp.setGrade(dto.getGrade());
                    emp.setActive(dto.getActive());
                } else {
                    emp = Employee.builder()
                            .empId(dto.getEmpId())
                            .accountId(accountId)
                            .name(dto.getName())
                            .email(dto.getEmail())
                            .organizationEmail(dto.getOrganizationEmail())
                            .role(dto.getRole())
                            .grade(dto.getGrade())
                            .active(dto.getActive())
                            .build();
                }
                employeeRepository.save(emp);
                savedResponses.add(employeeMapper.toResponseDto(emp));
            }

            if (!allDtos.isEmpty()) {
                log.info("Saved/Updated {} employees in total", allDtos.size());
            }

            return savedResponses;
        } catch (RestClientException e) {
            log.error("Failed to fetch employees from Sales CRM: {}", e.getMessage());
            return Collections.emptyList();
        }
    }

    @Data
    public static class PageResponse<T> {
        private List<T> content;
        private int totalPages;
        private long totalElements;
    }
}
