package gov.va.vinci.dart.rest;

import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.common.json.ErrorView;
import gov.va.vinci.dart.DartController;
import gov.va.vinci.dart.RequestController;
import gov.va.vinci.dart.biz.Person;
import gov.va.vinci.dart.biz.Request;
import gov.va.vinci.dart.biz.RequestSummary;
import gov.va.vinci.dart.biz.Review;
import gov.va.vinci.dart.biz.Role;
import gov.va.vinci.dart.db.util.HibernateSessionManager;
import gov.va.vinci.dart.json.RequestDetailsView;
import gov.va.vinci.dart.json.RequestListView;
import gov.va.vinci.dart.json.ReviewStatusListView;
import gov.va.vinci.dart.json.atom.AtomLinkFactory;
import gov.va.vinci.dart.json.builder.RequestListViewBuilder;
import gov.va.vinci.dart.json.builder.RequestViewBuilder;
import gov.va.vinci.dart.json.builder.ReviewStatusListViewBuilder;
import gov.va.vinci.dart.usr.UserPreferences;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class RequestResource extends DartController {

	private static Log log = LogFactory.getLog(RequestResource.class);
	
	@Autowired
	private AtomLinkFactory linkFactory;
	
	@Autowired
	private RequestListViewBuilder requestListViewBuilder;
	
	@Autowired
	private RequestViewBuilder requestViewBuilder;
	
	@RequestMapping(value = "/requests", method = RequestMethod.GET)
	@ResponseBody
	public Object getRequestQuery(final HttpServletRequest request) throws Exception {
		
		log.debug("getRequest"); 
		
		String queryString = request.getQueryString();
		RestQuery q = new RestQuery(queryString);
		String term = q.getTerm("trackingNumber");
		String participant = q.getTerm("participant");

		try {
			HibernateSessionManager.start();

			UserPreferences prefs = getUserPreferences();
			
			Person person = Person.findById(prefs.getUserId());
			
			Role.initialize();

			if( person != null && person.hasRole(Role.SUPER_USER) == false ) {
				return new ErrorView("Error: User does not have permission to perform this action.");
			}


			// query by tracking number
			if (StringUtils.isNotEmpty(term)) {
				List<RequestSummary> summaryList = Request.listByTrackingNumber(term);
				
				return requestListViewBuilder.build(summaryList, true);
			}
			else if (StringUtils.isNotEmpty(participant)) {
				Person pers = Person.findByName(participant);
				return requestListViewBuilder.build( Request.listAllRequestSummaryByParticipant(participant), pers, true );	
			}
			else {
				// return all requests.
				return requestListViewBuilder.build( Request.listAllRequestSummary(), true );	
			}
		} catch (Exception e) {
			log.error("Error retrieving request data.", e);
			HibernateSessionManager.rollback();
			throw e;
		} finally {
			HibernateSessionManager.close();
		}
	}

	@RequestMapping(value = "/requests/{requestId}", method = RequestMethod.GET)
	@ResponseBody
	public Object getRequestById(@PathVariable final int requestId) throws Exception {
		
		log.debug("getRequest"); 
		
		try {
			HibernateSessionManager.start();

			UserPreferences prefs = getUserPreferences();
			
			Request req = null;
			try {
				req = RequestController.retrieveRequest(requestId);
		
				if (req == null) {
					throw new ObjectNotFoundException();
				}
			} catch (ObjectNotFoundException e) {
				log.error("Error loading request " + requestId, e);
				throw e;
			}
			
			Person person = null;
			try {
				person = Person.findById(prefs.getUserId());
			} catch (ObjectNotFoundException e) {
				throw new ObjectNotFoundException("Cannot find person with id: " + prefs.getUserId());
			}

			Role.initialize();

			if( person != null && person.hasRole(Role.SUPER_USER) == false ) {
				return new ErrorView("Error: User does not have permission to perform this action.");
			}

			return (RequestController.populateRequestDetailsView(null, req, person));

		} catch (Exception e) {
			log.error("Error retrieving request data.", e);
			HibernateSessionManager.rollback();
			throw e;
		} finally {
			HibernateSessionManager.close();
		}
	}

	@RequestMapping(value = "/requests/{requestId}/reviews", method = RequestMethod.GET)
	@ResponseBody
	public Object getReviewsByRequestId(@PathVariable final int requestId) throws Exception {
		
		log.debug("getReviewsByRequestId"); 
		
		try {
			HibernateSessionManager.start();

			UserPreferences prefs = getUserPreferences();
			
			Person person = null;
			try {
				person = Person.findById(prefs.getUserId());
			} catch (ObjectNotFoundException e) {
				throw new ObjectNotFoundException("Cannot find person with id: " + prefs.getUserId());
			}

			Role.initialize();

			if( person != null && person.hasRole(Role.SUPER_USER) == false ) {
				return new ErrorView("Error: User does not have permission to perform this action.");
			}
			
			Request req = RequestController.retrieveRequest(requestId);
			if (req == null) {
				return new ErrorView("Error retrieving request: " + requestId);
			}

			List<Review> reviewList = Review.listByRequestId(requestId);

			return new ReviewStatusListViewBuilder().build(null, req, reviewList);
			
		} catch (Exception e) {
			log.error("Error retrieving review data.", e);
			HibernateSessionManager.rollback();
			throw e;
		} finally {
			HibernateSessionManager.close();
		}
	}

}
