package com.ikon.projectmanagement.service.impl;

import java.util.List;
import java.util.UUID;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ikon.projectmanagement.dto.request.ProductPSResourceAllocationRequestDto;
import com.ikon.projectmanagement.dto.response.ProductPSResourceAllocationResponseDto;
import com.ikon.projectmanagement.entity.ProductOfProject;
import com.ikon.projectmanagement.entity.ProductPSResourceAllocation;
import com.ikon.projectmanagement.mapper.ProductResourceAllocationMapper;
import com.ikon.projectmanagement.repository.ProductOfProjectRepository;
import com.ikon.projectmanagement.service.ProductResourceAllocationService;
import com.ikon.webservice.WebService;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class ProductResourceAllocationServiceImpl extends WebService implements ProductResourceAllocationService {

    private final ProductOfProjectRepository productRepository;
    private final ProductResourceAllocationMapper allocationMapper;

    private ProductOfProject getProduct(UUID productIdentifier) {
        UUID accountId = getActiveAccountId();
        return productRepository
                .findByAccountIdAndProductIdentifier(accountId, productIdentifier)
                .orElseThrow(() -> new RuntimeException("Product not found"));
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProductPSResourceAllocationResponseDto> getResourceAllocations(UUID productIdentifier) {
        ProductOfProject product = getProduct(productIdentifier);
        return product.getResourceDataWithAllocation().stream()
                .map(allocationMapper::toResponse)
                .toList();
    }

    @Override
    @Transactional(readOnly = true)
    public ProductPSResourceAllocationResponseDto getResourceAllocation(UUID productIdentifier, UUID allocationIdentifier) {
        ProductOfProject product = getProduct(productIdentifier);
        ProductPSResourceAllocation allocation = product.getResourceDataWithAllocation().stream()
                .filter(a -> a.getId().equals(allocationIdentifier))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Allocation not found"));

        return allocationMapper.toResponse(allocation);
    }

    @Override
    @Transactional
    public ProductPSResourceAllocationResponseDto createResourceAllocation(UUID productIdentifier, ProductPSResourceAllocationRequestDto dto) {
        ProductOfProject product = getProduct(productIdentifier);
        ProductPSResourceAllocation allocation = allocationMapper.toEntity(dto, product);
        product.getResourceDataWithAllocation().add(allocation);
        productRepository.save(product);
        return allocationMapper.toResponse(allocation);
    }

    @Override
    @Transactional
    public ProductPSResourceAllocationResponseDto updateResourceAllocation(UUID productIdentifier, UUID allocationIdentifier, ProductPSResourceAllocationRequestDto dto) {
        ProductOfProject product = getProduct(productIdentifier);
        ProductPSResourceAllocation allocation = product.getResourceDataWithAllocation().stream()
                .filter(a -> a.getId().equals(allocationIdentifier))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Allocation not found"));

        allocationMapper.updateEntity(allocation, dto);
        productRepository.save(product);
        return allocationMapper.toResponse(allocation);
    }

    @Override
    @Transactional
    public void deleteResourceAllocation(UUID productIdentifier, UUID allocationIdentifier) {
        ProductOfProject product = getProduct(productIdentifier);
        boolean removed = product.getResourceDataWithAllocation().removeIf(a -> a.getId().equals(allocationIdentifier));
        if (!removed) {
            throw new RuntimeException("Allocation not found");
        }
        productRepository.save(product);
    }
}
