package com.nisum.mytime.service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.nisum.mytime.configuration.DbConnection;
import com.nisum.mytime.exception.handler.MyTimeException;
import com.nisum.mytime.model.AttendenceData;
import com.nisum.mytime.model.ProjectTeamMate;
import com.nisum.mytime.repository.ProjectTeamMatesRepo;
import com.nisum.mytime.utils.MyTimeLogger;
import com.nisum.mytime.utils.MyTimeUtils;

@Service
public class AttendanceServiceImpl implements AttendanceService {

	@Autowired
	DbConnection dbConnection;
	
	@Autowired
	ProjectTeamMatesRepo projectTeamMatesRepo;

	@Override
	public List<AttendenceData> getAttendanciesReport(String reportDate, String shift) throws MyTimeException, SQLException {
		long start_ms = System.currentTimeMillis();
		List<AttendenceData> listOfEmployees = getEmpsAttendenceByShiftWise(reportDate,shift);
		MyTimeLogger.getInstance().info("Time Taken for " + (System.currentTimeMillis() - start_ms));
		return listOfEmployees;
	}
	
	private List<AttendenceData> getEmpsAttendenceByShiftWise(String reportDate,String shift) throws MyTimeException {
		List<AttendenceData> listOfEmployees = new ArrayList<AttendenceData>();
		
		Optional<List<ProjectTeamMate>> list = findEmpIdsByShiftWise(shift);
		
		if(list.isPresent()) {
			List<String> empIdList = list.get().stream()
	                .map(ProjectTeamMate::getEmployeeId)
	                .collect(Collectors.toList());
			
			if(null != empIdList && empIdList.size() == MyTimeUtils.INT_ZERO)		{
				return listOfEmployees;
			}
			String query = buildSqlQuery(reportDate,empIdList.toString().substring(1, empIdList.toString().length()-1),MyTimeUtils.PRESENT);
			listOfEmployees.addAll(getAttendenceData(query));
			
			List<String>  presentList = listOfEmployees.stream().map(AttendenceData :: getEmployeeId).collect(Collectors.toList());
			empIdList.removeAll(presentList);
			
			if(empIdList.size()>0) {			
				query = buildSqlQuery(reportDate, empIdList.toString().substring(1, empIdList.toString().length()-1), MyTimeUtils.ABSENT);
				listOfEmployees .addAll(getAttendenceData(query));
			}
		}
		return listOfEmployees;
	}
	
	private Optional<List<ProjectTeamMate>> findEmpIdsByShiftWise(String shift) {
		Optional<List<ProjectTeamMate>> list = null;
		
		if(MyTimeUtils.ALL.equalsIgnoreCase(shift)) {
			list = projectTeamMatesRepo.findByActiveAndShiftLikeOrderByEmployeeIdDesc( true, MyTimeUtils.SHIFT);
		}else {
			list = projectTeamMatesRepo.findByActiveAndShiftLikeOrderByEmployeeIdDesc( true,shift);
		}
		return list;
	}
	
	private String buildSqlQuery(String reportDate, String empIdsStr,String type) {
		String query = null;
		if(MyTimeUtils.PRESENT.equals(type)) {
			query = MyTimeUtils.PRESENT_QUERY
				      .replace("<TYPE>", type)
				      .replace("<REPORTDATE>", reportDate)
				      .replace("<EMPIDS>",empIdsStr);
		}else {
			query = MyTimeUtils.ABSENT_QUERY
					.replace("<ABSENTLIST>", empIdsStr);
		}
		return query;
	}
	
	private List<AttendenceData> getAttendenceData(String query) throws MyTimeException {
		List<AttendenceData> listOfEmployees = null;
		
		try (Connection connection = dbConnection.getDBConnection();
				Statement statement = connection.createStatement();
				ResultSet resultSet = statement.executeQuery(query)) {
			
			AttendenceData attendData = null;
			listOfEmployees = new ArrayList<AttendenceData>();
			
			while (resultSet.next()) {
				attendData = new AttendenceData();
				attendData.setEmployeeId(resultSet.getString("EmployeeCode"));
				attendData.setEmployeeName(resultSet.getString("FirstName"));
				attendData.setPresent(resultSet.getString("AttStatus"));
				listOfEmployees.add(attendData);
				attendData = null;
			}
			
		}catch (Exception e) {
			MyTimeLogger.getInstance().error("Exception occured due to : ", e);
			throw new MyTimeException(e.getMessage());
		}
		return listOfEmployees;
	}
	
}


