package gov.va.vinci.dart;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.context.SecurityContextHolder;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import gov.va.vinci.dart.common.SingletonShim;
import gov.va.vinci.dart.common.json.ErrorView;
import gov.va.vinci.dart.common.test.BusinessIntegrationTest;
import gov.va.vinci.dart.json.CreateActivityView;
import gov.va.vinci.dart.json.DataSourceIdView;
import gov.va.vinci.dart.json.DataSourceListView;
import gov.va.vinci.dart.json.DataSourceView;
import gov.va.vinci.dart.json.DocumentListView;
import gov.va.vinci.dart.json.DocumentTemplateListView;
import gov.va.vinci.dart.json.LocationIdListView;
import gov.va.vinci.dart.json.LocationIdView;
//import gov.va.vinci.dart.json.LocationListView;
import gov.va.vinci.dart.json.NewActivityView;
import gov.va.vinci.dart.json.PILocationView;
import gov.va.vinci.dart.json.PIParticipantInfoView;
import gov.va.vinci.dart.json.PIParticipantView;
import gov.va.vinci.dart.json.PrimaryInfoView;
import gov.va.vinci.dart.json.RequestDataSourcesView;
import gov.va.vinci.dart.json.RequestIdView;
import gov.va.vinci.dart.json.ReviewTemplateListView;
import gov.va.vinci.dart.json.ReviewTemplateView;
import gov.va.vinci.dart.json.SaveActivityView;
import gov.va.vinci.dart.json.SavePrimaryInfoView;
import gov.va.vinci.dart.json.SaveRequestDataSourcesView;
import gov.va.vinci.dart.json.SelectedReviewListView;
import gov.va.vinci.dart.json.SetupView;
import gov.va.vinci.dart.json.WorkflowIdView;
import gov.va.vinci.dart.service.DartObjectFactory;
import gov.va.vinci.dart.usr.CustomAuthentication;

public class TestReviewController extends BusinessIntegrationTest {

	@BeforeTest
	public void setup() {
		SingletonShim.getBean(DartObjectFactory.class);
		
		CustomAuthentication token = new CustomAuthentication("DNS", null, "password", "details", "principal");

		try {
			DartObjectFactory.getInstance().getUserManager().login(token);
			SecurityContextHolder.getContext().setAuthentication(token);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
//	@Test
	public void testOne() throws Exception {
		ReviewController rc = SingletonShim.getBean(ReviewController.class);
		
		RequestIdView view = new RequestIdView();
		view.setRequestId(5);
		view.setWorkflowId(0);
		
		Object obj = rc.listAllReviewTemplates( view );
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ReviewTemplateListView);
		
		ReviewTemplateListView rtList = (ReviewTemplateListView)obj;
		Assert.assertNotNull(rtList.getTemplates());
		Assert.assertTrue(rtList.getTemplates().size() > 0);
	}
	
	private SetupView createSetupView() throws Exception {
		ActivityController ac = SingletonShim.getBean(ActivityController.class);

//		HttpServletRequest req = new HttpServletRequestWrapper();
		HttpServletRequest req = null;
		
		Object obj = ac.setup(req);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof SetupView);
		SetupView sv = (SetupView) obj;

		return sv;
	}
	
	private NewActivityView createActivity(String officialName) throws Exception {
		ActivityController ac = SingletonShim.getBean(ActivityController.class);

		// create a new request
		CreateActivityView cav = new CreateActivityView();
		cav.setOfficialName(officialName);
		cav.setType("Dart Request");
		
		Object obj = ac.createActivity(cav);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof NewActivityView);
		
		NewActivityView nav = (NewActivityView) obj;
		
		System.err.println("activitiy id = " + nav.getActivityId());
		System.err.println("request id = " + nav.getRequestId());

		Assert.assertTrue(nav.getActivityId() > 0);
		Assert.assertTrue(nav.getRequestId() > 0);
		
		return nav;
	}
	
	private void testModifyActivity(int requestId, String officialName) {
		ActivityController ac = SingletonShim.getBean(ActivityController.class);

		// set the IRB number
		SaveActivityView sav = new SaveActivityView();
		sav.setOfficialName(officialName);
		sav.setShortName("This is a short name");
		sav.setRequestId(requestId);
		sav.setiRBApprovalNumber(String.valueOf(System.currentTimeMillis()));
		
		Object obj = ac.saveActivityInfo(sav); 

		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		ErrorView ev = (ErrorView)obj;
		Assert.assertEquals("OK", ev.getMessage().get("text"));
	}
	
	private LocationIdView getFirstLocation(int requestId, int userId) throws Exception {
		AdminController ac = SingletonShim.getBean(AdminController.class);

		// grab some location info
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(requestId);
		riv.setUserId(userId);
		
		Object obj = ac.getAllLocations(riv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof LocationIdListView);
		LocationIdListView llv = (LocationIdListView)obj;
		Assert.assertNotNull(llv.getLocations());
		Assert.assertTrue(llv.getLocations().size() > 0);
		LocationIdView locationIdView = llv.getLocations().get(0);
		Assert.assertNotNull(locationIdView);
		
		System.err.println("location name = " + locationIdView.getName());
		
		return locationIdView;
	}

	private void verifyParticipant(int requestId, int userId, String userName, LocationIdView locationIdView) throws Exception {
		ActivityController ac = SingletonShim.getBean(ActivityController.class);
		
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(requestId);
		riv.setUserId(userId);
		
		Object obj = ac.getPrimaryInfo(riv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof PrimaryInfoView);
		PrimaryInfoView piv = (PrimaryInfoView)obj;
		
		Assert.assertNotNull(piv.getInvestigators());
		Assert.assertNotNull(piv.getLocations());
		Assert.assertEquals(1, piv.getLocations().size());
		PILocationView pilv = piv.getLocations().get(0);
		Assert.assertNotNull(pilv);
		Assert.assertEquals(locationIdView.getName(), pilv.getLocation());
		Assert.assertEquals(userName, pilv.getPrimaryInvestigator());
		
		PIParticipantView pipv = piv.getInvestigators().get(locationIdView.getId());	//by location ID
		Assert.assertNotNull(pipv);
		Assert.assertNotNull(pipv.getParticipants());
		Assert.assertEquals(1, pipv.getParticipants().size());
		
		Assert.assertEquals(userName, pipv.getParticipants().get(0));
	}
	
	private void addParticipant(int requestId, String userLoginId, LocationIdView locationIdView) throws Exception {
		ActivityController ac = SingletonShim.getBean(ActivityController.class);

		// add a participant
		SavePrimaryInfoView spiv = new SavePrimaryInfoView();
		spiv.setRequestId(requestId);
		PrimaryInfoView piv = new PrimaryInfoView();
		spiv.setPrimaryInfo(piv);
		
		PIParticipantView pipv = new PIParticipantView();
		PIParticipantInfoView pipiv = new PIParticipantInfoView();
		pipv.getParticipants().add(pipiv);  // use the login user

		piv.getInvestigators().put(locationIdView.getId(),pipv);  // by location ID
		
		PILocationView pilv = new PILocationView();
		pilv.setLocation(locationIdView.getName());
		pilv.setLocationId(locationIdView.getId());
		pilv.setPrimary(true);
		pilv.setPrimaryInvestigator(userLoginId);
		piv.getLocations().add(pilv);
		
		Object obj = ac.savePrimaryInfo(spiv);

		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		ErrorView ev = (ErrorView)obj;
		Assert.assertEquals("OK", ev.getMessage().get("text"));
	}
	
	private int addDataSource(int requestId, String locationName) throws Exception {
		DataSourceController dsc = SingletonShim.getBean(DataSourceController.class);

		// add a data source
		Object obj = dsc.getAllDataSources(null);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DataSourceListView);
		DataSourceListView dslv = (DataSourceListView) obj;
		Assert.assertNotNull(dslv.getDataSources());
		Assert.assertTrue(dslv.getDataSources().size() > 0);
		DataSourceView dsv = dslv.getDataSources().get(0);
		
		SaveRequestDataSourcesView rdsv = new SaveRequestDataSourcesView();
		rdsv.setRequestId(requestId);
		rdsv.getDataSources().add(dsv.getId());
		rdsv.setLocationName(locationName);	//data source location name
		
		obj = dsc.saveRequestDataSources(rdsv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		ErrorView ev = (ErrorView)obj;
		Assert.assertEquals("OK", ev.getMessage().get("text"));
		
		return dsv.getId();
	}
	
	private void verifyOneDataSource(int requestId, int userId, int dataSourceId) throws Exception {
		DataSourceController dsc = SingletonShim.getBean(DataSourceController.class);

		RequestIdView riv = new RequestIdView();
		riv.setRequestId(requestId);
		riv.setUserId(userId);
		
		Object obj = dsc.getRequestDataSources(riv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof RequestDataSourcesView);
		RequestDataSourcesView rdsv = (RequestDataSourcesView)obj;

		Assert.assertNotNull(rdsv.getDataSources());
		Assert.assertEquals(rdsv.getDataSources().size(), 1);
		Assert.assertEquals(rdsv.getDataSources().get(0), new Integer(dataSourceId));
	}
	
	private int countDocumentTemplatesForDataSource(int dataSourceId) throws Exception {
		DataSourceController dc = SingletonShim.getBean(DataSourceController.class);
		
		DataSourceIdView dsiv = new DataSourceIdView();
		dsiv.setId(dataSourceId);
		
		Object obj = dc.listDocumentTemplatesByDataSource(dsiv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DocumentTemplateListView);
		DocumentTemplateListView rdsv = (DocumentTemplateListView)obj;
		
		return rdsv.getTemplates().size();
	}

	private void countDocuments(int requestId, int userId, int expectedCount) throws Exception {
		DocumentController dc = SingletonShim.getBean(DocumentController.class);
		
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(requestId);
		riv.setUserId(userId);
		
		Object obj = dc.listDocumentsByRequest(riv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DocumentListView);
		DocumentListView dlv = (DocumentListView)obj;
		
		int actualCount = dlv.getLocations().size() + dlv.getParticipants().size();
		System.err.println("locations = " + dlv.getLocations().size());
		System.err.println("participants = " + dlv.getParticipants().size());
		
		Assert.assertEquals(actualCount, expectedCount);
	}

	private void submitRequest(int requestId, int userId) throws Exception {
		RequestController rc = SingletonShim.getBean(RequestController.class);
		
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(requestId);
		riv.setUserId(userId);
		
		Object obj = rc.submitRequest(riv); 
		 
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		ErrorView ev = (ErrorView)obj;
		Assert.assertEquals("OK", ev.getMessage().get("text"));
	}
	
	private void createReviews(int requestId, int userId) throws Exception {
		ReviewController rc = SingletonShim.getBean(ReviewController.class);
		
		RequestIdView view = new RequestIdView();
		view.setRequestId(5);
		view.setWorkflowId(0);
		Object obj = rc.listAllReviewTemplates( view );

		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ReviewTemplateListView);
		ReviewTemplateListView rtlv = (ReviewTemplateListView)obj;

		Assert.assertNotNull(rtlv.getTemplates());
		Assert.assertTrue(rtlv.getTemplates().size() > 1);
		ReviewTemplateView rtv = rtlv.getTemplates().get(0);
		Assert.assertNotNull(rtv);
		
		SelectedReviewListView srlv = new SelectedReviewListView();
		srlv.setRequestId(requestId);
		srlv.getReviewTemplates().add(String.valueOf(rtv.getId()));
		
		obj = rc.selectReviews(srlv);
		
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		ErrorView ev = (ErrorView)obj;
		Assert.assertEquals("OK", ev.getMessage().get("text"));
	}
	
//	private void approveAllReviews(int requestId, int userId, String userLoginId) throws Exception {
//		ReviewController rc = SingletonShim.getBean(ReviewController.class);
//		
//		// have to cheat a bit here.  there's no controller API for this
////		DartRequest req = DartRequest.findById(requestId);
//		Request req = RequestController.retrieveRequest(requestId);
//		
//		System.err.println("reviews = " + req.getReviews()); 
//		
//		for (Review rev : req.getReviews()) {
//			ReviewIdView riv = new ReviewIdView();
//			riv.setReviewId(rev.getId());
//			riv.setUserId(userId);
//			
//			Object obj = rc.approveReview(riv);
//			
//			Assert.assertNotNull(obj);
//			Assert.assertTrue(obj instanceof ErrorView);
//			ErrorView ev = (ErrorView)obj;
//			Assert.assertEquals("OK", ev.getMessage().get("text"));
//		}
//	}
	
//	private void finalApproveRequest(int requestId, int userId, String userLoginId) throws Exception {
//		RequestController rc = SingletonShim.getBean(RequestController.class);
//		
//		RequestIdView riv = new RequestIdView();
//		riv.setRequestId(requestId);
//		riv.setUserId(userId);
//		
//		Object obj = rc.approveRequest(riv);
//		
//		Assert.assertNotNull(obj);
//		Assert.assertTrue(obj instanceof ErrorView);
//		ErrorView ev = (ErrorView)obj;
//		Assert.assertEquals("OK", ev.getMessage().get("text"));
//	}
	
//	private void createAmendment(int requestId, int userId, String userLoginId) {
//		RequestController rc = SingletonShim.getBean(RequestController.class);
//		
//		AmendmentView riv = new AmendmentView();
//		riv.setRequestId(requestId);
//		
//		Object obj = rc.createAmendment(riv);
//		
//		Assert.assertNotNull(obj);
//		Assert.assertTrue(obj instanceof RequestIdView);
//		RequestIdView ev = (RequestIdView)obj;
//		Assert.assertTrue(ev.getRequestId() > 0);
//	}
	
//	@Test
	public void testTwo() throws Exception {

		SetupView sv = createSetupView();

		String officialName = "Test Request " + System.currentTimeMillis() + " Official Name";
		NewActivityView nav = createActivity(officialName);
		
		testModifyActivity(nav.getRequestId(), officialName);
		
		LocationIdView locationIdView = getFirstLocation(nav.getRequestId(), sv.getUserId());
		
		addParticipant(nav.getRequestId(), sv.getUserLoginId(), locationIdView);
		verifyParticipant(nav.getRequestId(), sv.getUserId(), sv.getUserLoginId(), locationIdView);
		
		int dataSourceId = addDataSource(nav.getRequestId(), locationIdView.getName());
		verifyOneDataSource(nav.getRequestId(), sv.getUserId(), dataSourceId);
		
//		System.err.println("dataSourceId = " + dataSourceId);
		int count = countDocumentTemplatesForDataSource(dataSourceId);
//		System.err.println("count = " + count);
		
		countDocuments(nav.getRequestId(), sv.getUserId(), count);
		
		// you really should upload documents here
		
		// you realy should test validity of the request here
		
		// I don't care if the request won't pass validation.  submit it!
		submitRequest(nav.getRequestId(), sv.getUserId());
		
		// Irma wants to create reviews
		createReviews(nav.getRequestId(), sv.getUserId());
		
		// approve the review
//		approveAllReviews(nav.getRequestId(), sv.getUserId(), sv.getUserLoginId());
		
		// finally approve the request
//		finalApproveRequest(nav.getRequestId(), sv.getUserId(), sv.getUserLoginId());
		
		// create an amendment
//		createAmendment(nav.getRequestId(), sv.getUserId(), sv.getUserLoginId());

	}
}
