package org.exoplatform.cs.injector;

import java.util.HashSet;
import java.util.Set;


import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.RuntimeDelegate;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.component.RequestLifeCycle;
import org.exoplatform.cs.dto.BasicEntityDTO;
import org.exoplatform.cs.dto.EnvironmentDTO;
import org.exoplatform.cs.dto.IssueSeverity;
import org.exoplatform.cs.dto.IssueType;
import org.exoplatform.cs.dto.SpaceDTO;
import org.exoplatform.cs.dto.TicketDTO;
import org.exoplatform.cs.service.CSSpaceService;
import org.exoplatform.cs.service.EnvironmentService;
import org.exoplatform.cs.service.TicketService;
import org.exoplatform.cs.service.TicketUpdatesService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.organization.impl.UserImpl;
import org.exoplatform.services.rest.impl.RuntimeDelegateImpl;
import org.exoplatform.services.rest.resource.ResourceContainer;
import org.exoplatform.task.domain.Priority;

/**
 * Created by eXo Platform SAS.
 *
 * @author Ali Hamdi
 * @since 11/08/17 15:48
 */
@Path("csinjector")
public class CSInjector implements ResourceContainer {
  private static final Log LOG = ExoLogger.getLogger(CSInjector.class);
  private static final CacheControl cc;

  private CSSpaceService spaceService;
  private TicketService ticketService;
  private EnvironmentService environmentService;
  private OrganizationService organizationService;

  static {
    RuntimeDelegate.setInstance(new RuntimeDelegateImpl());
    cc = new CacheControl();
    cc.setNoCache(true);
    cc.setNoStore(true);
  }

  public CSInjector(CSSpaceService spaceService, TicketService ticketService, EnvironmentService environmentService, OrganizationService organizationService) {
    this.spaceService = spaceService;
    this.ticketService = ticketService;
    this.environmentService = environmentService;
    this.organizationService = organizationService;
  }

  @GET
  @RolesAllowed("administrators")
  @Path("createspaces/spaces")
  @Produces(MediaType.TEXT_PLAIN)
  public Response getUpdates(@Context UriInfo uriInfo,
                             @QueryParam("prefix") String spacePrefix,
                             @QueryParam("spacecount") String spaceCount,
                             @QueryParam("ticketperspace") String ticketPerSpace) {
    int spacesCount, ticketsPerSpace;
    User customerUser = new UserImpl();
    BasicEntityDTO customer = new BasicEntityDTO("bugs", "bugs");
    BasicEntityDTO support = new BasicEntityDTO("support", "support");
    BasicEntityDTO spaceMembersgroup = new BasicEntityDTO("support-team", "support-team");
    BasicEntityDTO spaceManagersGroup = new BasicEntityDTO("gss", "gss");
    try {
      spacesCount = Integer.parseInt(spaceCount);
    } catch (NumberFormatException nfe) {
      spacesCount = 10;
      LOG.info("We will create 10 customer spaces ");
    }
    try {
      ticketsPerSpace = Integer.parseInt(spaceCount);
    } catch (NumberFormatException nfe) {
      ticketsPerSpace = 10;
      LOG.info("We will create 10 tickets per space ");
    }
    RequestLifeCycle.begin(PortalContainer.getInstance());
    try {
      customerUser = organizationService.getUserHandler().findUserByName(customer.computeId());
    } catch (Exception e) {
      LOG.error("User {} not found",customer.computeId(),e);
      return Response.serverError().cacheControl(cc).build();
    } finally {
      RequestLifeCycle.end();
    }


    for (int i = 0; i < spacesCount; i++) {
      try {
        String spaceName = spacePrefix + i;
        SpaceDTO space = new SpaceDTO();
        space.setDescription("Description for space" + spaceName);
        space.setInvitedMembersGroupId(spaceMembersgroup);
        space.setLimitTicketsNumber(1000);
        space.setManagersGroupId(spaceManagersGroup);
        Set<BasicEntityDTO> members = new HashSet<>();
        members.add(customer);
        space.setMembers(members);
        space.setName(spaceName);
        space.setOwner(support.computeId());
        space.setTagPrefix(spacePrefix + i);
        space.setTaskDefaultAssignee(support);
        space.setTaskPriority(Priority.NONE);
        RequestLifeCycle.begin(PortalContainer.getInstance());
        try {
          space = spaceService.saveSpace(space);
        } catch (Exception e) {
          LOG.error("Error creating space {}",space.getName(),e);
          return Response.serverError().cacheControl(cc).build();
        } finally {
          RequestLifeCycle.end();
        }
        LOG.info("Space {} created!", space.getName());

        EnvironmentDTO environment = new EnvironmentDTO();
        environment.setName("PROD");
        environment.setTypeOtherName("Production");
        environment.setProductVersion("5.0.0");
        environment.setDefaultEnvironment(true);
        environment.setSpaceGroupId(space.getGroupId());

        environment = environmentService.saveEnvironment(environment);
        LOG.info("Environment {} created for space {} !", environment.getName(), space.getName());

        for (int counter = 0; counter < ticketsPerSpace; counter++) {
          TicketDTO ticket = new TicketDTO();
          ticket.setAssignee(support.computeId());
          ticket.setDescription("Description for ticket " + counter + "in space " + space.getName());
          ticket.setEnvironmentId(environment.getId());
          ticket.setEnvironmentName(environment.getName());
          ticket.setSeverity(IssueSeverity.SEVERITY_2);
          ticket.setTitle("Title of ticket " + counter + "in space " + space.getName());
          ticket.setSpaceGroupId(space.getGroupId());
          ticket.setStatus("Open");
          ticket.setType(IssueType.INCIDENT);
          ticketService.createTicket(ticket, customerUser);
          LOG.info("Ticket {} created in space {}!", ticket.getTitle(), space.getName());
        }

      } catch (Exception e) {
        LOG.error("Could not create space {}", spacePrefix + i, e);
        return Response.serverError().cacheControl(cc).build();
      }
    }
    return Response.ok("Created " + spacesCount + " spaces with " + ticketPerSpace + " tickets in each.", MediaType.TEXT_PLAIN).cacheControl(cc).build();

  }
}
