package com.atlassian.bitbucket.internal.importer.rest;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.internal.importer.*;
import com.atlassian.bitbucket.internal.importer.repository.OwnerImportRequest;
import com.atlassian.bitbucket.internal.importer.repository.RepositoriesImportRequest;
import com.atlassian.bitbucket.internal.importer.repository.RepositoryImportService;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.rest.util.ResponseFactory;
import com.atlassian.bitbucket.rest.util.RestUtils;
import com.sun.jersey.spi.resource.Singleton;

import javax.validation.Validator;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;

import static com.atlassian.bitbucket.rest.util.ResourcePatterns.PROJECT_URI;
import static com.atlassian.bitbucket.util.ValidationUtils.validate;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;

@Path(PROJECT_URI + "/import")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({RestUtils.APPLICATION_JSON_UTF8})
@Singleton
public class RepositoryImportResource {

    private final I18nService i18nService;
    private final RepositoryImportService repositoryImportService;
    private final ResourceHelper resourceHelper;
    private final Validator validator;

    public RepositoryImportResource(I18nService i18nService,
                                    RepositoryImportService repositoryImportService,
                                    ResourceHelper resourceHelper,
                                    Validator validator) {
        this.i18nService = i18nService;
        this.repositoryImportService = repositoryImportService;
        this.resourceHelper = resourceHelper;
        this.validator = validator;
    }

    @Path("/job/{jobId}")
    @GET
    public Response getImportJob(@PathParam("jobId") long jobId) {
        return repositoryImportService.getImportJob(jobId)
                .map(RestImportJob::new)
                .map(importJob -> ResponseFactory.ok(importJob).build())
                .orElse(ResponseFactory.notFound().build());
    }

    @Path("/owner-repos")
    @POST
    public Response importAllRepositoriesForOwner(@Context Project project,
                                                  RestOwnerImportRequest request) {
        List<String> errors = resourceHelper.validate(request);
        if (!errors.isEmpty()) {
            return resourceHelper.restRequestError(errors);
        }
        ExternalOwner owner = request.getOwner();
        if (owner != null) {
            validate(validator, owner);
        }

        Credential credential = resourceHelper.credential(request);
        ExternalSource source = resourceHelper.source(request);
        OwnerImportRequest importRequest = new OwnerImportRequest.Builder(credential, project, source)
                .owner(owner)
                .build();

        return Response.ok(new RestImportJob(repositoryImportService.importRepositoriesForOwner(importRequest))).build();
    }

    @Path("/repos")
    @POST
    public Response importRepositories(@Context Project project,
                                       RestRepositoriesImportRequest request) {
        List<ExternalRepository> externalRepositories = request.getExternalRepositories();
        if (externalRepositories.isEmpty()) {
            return ResponseFactory.error(BAD_REQUEST, "externalRepositories",
                    i18nService.getMessage("bitbucket.importer.rest.import.repository.empty.externalRepositories")).build();
        }

        RepositoriesImportRequest.Builder importRequestBuilder = new RepositoriesImportRequest.Builder(project)
                .externalRepositories(externalRepositories);

        RestCredential restCredential = request.getCredential();
        if (restCredential != null) {
            List<String> errors = resourceHelper.validateCredential(restCredential);
            if (!errors.isEmpty()) {
                return resourceHelper.restRequestError(errors);
            }
            importRequestBuilder.credential(new Credential.Builder(restCredential.getUsername(), restCredential.getPassword()).build());
        }

        RestImportJob importJob = new RestImportJob(repositoryImportService.importRepositories(importRequestBuilder.build()));
        return Response.ok(importJob).build();
    }
}