package ai.decompile.workspace.service;

import ai.decompile.common.exception.ConflictException;
import ai.decompile.common.exception.NotFoundException;
import ai.decompile.workspace.model.dto.ProjectRequest;
import ai.decompile.workspace.model.dto.ProjectResponse;
import ai.decompile.workspace.model.entity.Project;
import ai.decompile.workspace.model.repository.ProjectRepository;
import ai.decompile.workspace.model.specification.ProjectSpecification;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ProjectService {
  private final WorkspaceService workspaceService;
  private final ProjectRepository projectRepository;

  public List<ProjectResponse> getProjects(UUID workspaceId, String name) {
    Specification<Project> spec = ProjectSpecification.hasWorkspaceId(workspaceId);
    if (StringUtils.isNotBlank(name)) {
      spec = spec.and(ProjectSpecification.nameContains(name));
    }

    return projectRepository.findAll(spec).stream().map(ProjectResponse::from).toList();
  }

  public ProjectResponse getProjectById(UUID projectId) {
    return ProjectResponse.from(getProject(projectId));
  }

  public ProjectResponse createProject(UUID workspaceId, ProjectRequest request) {
    var workspace = workspaceService.getWorkspace(workspaceId);

    if (projectRepository.existsByNameIgnoreCaseAndWorkspace_Id(request.name(), workspaceId)) {
      throw new ConflictException(
          "A project with the name '" + request.name() + "' already exists in this workspace.");
    }

    var project =
        projectRepository.save(
            Project.builder()
                .name(request.name())
                .description(request.description())
                .workspace(workspace)
                .build());

    return ProjectResponse.from(project);
  }

  public ProjectResponse updateProject(UUID projectId, ProjectRequest request) {
    var project = getProject(projectId);

    if (!project.getName().equalsIgnoreCase(request.name())
        && projectRepository.existsByNameIgnoreCaseAndWorkspace_Id(
            request.name(), project.getWorkspace().getId())) {
      throw new ConflictException(
          "A project with the name '" + request.name() + "' already exists in this workspace.");
    }

    project.setName(request.name());
    project.setDescription(request.description());

    return ProjectResponse.from(projectRepository.save(project));
  }

  public void deleteProject(UUID projectId) {
    var project = getProject(projectId);
    projectRepository.delete(project);
  }

  Project getProject(UUID projectId) {
    return projectRepository
        .findById(projectId)
        .orElseThrow(() -> new NotFoundException("Project with id '" + projectId + "' not found"));
  }
}
