package com.nisum.mytime.service;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
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.EmpLoginData;
import com.nisum.mytime.model.ProjectTeamMate;
import com.nisum.mytime.repository.ProjectTeamMatesRepo;
import com.nisum.mytime.utils.CommomUtil;
import com.nisum.mytime.utils.MyTimeLogger;
import com.nisum.mytime.utils.MyTimeUtils;
import com.nisum.mytime.utils.PdfReportGenerator;

@Service
public class AttendanceServiceImpl implements AttendanceService {

	@Autowired
	private EmployeeDataService employeeDataBaseService;
	
	@Autowired
	DbConnection dbConnection;
	
	@Autowired
	ProjectTeamMatesRepo projectTeamMatesRepo;
	
	@Autowired
    private PdfReportGenerator pdfReportGenerator;

	@Override
	public List<AttendenceData> getAttendanciesReport(String reportDate, String shift) throws MyTimeException {
		long start_ms = System.currentTimeMillis();
		String reportDateInReqDateFormat = reportDate.replace("-", "/");
		List<AttendenceData> listOfEmployees = getEmpsAttendenceByShiftWise(reportDateInReqDateFormat, shift);
		MyTimeLogger.getInstance().info("Time Taken for " + (System.currentTimeMillis() - start_ms));
		return listOfEmployees;
	}

	@Override
    public List<EmpLoginData> employeeLoginReportBasedOnDateTime(long id, String fromDate, String toDate,String fromTime,String toTime) throws MyTimeException, ParseException {
		String timeFrom= CommomUtil.convertTimeFormat(fromTime); 
	    String timeTo= CommomUtil.convertTimeFormat(toTime);
		String nextDayDate = CommomUtil.getNextDay(fromDate,fromTime,toTime);  
        return employeeDataBaseService.fetchEmployeeLoginsBasedOnDatesTime(id, fromDate, nextDayDate, toDate, timeFrom, timeTo);
    }
	
    @Override
    public List generatePdfReport(long id, String fromDate, String toDate, String fromTime, String toTime)
            throws MyTimeException { 
        return pdfReportGenerator.generateEmployeeReport(id, fromDate, toDate);
    }
	
	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)		{
				String query = buildSqlQuery(reportDate,empIdList.toString().substring(1, empIdList.toString().length()-1), MyTimeUtils.PRESENT);
				listOfEmployees.addAll(getAttendenceData(query, MyTimeUtils.PRESENT));
				
				List<String>  presentList = listOfEmployees.stream().map(AttendenceData :: getEmployeeId).collect(Collectors.toList());
				empIdList.removeAll(presentList);
				if(empIdList.size() > MyTimeUtils.INT_ZERO) {			
					query = buildSqlQuery(reportDate, empIdList.toString().substring(1, empIdList.toString().length()-1), MyTimeUtils.ABSENT);
					listOfEmployees .addAll(getAttendenceData(query, MyTimeUtils.ABSENT));
				}
			}
		}
		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("<REPORTDATE>", reportDate)
				      .replace("<EMPIDS>",empIdsStr);
		}else {
			query = MyTimeUtils.ABSENT_QUERY.replace("<ABSENTLIST>", empIdsStr);
		}
		return query;
	}
	
	private List<AttendenceData> getAttendenceData(String query, String type) 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(type);
				listOfEmployees.add(attendData);
				attendData = null;
			}
		} catch (Exception e) {
			MyTimeLogger.getInstance().error("Exception occured due to : ", e);
			throw new MyTimeException(e.getMessage());
		}
		return listOfEmployees;
	}
}


