package com.ikon.projectmanagement.service.impl;

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

import com.ikon.projectmanagement.dto.request.RiskCreateRequestDto;
import com.ikon.projectmanagement.dto.response.RiskResponseDto;
import com.ikon.projectmanagement.entity.Risks;
import com.ikon.projectmanagement.mapper.RiskMapper;
import com.ikon.projectmanagement.repository.ProjectRepository;
import com.ikon.projectmanagement.repository.RiskRepository;
import com.ikon.projectmanagement.service.RiskService;
import com.ikon.webservice.WebService;

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

import org.apache.kafka.common.errors.ResourceNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Slf4j
public class RiskServiceImpl extends WebService implements RiskService {

    private final RiskRepository riskRepository;
    private final ProjectRepository projectRepository;
    private final RiskMapper riskMapper;

    @Override
    @Transactional
    public RiskResponseDto createRisk(RiskCreateRequestDto riskCreateRequestDto) {

        log.info("Creating risk for project: {}", riskCreateRequestDto.getProjectIdentifier());

      //  UUID projectId = UUID.fromString(riskCreateRequestDto.getProjectIdentifier());

        UUID projectId = riskCreateRequestDto.getProjectIdentifier();

        projectRepository.findByProjectIdentifier(projectId)
                .orElseThrow(() -> new NoSuchElementException(
                        "Project not found with identifier: " + riskCreateRequestDto.getProjectIdentifier()));

        Risks risk = riskMapper.toEntity(riskCreateRequestDto);
        // No more risk.setProject(project) — just set the UUID directly
       // risk.setProjectIdentifier(projectId);

       // Risks savedRisk = riskRepository.saveAndFlush(risk);


        Risks savedRisk = riskRepository.save(risk);

        return riskMapper.toResponse(savedRisk);
    }

    @Override
    public List<RiskResponseDto> getAllRisks() {

        log.info("Fetching all risks");

        return riskRepository.findAll()
                .stream()
                .map(riskMapper::toResponse)
                .toList();
    }

    @Override
    public RiskResponseDto getRiskById(UUID riskIdentifier) {

        log.info("Fetching risk with identifier: {}", riskIdentifier);

        Risks risk = riskRepository.findById(riskIdentifier)
                .orElseThrow(() -> new NoSuchElementException(
                        "Risk not found with identifier: " + riskIdentifier));

        return riskMapper.toResponse(risk);
    }

    @Override
    @Transactional
    public RiskResponseDto updateRisk(UUID riskIdentifier, RiskCreateRequestDto riskCreateRequestDto) {

        log.info("Updating risk with identifier: {}", riskIdentifier);

        Risks existingRisk = riskRepository.findById(riskIdentifier)
                .orElseThrow(() -> new ResourceNotFoundException(
                        "Risk not found with identifier: " + riskIdentifier));

        riskMapper.updateEntityFromDto(riskCreateRequestDto, existingRisk);

        Risks updatedRisk = riskRepository.save(existingRisk);

        log.info("Risk updated successfully with identifier: {}", riskIdentifier);

        return riskMapper.toResponse(updatedRisk);
    }

    @Override
    public List<RiskResponseDto> getRisksByProject(String projectIdentifier) {

        log.info("Fetching all risks for project: {}", projectIdentifier);

        UUID projectId = UUID.fromString(projectIdentifier);

        // Validate project exists
        projectRepository.findByProjectIdentifier(projectId)
                .orElseThrow(() -> new NoSuchElementException(
                        "Project not found with identifier: " + projectIdentifier));

        // Updated to use direct field query instead of relationship navigation
        return riskRepository.findByProjectIdentifier(projectId)
                .stream()
                .map(riskMapper::toResponse)
                .toList();
    }
}