Subversion Repositories SmartDukaan

Rev

Rev 35507 | Rev 35548 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.spice.profitmandi.web.controller;

import com.google.gson.Gson;
import com.mongodb.DBObject;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.*;
import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.common.util.FormattingUtils;
import com.spice.profitmandi.common.web.util.ResponseSender;
import com.spice.profitmandi.dao.entity.auth.AuthUser;
import com.spice.profitmandi.dao.entity.catalog.BrandCatalog;
import com.spice.profitmandi.dao.entity.fofo.PartnerDailyInvestment;
import com.spice.profitmandi.dao.entity.user.*;
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
import com.spice.profitmandi.dao.enumuration.dtr.CommunicationType;
import com.spice.profitmandi.dao.enumuration.dtr.LeadSource;
import com.spice.profitmandi.dao.enumuration.dtr.LeadStatus;
import com.spice.profitmandi.dao.model.*;
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
import com.spice.profitmandi.dao.repository.auth.PartnerCollectionPlanRepository;
import com.spice.profitmandi.dao.repository.auth.PartnerCollectionRemarkRepository;
import com.spice.profitmandi.dao.repository.cs.CsService;
import com.spice.profitmandi.dao.repository.cs.PositionRepository;
import com.spice.profitmandi.dao.repository.dtr.*;
import com.spice.profitmandi.dao.repository.fofo.PartnerDailyInvestmentRepository;
import com.spice.profitmandi.dao.repository.fofo.RbmRatingRepository;
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
import com.spice.profitmandi.dao.repository.transaction.UserWalletRepository;
import com.spice.profitmandi.service.AuthService;
import com.spice.profitmandi.service.PartnerCollectionService;
import com.spice.profitmandi.service.RbmTargetService;
import com.spice.profitmandi.service.catalog.BrandsService;
import com.spice.profitmandi.service.order.OrderService;
import com.spice.profitmandi.service.user.RetailerService;
import com.spice.profitmandi.web.model.LoginDetails;
import com.spice.profitmandi.web.util.CookiesProcessor;
import com.spice.profitmandi.web.util.MVCResponseSender;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

@Controller
@Transactional(rollbackFor = Throwable.class)
public class LeadController {
    private static final Logger LOGGER = LogManager.getLogger(LeadController.class);

    @Autowired
    private LeadRepository leadRepository;

    @Autowired
    private LeadActivityRepository leadActivityRepository;

    @Autowired
    private StateRepository stateRepository;

    @Autowired
    private AuthService authService;

    @Autowired
    private AuthRepository authRepository;

    @Autowired
    private Gson gson;

    @Autowired
    private CookiesProcessor cookiesProcessor;

    @Autowired
    PositionRepository positionRepository;

    @Autowired
    private MVCResponseSender mvcResponseSender;

    @Autowired
    private PartnerCollectionPlanRepository partnerCollectionPlanRepository;

    @Autowired
    private CsService csService;

    @Autowired
    private FofoStoreRepository fofoStoreRepository;

    @Autowired
    private PartnerCollectionService partnerCollectionService;

    @Autowired
    private RetailerService retailerService;

    @Autowired
    private PartnerCollectionRemarkRepository partnerCollectionRemarkRepository;

    @Autowired
    private PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;

    @Autowired
    private UserWalletRepository userWalletRepository;

    @Autowired
    private FranchiseeVisitRepository franchiseeVisitRepository;

    @Autowired
    private FranchiseeActivityRepository franchiseeActivityRepository;

    @Autowired
    private VisitRequestRepository visitRequestRepository;

    @Autowired
    private LeadBrandRepository leadBrandRepository;

    @Autowired
    private LeadDetailRepository leadDetailRepository;

    @Autowired
    private Mongo mongoClient;

    @Autowired
    private ResponseSender<?> responseSender;

    @Autowired
    private BrandsService brandsService;
    @Autowired
    OrderService orderService;


    @Autowired
    private RbmRatingRepository rbmRatingRepository;

    List<LeadStatus> status = Arrays.asList(LeadStatus.notInterested, LeadStatus.finalized);

    @RequestMapping(value = "/getOpenLead", method = RequestMethod.GET)
    public String getOpenLead(HttpServletRequest request, @RequestParam(name = "leadStatus", required = false, defaultValue = "All") List<LeadStatus> leadStatus, @RequestParam(name = "color", required = false, defaultValue = "All") List<String> color, @RequestParam(name = "leadDate", required = false, defaultValue = "") LocalDate leadDate, Model model) throws Exception {

        LocalDateTime leadCreatedDateTime = null;
        if (leadDate != null) {
            leadCreatedDateTime = leadDate.atStartOfDay();
        }
        LOGGER.info("localDateTime" + leadCreatedDateTime);

        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        String emailId = loginDetails.getEmailId();
        AuthUser authUser = authRepository.selectByEmailOrMobile(emailId);

        boolean isPositionSales = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_SALES);

        if (leadStatus.contains(LeadStatus.All)) {

            leadStatus.add(LeadStatus.pending);
            leadStatus.add(LeadStatus.notInterested);
            leadStatus.add(LeadStatus.finalized);
        }

        if (color.contains("All")) {
            color.add("yellow");
            color.add("green");
        }

        List<Lead> leads = new ArrayList<>();

        model.addAttribute("colors", color);

        Map<Integer, List<LeadActivity>> leadActivityMap = new HashMap<>();

        List<Integer> authUserIds = null;

        LOGGER.info("color111" + color);
        List<Lead> leadFollowUp = new ArrayList<>();
        if (isPositionSales) {
            authUserIds = authService.getAllReportees(authUser.getId());
            authUserIds.add(authUser.getId());
            LOGGER.info("authIds" + authUserIds);

            LOGGER.info("leadStatus" + leadStatus);

            if (leadCreatedDateTime == null) {

                if (!leadStatus.contains(LeadStatus.followUp)) {

                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestampAndAuthIds(leadStatus, authUserIds, color, LocalDateTime.now().minusMonths(1));
                }

                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
                    leads.addAll(leadFollowUp);
                }

            } else {

                if (!leadStatus.contains(LeadStatus.followUp)) {

                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestampAndAuthIds(leadStatus, authUserIds, color, leadCreatedDateTime);
                }

                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {

                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);

                    leads.addAll(leadFollowUp);

                }

            }

        } else {

            if (leadCreatedDateTime == null) {
                if (!leadStatus.contains(LeadStatus.followUp)) {

                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestamp(leadStatus, color, LocalDateTime.now().minusMonths(1));
                }
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {

                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);

                    leads.addAll(leadFollowUp);
                }
                LOGGER.info("leadlocalDateTime1" + leads);

            } else {
                if (!leadStatus.contains(LeadStatus.followUp)) {

                    LocalDateTime today = LocalDate.now().atStartOfDay();

                    int OneYearsAgoYear = today.minusYears(1).getYear();

                    LocalDateTime endLocalDate;

                    if (leadCreatedDateTime.getYear() < OneYearsAgoYear) {
                        // End date = last day of created year (31 Dec 23:59:59)
                        endLocalDate = leadCreatedDateTime
                                .withMonth(12)
                                .withDayOfMonth(31)
                                .withHour(23)
                                .withMinute(59)
                                .withSecond(59);
                    } else {
                        // End date = today end of day
                        endLocalDate = today
                                .withHour(23)
                                .withMinute(59)
                                .withSecond(59);
                    }

//                    leads = leadRepository.selectAllByColorStatusAndCreatedTimestamp(leadStatus, color, leadCreatedDateTime);
                    leads = leadRepository.selectAllByColorStatusAndBetweenDate(leadStatus, color, leadCreatedDateTime, endLocalDate);
                }

                if (leadStatus.contains(LeadStatus.followUp)) {

                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);

                    leads.addAll(leadFollowUp);
                }
                LOGGER.info("leadlocalDateTime2" + leads);

            }

        }

        if (isPositionSales && authUserIds.size() > 0) {
            List<String> leadCreators = new ArrayList<>();
            leadCreators.add("daily-sync");
            leadCreators.addAll(csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_SALES, Arrays.asList(EscalationType.L1, EscalationType.L2)).stream().map(x -> x.getFullName()).collect(Collectors.toList()));
            leadCreators.addAll(csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_BGC, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3)).stream().map(x -> x.getFullName()).collect(Collectors.toList()));
            model.addAttribute("leadCreators", leadCreators);
        }
        List<Lead> weekLast = new ArrayList<>();
        List<Lead> weekThird = new ArrayList<>();
        List<Lead> weekSecond = new ArrayList<>();
        List<Lead> weekFirst = new ArrayList<>();
        LocalDateTime curDate = LocalDate.now().atStartOfDay();
        List<LeadWeakWiseModel> lwDays = new ArrayList<>();

        for (int i = 7; i >= 1; i--) {
            LocalDateTime startOfDay = curDate.minusDays(i);

            LeadWeakWiseModel lm = new LeadWeakWiseModel();
            lm.setMonth(startOfDay.toLocalDate());
            lwDays.add(lm);
        }
        if (!leads.isEmpty()) {

            weekLast.addAll(
                    leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(28)) && x.getCreatedTimestamp().isBefore(curDate.minusDays(21))).collect(Collectors.toList()));

            weekThird.addAll(leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(21)) && x.getCreatedTimestamp().isBefore(curDate.minusDays(14))).collect(Collectors.toList()));

            weekSecond.addAll(leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(14)) && x.getCreatedTimestamp().isBefore(curDate.minusDays(7))).collect(Collectors.toList()));

            weekFirst.addAll(leads.stream().filter(x -> x.getCreatedTimestamp().isAfter(curDate.minusDays(7))).collect(Collectors.toList()));

        }
        LOGGER.info("weekLast" + weekLast);
        LOGGER.info("weekThird" + weekThird);
        LOGGER.info("weekSecond" + weekSecond);
        Map<String, Long> leadLasts = weekLast.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.counting()));
        Map<String, Long> leadThirds = weekThird.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.counting()));
        Map<String, Long> leadSeconds = weekSecond.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.mapping(Lead::getCreatedBy, Collectors.counting())));

        Map<String, Map<LocalDate, Long>> leadFirsts = weekFirst.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy(), Collectors.groupingBy(x -> x.getCreatedTimestamp().toLocalDate(), Collectors.counting())));

        LOGGER.info("leadFirsts" + leadFirsts);

        List<Integer> authIds = new ArrayList<>();
        if (!leads.isEmpty()) {

            authIds.addAll(leads.stream().map(x -> x.getAssignTo()).collect(Collectors.toList()));

            leadActivityMap = leadActivityRepository.selectAllByleadIds(leads.stream().map(x -> x.getId()).collect(Collectors.toList())).stream().collect(Collectors.groupingBy(LeadActivity::getLeadId, Collectors.toList()));

            Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
            model.addAttribute("leadActivityMap", leadActivityMap);
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
        }

        ChartLeadModel cm = this.getLeadChart(leads);
        model.addAttribute("chartLead", gson.toJson(cm));

        LOGGER.info("ChartLeadModel" + gson.toJson(cm));
        LOGGER.info("lwDays" + lwDays);

        LOGGER.info("leads" + leads);
        List<String> stateNames = stateRepository.selectAll().stream().map(x -> x.getName()).collect(Collectors.toList());
//        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
        List<AuthUser> authUsers = new ArrayList<>();
        List<AuthUser> salesUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_SALES, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3));
        List<AuthUser> abmUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_ABM, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3));
        List<AuthUser> bgcUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_BGC, Arrays.asList(EscalationType.L1, EscalationType.L2, EscalationType.L3));
        authUsers.addAll(salesUsers);
        authUsers.addAll(abmUsers);
        authUsers.addAll(bgcUsers);
        LocalDate lastDate = curDate.minusDays(1).toLocalDate();

        List<LocalDate> weekDates = new ArrayList<>();

        weekDates.add(curDate.minusDays(28).toLocalDate());
        weekDates.add(curDate.minusDays(22).toLocalDate());
        weekDates.add(curDate.minusDays(21).toLocalDate());
        weekDates.add(curDate.minusDays(15).toLocalDate());
        weekDates.add(curDate.minusDays(14).toLocalDate());
        weekDates.add(curDate.minusDays(8).toLocalDate());
        weekDates.add(curDate.minusDays(7).toLocalDate());
        LOGGER.info("lastDate" + lastDate);

        model.addAttribute("weekDates", weekDates);

        model.addAttribute("leadDate", leadDate);
        model.addAttribute("lastDate", lastDate);
        model.addAttribute("stateNames", stateNames);

        model.addAttribute("communicationTypes", CommunicationType.values());

        model.addAttribute("authUsers", authUsers);
        model.addAttribute("leads", leads);
        model.addAttribute("leadStatus", LeadStatus.values());
        model.addAttribute("leadLasts", leadLasts);
        model.addAttribute("leadThirds", leadThirds);
        model.addAttribute("leadSeconds", leadSeconds);
        model.addAttribute("leadFirsts", leadFirsts);
        model.addAttribute("lwDays", lwDays);

        model.addAttribute("selectedLeadStatus", leadStatus.get(0));


        List<BrandCatalog> brandsDisplays = brandsService.getBrandsToDisplay(3);
        brandsDisplays.addAll(brandsService.getBrandsToDisplay(6));
        model.addAttribute("brandsDisplays", brandsDisplays.stream().distinct().collect(Collectors.toList()));

        LOGGER.info("brandsDisplays" + brandsDisplays);


        return "lead";

    }

    public ChartLeadModel getLeadChart(List<Lead> leads) throws ProfitMandiBusinessException {

        Map<LeadStatus, Long> leadStatusMap = leads.stream().collect(
                Collectors.groupingBy(x -> x.getStatus(), Collectors.mapping(Lead::getStatus, Collectors.counting())));

        Map<String, Long> hotLeadsMap = leads.stream().collect(
                Collectors.groupingBy(x -> x.getColor(), Collectors.mapping(Lead::getColor, Collectors.counting())));

        LOGGER.info("hotLeadsMap" + hotLeadsMap);
        ChartLeadModel cm = new ChartLeadModel();

        HashSet<LeadStatus> labels = new HashSet<LeadStatus>();
        labels.addAll(leadStatusMap.keySet());

        List<String> hotLeads = new ArrayList<>();
        hotLeads.addAll(leadStatusMap.keySet().stream().map(x -> x.toString()).collect(Collectors.toSet()));
        hotLeads.add("HotLead");

        List<String> hotLeadKeys = new ArrayList<>();

        hotLeadKeys.add("HotLead");
        List<String> hotLeadGreen = new ArrayList<>(hotLeadKeys);

        LOGGER.info("hotLeads" + hotLeads);

        List<LeadStatus> labelList = new ArrayList<>(labels);
        List<String> backgroundColor = new ArrayList<>();
        LOGGER.info("hotLeadKeys" + hotLeadKeys);
        List<Long> values = new ArrayList<>();

        for (String hotLead : hotLeads) {

            if (hotLead.equals("pending")) {
                backgroundColor.add("pink");
                values.add(leadStatusMap.get(LeadStatus.pending));
            }
            if (hotLead.equals("notInterested")) {
                backgroundColor.add("red");
                values.add(leadStatusMap.get(LeadStatus.notInterested));
            }
            if (hotLead.equals("followUp")) {
                backgroundColor.add("#9ACD32");
                values.add(leadStatusMap.get(LeadStatus.followUp));
            }
            if (hotLead.equals("finalized")) {
                backgroundColor.add("blue");
                values.add(leadStatusMap.get(LeadStatus.finalized));
            }

            if (hotLead.equals("HotLead")) {
                backgroundColor.add("green");
                values.add(hotLeadsMap.get("Green"));

            }

        }
        LOGGER.info("labelList" + labelList);

        LOGGER.info("backgroundColor" + backgroundColor);
        LOGGER.info("labelsChartLead" + labels);
        LeadStatusData data = new LeadStatusData();
        data.setData(values);
        data.setBackgroundColor(backgroundColor);
        data.setLabel("DataSet 1");

        PieLables label = new PieLables();
        label.setFontColor("black");
        label.setFontSize(15);

        Legend legend = new Legend();
        legend.setLabels(label);
        legend.setPosition("left");

        List<LeadStatusData> dataList = new ArrayList<>();
        dataList.add(data);

        DataLeadModel datasets = new DataLeadModel();
        datasets.setDatasets(dataList);
        datasets.setLabels(hotLeads);

        OptionModel om = new OptionModel();
        om.setLegend(legend);

        cm.setType("pie");
        cm.setData(datasets);
        cm.setOptions(om);

        return cm;
    }

    @RequestMapping(value = "/downloadDateWiseLead", method = RequestMethod.GET)
    public ResponseEntity<?> getdownloadLeadDataByDate(HttpServletRequest request,
                                                       @RequestParam(name = "leadStatus", required = false, defaultValue = "All") List<LeadStatus> leadStatus,
                                                       @RequestParam(name = "color", required = false, defaultValue = "All") List<String> color,
                                                       @RequestParam(name = "leadDate", required = false, defaultValue = "") LocalDate leadDate) throws Exception {

        LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
        String emailId = fofoDetails.getEmailId();
        LocalDateTime localDateTime = null;
        if (leadDate != null) {
            localDateTime = leadDate.atStartOfDay();
        }
        List<Lead> leads = new ArrayList<>();
        AuthUser authUser = authRepository.selectByEmailOrMobile(emailId);

        if (leadStatus.contains(LeadStatus.All)) {
            leadStatus.add(LeadStatus.pending);
            leadStatus.add(LeadStatus.notInterested);
            leadStatus.add(LeadStatus.finalized);
            leadStatus.add(LeadStatus.followUp);
        }
        if (color.contains("All")) {
            color.add("yellow");
            color.add("green");
        }

        Map<Integer, List<LeadActivity>> leadActivityMap = new HashMap<>();
        boolean authPositon = positionRepository.hasCategory(authUser.getId(), ProfitMandiConstants.TICKET_CATEGORY_SALES);
        List<Integer> authUserIds = null;
        List<Lead> leadFollowUp = new ArrayList<>();

        if (authPositon) {
            authUserIds = authService.getAllReportees(authUser.getId());
            authUserIds.add(authUser.getId());
            if (localDateTime == null) {
                if (!leadStatus.contains(LeadStatus.followUp)) {
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestampAndAuthIds(leadStatus, authUserIds, color, LocalDateTime.now().minusMonths(1));
                }
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
                    leads.addAll(leadFollowUp);
                }
            } else {
                if (!leadStatus.contains(LeadStatus.followUp)) {
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestampAndAuthIds(leadStatus, authUserIds, color, localDateTime);
                }
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
                    leadFollowUp = leadRepository.selectByAssignAuthIdsAndStatus(authUserIds, LeadStatus.followUp);
                    leads.addAll(leadFollowUp);
                }
            }
        } else {
            if (localDateTime == null) {
                if (!leadStatus.contains(LeadStatus.followUp)) {
                    leads = leadRepository.selectAllByColorStatusAndUpdatedTimestamp(leadStatus, color, LocalDateTime.now().minusMonths(1));
                }
                if (leadStatus.contains(LeadStatus.followUp) || leadStatus.contains(LeadStatus.All)) {
                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);
                    leads.addAll(leadFollowUp);
                }
            } else {
                /*if (!leadStatus.contains(LeadStatus.followUp)) {
                    leads = leadRepository.selectAllByColorStatusAndCreatedTimestamp(leadStatus, color, localDateTime);
                }
                if (leadStatus.contains(LeadStatus.followUp)) {
                    leadFollowUp = leadRepository.selectAllByStatus(LeadStatus.followUp);
                    leads.addAll(leadFollowUp);
                }*/

                leads = leadRepository.selectAllByColorStatusAndCreatedTimestamp(leadStatus, color, localDateTime);
            }
        }

        // Build activity map and auth map (SAME AS VIEW ENDPOINT)
        if (!leads.isEmpty()) {
            List<Integer> leadIds = leads.stream().map(Lead::getId).collect(Collectors.toList());
            leadActivityMap = leadActivityRepository.selectAllByleadIds(leadIds).stream()
                    .collect(Collectors.groupingBy(LeadActivity::getLeadId));
        }
        List<Integer> authIds = leads.stream().map(Lead::getAssignTo).collect(Collectors.toList());
        Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream()
                .collect(Collectors.toMap(AuthUser::getId, x -> x));

        // Build CSV rows (USE DIRECT LEAD PROPERTIES - NO ACTIVITY FALLBACK)
        List<List<?>> rows = new ArrayList<>();
        for (Lead lead : leads) {
            List<LeadActivity> activities = leadActivityMap.get(lead.getId());

            // Use FIRST activity's schedule timestamp if exists
            String scheduleTimestamp = (activities != null && !activities.isEmpty())
                    ? FormattingUtils.format(activities.get(0).getSchelduleTimestamp())
                    : "";

            // DIRECTLY use Lead properties (NO fallback to activity)
            Double potential = lead.getPotential();
            String outLetName = lead.getOutLetName() != null ? lead.getOutLetName() : "";

            // Assignee name (blank if missing)
            String assignTo = "";
            if (authIdAndAuthUserMap.containsKey(lead.getAssignTo())) {
                AuthUser user = authIdAndAuthUserMap.get(lead.getAssignTo());
                assignTo = (user.getFirstName() + " " + user.getLastName()).trim();
            }

            rows.add(Arrays.asList(
                    lead.getSource(),
                    lead.getFullName(),
                    outLetName,
                    potential,
                    lead.getLeadMobile(),
                    lead.getAddress() != null ? lead.getAddress() : "",
                    lead.getCity() != null ? lead.getCity() : "",
                    lead.getState() != null ? lead.getState() : "",
                    lead.getCreatedBy() != null ? lead.getCreatedBy() : "",
                    lead.getStatus().toString(),
                    FormattingUtils.format(lead.getCreatedTimestamp()),
                    FormattingUtils.format(lead.getUpdatedTimestamp()),
                    scheduleTimestamp,
                    lead.getClosureTimestamp() != null
                            ? FormattingUtils.format(lead.getClosureTimestamp())
                            : "",  // Handle null closure
                    assignTo,
                    lead.getColor() != null ? lead.getColor() : ""
            ));
        }

        // Generate CSV response
        ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                Arrays.asList("Source", "Partner Name", "Outlet Name", "Potential", "Mobile", "Address", "City", "State",
                        "Created By", "Status", "Created On", "Updated On", "Scheduled Timestamp",
                        "Closure Timestamp", "Assign To", "Color"),
                rows
        );
        return orderService.downloadReportInCsv(baos, rows, "LeadDetails_");
    }

    @RequestMapping(value = "/getClosedLead", method = RequestMethod.GET)
    public String getClosedLead(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm, Model model) throws Exception {
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
        List<Lead> leads = null;
        long size = 0;
        leads = leadRepository.selectAllByStatus(status, offset, limit);
        size = leadRepository.selectCountByStatus(status);

        if (!leads.isEmpty()) {
            List<Integer> authIds = new ArrayList<>();
            for (Lead lead : leads) {
                authIds.add(lead.getAssignTo());
            }
            Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));

            model.addAttribute("leads", leads);
            model.addAttribute("start", offset + 1);
            model.addAttribute("size", size);
            model.addAttribute("searchTerm", searchTerm);
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
            model.addAttribute("url", "/getPaginatedClosedLeads");

            if (leads.size() < limit) {
                model.addAttribute("end", offset + leads.size());
            } else {
                model.addAttribute("end", offset + limit);
            }

        } else {
            model.addAttribute("lead", leads);

            model.addAttribute("size", size);
        }

        model.addAttribute("authUsers", authUsers);
        return "lead-close";
    }

    @RequestMapping(value = "/getPaginatedClosedLeads", method = RequestMethod.GET)
    public String getPaginatedClosedLeads(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) throws ProfitMandiBusinessException {
        List<Lead> leads = null;
        leads = leadRepository.selectAllByStatus(status, offset, limit);

        if (!leads.isEmpty()) {
            List<Integer> authIds = new ArrayList<>();
            for (Lead lead : leads) {
                authIds.add(lead.getAssignTo());
            }
            Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
            model.addAttribute("leads", leads);
            model.addAttribute("url", "/getPaginatedClosedLeads");

        } else {
            model.addAttribute("leads", leads);

        }
        return "lead-close-paginated";
    }

    @RequestMapping(value = "/searchLeads")
    public String getClosedLeads(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm, Model model) throws ProfitMandiBusinessException {
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
        List<Lead> leads = null;
        long size = 0;
        if (!(searchTerm.equals(""))) {
            leads = leadRepository.selectBySearchTerm(status, searchTerm, offset, limit);
            size = leadRepository.selectCountByStatus(status);
            Map<Integer, AuthUser> authIdAndAuthUserMap = new HashMap<>();
            List<Integer> authIds = new ArrayList<>();
            if (!(leads.size() == 0)) {
                for (Lead lead : leads) {
                    authIds.add(lead.getAssignTo());
                }
                authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
                if (leads.size() < limit) {
                    model.addAttribute("end", offset + leads.size());
                } else {
                    model.addAttribute("end", offset + limit);
                }
            } else {
                model.addAttribute("end", offset + limit);
            }
            model.addAttribute("leads", leads);
            model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
            model.addAttribute("start", offset + 1);
            model.addAttribute("size", size);
            model.addAttribute("searchTerm", searchTerm);
        } else {
            leads = leadRepository.selectAllByStatus(status, offset, limit);
            size = leadRepository.selectCountByStatus(status);

            if (!leads.isEmpty()) {
                List<Integer> authIds = new ArrayList<>();
                for (Lead lead : leads) {
                    authIds.add(lead.getAssignTo());
                }
                Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));

                model.addAttribute("leads", leads);
                model.addAttribute("start", offset + 1);
                model.addAttribute("size", size);
                model.addAttribute("searchTerm", searchTerm);
                model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);

                if (leads.size() < limit) {
                    model.addAttribute("end", offset + leads.size());
                } else {
                    model.addAttribute("end", offset + limit);
                }

            }
        }

        model.addAttribute("authUsers", authUsers);
        return "lead-close";
    }

    @RequestMapping(value = "/searchLeadPaginated")
    public String searchLeadPaginated(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "searchTerm", required = false, defaultValue = "") String searchTerm, Model model) throws ProfitMandiBusinessException {
        LOGGER.info("In search Item....");
        List<Lead> leads = null;
        if (!searchTerm.equals("")) {
            leads = leadRepository.selectBySearchTerm(status, searchTerm, offset, limit);
            if (!(leads.size() == 0)) {

                List<Integer> authIds = new ArrayList<>();
                for (Lead lead : leads) {
                    authIds.add(lead.getAssignTo());
                }
                Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectByIds(authIds).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
                model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);
                model.addAttribute("leads", leads);
            }
        }

        return "lead-close-paginated";

    }

    @RequestMapping(value = "/getLeadActivity", method = RequestMethod.GET)
    public String getLeadActivity(HttpServletRequest request, @RequestParam int leadId, Model model) throws Exception {
        List<LeadActivity> leadActivity = leadActivityRepository.selectBYLeadId(leadId);

        LOGGER.info("leadActivity" + leadActivity);

        model.addAttribute("leadActivity", leadActivity);
        model.addAttribute("authUserMap", authRepository.selectAllActiveUser().stream().collect(Collectors.toMap(x -> x.getId(), x -> x)));

        return "lead_activity_modal";
    }

    @RequestMapping(value = "/getLead", method = RequestMethod.GET)
    public ResponseEntity<?> getLead(HttpServletRequest request, @RequestParam int leadId) throws Exception {
        Lead lead = leadRepository.selectById(leadId);

        LeadDetail leadDetail = leadDetailRepository.selectByLeadId(lead.getId());
        if (leadDetail != null) {
            lead.setOutLetName(leadDetail.getOutletName());
        }

        return responseSender.ok(lead);

    }

    @RequestMapping(value = "/createLead", method = RequestMethod.POST)
    public String CreateLead(HttpServletRequest request, @RequestBody CreateRefferalRequest createRefferalRequest, Model model) throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        Lead leadDetails = leadRepository.selectByMobileNumber(createRefferalRequest.getMobile());
        LOGGER.info("Lead Details {}", leadDetails);

        if (leadDetails != null && leadDetails.getStatus() != LeadStatus.notInterested) {
            AuthUser authUser1 = authRepository.selectById(leadDetails.getAssignTo());
            model.addAttribute("response1", "Lead already exists, created by " + leadDetails.getCreatedBy() +
                    " on " + FormattingUtils.format(leadDetails.getCreatedTimestamp()) +
                    ", assigned to " + authUser1.getFullName());
            return "response";


        }

        LOGGER.info("createRefferalRequest" + createRefferalRequest.getSchelduleTimestamp());
        Lead lead = new Lead();
        lead.setFirstName(createRefferalRequest.getFirstName());
        lead.setLastName(createRefferalRequest.getLastName());
        lead.setLeadMobile(createRefferalRequest.getMobile());
        lead.setState(createRefferalRequest.getState());
        lead.setCity(createRefferalRequest.getCity());
        lead.setAddress(createRefferalRequest.getAddress());
        lead.setCreatedTimestamp(LocalDateTime.now());
        lead.setUpdatedTimestamp(LocalDateTime.now());
        lead.setStatus(createRefferalRequest.getStatus());
        lead.setAssignTo(createRefferalRequest.getAssignTo());
        lead.setSource(createRefferalRequest.getSource());
        if (createRefferalRequest.getColorCheck() == true) {
            lead.setColor("Green");
        } else {
            lead.setColor("Yellow");
        }
        // change
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());
        String authUserName = authUser.getFirstName() + " " + authUser.getLastName();
        lead.setCreatedBy(authUserName);
        lead.setAuthId(authUser.getId());
        LOGGER.info("lead --- {}", lead);
        leadRepository.persist(lead);
        LeadActivity leadActivity = new LeadActivity();
        leadActivity.setLeadId(lead.getId());
        leadActivity.setRemark(createRefferalRequest.getRemark());
        leadActivity.setAuthId(authUser.getId());

        LOGGER.info("createRefferalRequest" + createRefferalRequest.getCommunicationType());

        if (createRefferalRequest.getStatus() == LeadStatus.followUp) {
            leadActivity.setSchelduleTimestamp(createRefferalRequest.getSchelduleTimestamp());
            leadActivity.setCommunicationType(createRefferalRequest.getCommunicationType());

            if (leadActivity.getCommunicationType().equals(CommunicationType.VISIT)) {
                visitRequestRepository.createVisitRequest(lead.getId(), "lead", lead.getAssignTo(), createRefferalRequest.getSchelduleTimestamp());
            }
        } else {
            leadActivity.setSchelduleTimestamp(null);
        }
        leadActivity.setCreatedTimestamp(LocalDateTime.now());
        leadActivityRepository.persist(leadActivity);
        if (!lead.getStatus().equals(LeadStatus.notInterested)) {
            LeadDetailModel leadDetail = new LeadDetailModel();
            leadDetail.setLeadId(lead.getId());
            leadDetail.setOutletName(createRefferalRequest.getOutletName());
            leadDetail.setCounterSize(createRefferalRequest.getCounterSize());


            leadDetail.setFrontp(createRefferalRequest.getFrontp());
            leadDetail.setFrontWithMarket(createRefferalRequest.getFrontWithMarket());


            leadDetail.setInternalLongShot(createRefferalRequest.getInternalLongShot());

            leadDetail.setInternalLeftWall(createRefferalRequest.getInternalLeftWall());

            leadDetail.setInternalRightWall(createRefferalRequest.getInternalRightWall());
            List<LeadBrandModel> brandModels = new ArrayList<LeadBrandModel>();

            for (LeadBrandModel leadBrandModel : createRefferalRequest.getLeadBrands()) {

                LeadBrandModel leadBrand = new LeadBrandModel();
                leadBrand.setBrand(leadBrandModel.getBrand());
                leadBrand.setValue(leadBrandModel.getValue());

                brandModels.add(leadBrand);

            }

            leadDetail.setLeadBrands(brandModels);

            leadRepository.persistLeadDetail(leadDetail, authUser);
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));

        return "response";

    }


    @RequestMapping(value = "/editLead", method = RequestMethod.POST)
    public String EditLead(HttpServletRequest request, @RequestBody CreateLeacdActivityRequest createLeadActivityRequest, Model model) throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());

        Lead lead = leadRepository.selectById(createLeadActivityRequest.getId());
        AuthUser leadAuthUser = authRepository.selectById(lead.getAuthId());
        LeadDetail leadDetail = leadDetailRepository.selectByLeadId(createLeadActivityRequest.getId());

        if (leadDetail == null && !createLeadActivityRequest.getStatus().equals(LeadStatus.notInterested) && leadAuthUser.isActive()) {

            throw new ProfitMandiBusinessException("LeadDetail", "", "Please fill lead detail");
        }

        LeadActivity leadActivity = new LeadActivity();
        leadActivity.setLeadId(createLeadActivityRequest.getId());
        leadActivity.setRemark(createLeadActivityRequest.getRemark());

        LOGGER.info("createRefferalRequest" + createLeadActivityRequest);

        if (createLeadActivityRequest.getStatus() == LeadStatus.followUp) {
            leadActivity.setSchelduleTimestamp(createLeadActivityRequest.getScheldule());
            leadActivity.setCommunicationType(createLeadActivityRequest.getCommunicationType());
            if (leadActivity.getCommunicationType().equals(CommunicationType.VISIT)) {
                visitRequestRepository.createVisitRequest(createLeadActivityRequest.getId(), "lead", createLeadActivityRequest.getAssignTo(), createLeadActivityRequest.getScheldule());
            }
        } else {
            leadActivity.setSchelduleTimestamp(null);
        }
        leadActivity.setCreatedTimestamp(LocalDateTime.now());
        leadActivity.setAuthId(authUser.getId());
        leadActivityRepository.persist(leadActivity);
        lead.setAssignTo(createLeadActivityRequest.getAssignTo());
        lead.setStatus(createLeadActivityRequest.getStatus());
        if (createLeadActivityRequest.getColorCheck() == true) {
            lead.setColor("Green");
        } else {
            lead.setColor("Yellow");
        }
        lead.setNotinterestedReason(createLeadActivityRequest.getReason());
        lead.setUpdatedTimestamp(LocalDateTime.now());

        int authId = 0;
        authId = lead.getAssignTo();
        Map<Integer, LeadActivity> leadActivityMap = new HashMap<>();

        List<LeadActivity> leadActivitys = leadActivityRepository.selectBYLeadId(lead.getId());

        if (!leadActivitys.isEmpty()) {
            leadActivityMap.put(lead.getId(), leadActivitys.get(0));
        }

        Map<Integer, AuthUser> authIdAndAuthUserMap = new HashMap<>();
        AuthUser AuthUser = authRepository.selectById(authId);

        authIdAndAuthUserMap.put(AuthUser.getId(), AuthUser);

        model.addAttribute("leadActivityMap", leadActivityMap);
        model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);


        model.addAttribute("lead", lead);

        return "edit-lead";

    }

    @RequestMapping(value = "/downloadIvoryLead", method = RequestMethod.GET)
    public ResponseEntity<?> downloadDelayDayTemplate(HttpServletRequest request) throws Exception {
        List<String> stateNames = stateRepository.selectAll().stream().map(x -> x.getName()).collect(Collectors.toList());

        List<List<?>> rows = new ArrayList<>();

        List<LeadSource> lss = LeadSource.enumValues;

        for (LeadSource ls : lss) {
            rows.add(Arrays.asList("-", "-", "-", "-", "-", "-", "-", ls));

        }
        for (String stateName : stateNames) {
            rows.add(Arrays.asList("-", "-", "-", "-", stateName, "-", "-", "-"));

        }

        org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("First Name", "Last Name", "Address", "City", "State", "Mobile", "Assign To(email)", "Source"), rows);

        final HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "text/csv");
        headers.set("Content-disposition", "inline; filename=leads.format.csv");
        headers.setContentLength(baos.toByteArray().length);

        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);

    }

    @RequestMapping(value = "/csvFileAndSetLead", method = RequestMethod.POST)
    public String readCsvFileAndSetLead(HttpServletRequest request, Model model, HttpServletResponse response, @RequestPart MultipartFile file) throws Throwable {

        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        String email = loginDetails.getEmailId();

        AuthUser createdBy = authRepository.selectByEmailOrMobile(email);

        LOGGER.info("file" + file.toString());

        String fileName = file.getName();

        String fileNames = file.getOriginalFilename();

        LOGGER.info("fileName" + fileName);
        LOGGER.info("fileNames" + fileNames);

        List<CSVRecord> records = FileUtil.readFile(file);

        for (CSVRecord record : records) {

            Lead lead = new Lead();
            lead.setFirstName(record.get(0));
            lead.setLastName(record.get(1));
            lead.setAddress(record.get(2));
            lead.setCity(record.get(3));
            lead.setState(record.get(4));
            lead.setLeadMobile(record.get(5));
            LOGGER.info("record" + record.get(6));

            AuthUser assignTo = authRepository.selectByEmailOrMobile(record.get(6));

            if (assignTo == null) {
                throw new ProfitMandiBusinessException("Assign To ", record.get(6), "email id not exist");
            }

            lead.setAssignTo(assignTo.getId());
            lead.setSource(record.get(7));

            lead.setCreatedTimestamp(LocalDateTime.now());

            lead.setUpdatedTimestamp(LocalDateTime.now());
            lead.setStatus(LeadStatus.pending);
            lead.setColor("yellow");
            // change
            lead.setCreatedBy(createdBy.getFullName());
            lead.setAuthId(createdBy.getId());

            leadRepository.persist(lead);

            LeadActivity leadActivity = new LeadActivity();
            leadActivity.setLeadId(lead.getId());
            leadActivity.setRemark("New Lead");
            leadActivity.setSchelduleTimestamp(null);

            leadActivity.setCreatedTimestamp(LocalDateTime.now());
            leadActivityRepository.persist(leadActivity);
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));

        }

        model.addAttribute("responseSTG", mvcResponseSender.createResponseString(true));

        return "response";

    }

    @RequestMapping(value = "/teamCommitment", method = RequestMethod.GET)
    public String teamCommitments(HttpServletRequest request, Model model) throws Exception {

        return "team-commitment";

    }

    @RequestMapping(value = "/leadDetail", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public String leadDetail(HttpServletRequest request, @RequestBody LeadDetailModel leadDetailModel, Model model) throws Exception {

        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());

        leadRepository.persistLeadDetail(leadDetailModel, authUser);
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));

        return "response";

    }

    @RequestMapping(value = "/getLeadDetail", method = RequestMethod.GET)
    public String getLeadDetail(HttpServletRequest request, Model model) throws Exception {
        List<Integer> followUpleadIds = leadRepository.selectAllByStatus(LeadStatus.followUp).stream().map(x -> x.getId()).collect(Collectors.toList());
        List<LeadDetail> leadDetails = leadDetailRepository.selectByLeadIds(followUpleadIds);

        List<DBObject> mobileBrands = mongoClient.getAllBrandsToDisplay(3);

        List<String> brands = mobileBrands.stream().map(x -> (String) x.get("name")).collect(Collectors.toList());

        model.addAttribute("brands", brands);
        if (!leadDetails.isEmpty()) {

            List<Integer> detailsIds = leadDetails.stream().map(x -> x.getId()).collect(Collectors.toList());

            List<Integer> leadIds = leadDetails.stream().map(x -> x.getLeadId()).collect(Collectors.toList());

            Map<Integer, Lead> leadMap = leadRepository.selectAllByIds(leadIds).stream().filter(x -> x.getStatus().equals(LeadStatus.followUp)).collect(Collectors.toMap(x -> x.getId(), x -> x));

            Map<Integer, Optional<LeadActivity>> leadActivityMap = leadActivityRepository.selectAllByleadIds(leadIds).stream().collect(Collectors.groupingBy(x -> x.getLeadId(), Collectors.maxBy(Comparator.comparing(LeadActivity::getId))));

            model.addAttribute("leadActivityMap", leadActivityMap);

            List<LeadBrand> leadBrands = leadBrandRepository.selectByLeadDetailId(detailsIds);

            LOGGER.info("leadBrands {}" + leadBrands);

            Map<Integer, Map<String, Integer>> leadDetailBrandValue = new HashMap<>();

            Map<Integer, List<LeadBrand>> leadDetail = leadBrands.stream().collect(Collectors.groupingBy(x -> x.getLeadDetailId(), Collectors.toList()));

            for (Entry<Integer, List<LeadBrand>> leadDetailEntry : leadDetail.entrySet()) {

                Map<String, Integer> brandValue = new HashMap<>();

                for (LeadBrand leadBrand : leadDetailEntry.getValue()) {
                    brandValue.put(leadBrand.getBrand(), leadBrand.getValue());

                }
                leadDetailBrandValue.put(leadDetailEntry.getKey(), brandValue);
            }

            LOGGER.info("leadDetailBrandValue {}" + leadDetailBrandValue);

            model.addAttribute("leadDetailBrandValue", leadDetailBrandValue);

            model.addAttribute("leadMap", leadMap);
        }

        model.addAttribute("leadDetails", leadDetails);

        Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectAllActiveUser().stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
        model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);

        return "lead-detail";

    }

    @RequestMapping(value = "/getLeadDetailByLeadId", method = RequestMethod.GET)
    public ResponseEntity<?> getLeadDetailByLeadId(HttpServletRequest request, @RequestParam int leadId, Model model) throws Exception {

        LeadDetail leadDetail = leadDetailRepository.selectByLeadId(leadId);
        return responseSender.ok(leadDetail);

    }

    @RequestMapping(value = "/getTeamCommitment", method = RequestMethod.GET)
    public String getTeamCommitments(HttpServletRequest request, @RequestParam LocalDateTime date, Model model) throws Exception {

        List<TeamCommitmentModel> commitments = partnerCollectionPlanRepository.selectTeamCommitmentByDate(date.toLocalDate());

        model.addAttribute("commitments", commitments);
        return "team-commitment-table";

    }

    @Autowired
    RbmTargetService rbmTargetService;

    @RequestMapping(value = "/rbmTodayArr", method = RequestMethod.GET)
    public String getRbmTodayArr(HttpServletRequest request, Model model, @RequestParam(value = "startDate", required = false) LocalDate startDate) throws Exception {
        List<RbmArrViewModel> rbmArrViewModels;
        DecimalFormat decimalFormat = new DecimalFormat("#"); // No decimal places
        if (startDate != null) {
            rbmArrViewModels = rbmTargetService.getRbmTodayArr(startDate);
        } else {
            rbmArrViewModels = rbmTargetService.getRbmTodayArr();
        }

        Set<AuthUser> authUsers = new HashSet<>();
        Set<AuthUser> rbmAuthUsers = csService.getAuthUserByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM, EscalationType.L1).stream().filter(x -> x.isActive()).collect(Collectors.toSet());
        Set<AuthUser> salesAuthUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_RBM, Arrays.asList(EscalationType.L1, EscalationType.L2)).stream().filter(x -> x.isActive()).collect(Collectors.toSet());

        authUsers.addAll(rbmAuthUsers);
        authUsers.addAll(salesAuthUsers);

        double totalAchieved = rbmArrViewModels.stream().mapToDouble(RbmArrViewModel::getTotalAchievedTarget).sum();
        double totalTargetSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayTarget).sum();

        double totalHidSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayHidTarget).sum();
        double totalHidAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedHidTarget).sum();

        double totalFastSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayFastMovingTarget).sum();
        double totalFastAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedFastMovingTarget).sum();

        double totalSlowSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodaySlowMovingTarget).sum();
        double totalSlowAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedSlowMovingTarget).sum();

        double totalRunningSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayRunningTarget).sum();
        double totalRunningAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedRunningTarget).sum();

        double totalOtherSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayOtherMovingTarget).sum();
        double totalOtherAchievedSum = rbmArrViewModels.stream().mapToLong(RbmArrViewModel::getTodayAchievedOtherMovingTarget).sum();

        List<Sold15daysOldAgingModel> sold15daysOldAgingModels = rbmTargetService.getAgingSale(LocalDate.now(), LocalDate.now().plusDays(1));
        List<Our15DaysOldAgingStock> our15DaysOldAgingStocks = rbmTargetService.our15DaysAgingStock();

        long totalSoldSlow = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getSlowmovingBilled).sum();
        long totalSoldRun = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getRunningBilled).sum();
        long totalSoldFast = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getFastmovingBilled).sum();
        long totalSoldHid = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getHidBilled).sum();
        long totalSoldOther = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getOthersBilled).sum();
        long totalSoldAging = sold15daysOldAgingModels.stream().mapToLong(Sold15daysOldAgingModel::getTotalBilled).sum();


//        first week count of rbm partner billing
        LocalDate firstOfCurrentMonth = LocalDate.now().withDayOfMonth(1);
        LocalDate seventhOfCurrentMonth = LocalDate.now().withDayOfMonth(7);

        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsFirstWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(firstOfCurrentMonth, seventhOfCurrentMonth);

        Map<String, Long> rbmBilledCountMapFirstWeek = rbmBilledFofoIdsModelsFirstWeek.stream()
                .filter(x -> x.getStatus().equals("Billed"))
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));

        long totalFirstWeekCount = rbmBilledCountMapFirstWeek.values().stream()
                .mapToLong(Long::longValue)
                .sum();

        Map<String, Long> rbmTargetedFofoIdCountMap = rbmBilledFofoIdsModelsFirstWeek.stream()
                .collect(Collectors.groupingBy(
                        RbmBilledFofoIdsModel::getRbmName, // Group by RBM Name
                        Collectors.counting() // Count all fofoId entries for each RBM
                ));

        long totalTargetedCount = rbmTargetedFofoIdCountMap.values().stream().mapToLong(x -> x.longValue()).sum();


//        second week count of rbm partner billing

        LocalDate eightOfCurrentMonth = LocalDate.now().withDayOfMonth(8);
        LocalDate fifteenOfCurrentMonth = LocalDate.now().withDayOfMonth(15);

        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsSecondWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(eightOfCurrentMonth, fifteenOfCurrentMonth);

        Map<String, Long> rbmBilledCountMapSecondWeek = rbmBilledFofoIdsModelsSecondWeek.stream()
                .filter(x -> x.getStatus().equals("Billed"))
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));

        long totalSecondWeekCount = rbmBilledCountMapSecondWeek.values().stream().mapToLong(Long::longValue).sum();

//      third week count of rbm partner billing

        LocalDate sixteenOfCurrentMonth = LocalDate.now().withDayOfMonth(16);
        LocalDate twentySecondOfCurrentMonth = LocalDate.now().withDayOfMonth(22);

        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsThirdWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(sixteenOfCurrentMonth, twentySecondOfCurrentMonth);

        Map<String, Long> rbmBilledCountMapThirdWeek = rbmBilledFofoIdsModelsThirdWeek.stream()
                .filter(x -> x.getStatus().equals("Billed"))
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));

        long totalThirdWeekCount = rbmBilledCountMapThirdWeek.values().stream().mapToLong(Long::longValue).sum();


        //      fourth week count of rbm partner billing

        LocalDate twentyThirdOfCurrentMonth = LocalDate.now().withDayOfMonth(23);
        LocalDate lastDayOfCurrentMonth = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());

        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsFourthWeek = rbmTargetService.getDateWiseBilledFofoIdByRbm(twentyThirdOfCurrentMonth, lastDayOfCurrentMonth);

        Map<String, Long> rbmBilledCountMapFourthWeek = rbmBilledFofoIdsModelsFourthWeek.stream()
                .filter(x -> x.getStatus().equals("Billed"))
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));

        long totalFourthWeekCount = rbmBilledCountMapFourthWeek.values().stream().mapToLong(x -> x.longValue()).sum();


//      mtd rbm partner billing

        List<RbmBilledFofoIdsModel> rbmBilledFofoIdsModelsMtd = rbmTargetService.getDateWiseBilledFofoIdByRbm(firstOfCurrentMonth, LocalDate.now());

        Map<String, Long> rbmBilledCountMapMtd = rbmBilledFofoIdsModelsMtd.stream()
                .filter(x -> x.getStatus().equals("Billed"))
                .collect(Collectors.groupingBy(RbmBilledFofoIdsModel::getRbmName, Collectors.counting()));

        long totalMtdCount = rbmBilledCountMapMtd.values().stream().mapToLong(Long::longValue).sum();

        Map<String, Long> zeroBilledCountMap = rbmTargetedFofoIdCountMap.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> entry.getValue() - rbmBilledCountMapMtd.getOrDefault(entry.getKey(), 0L)
                ));

        long totalZeroBilledCount = zeroBilledCountMap.values().stream().mapToLong(Long::longValue).sum();

        //        rbmRating by franchisee visits

        Map<Integer, String> rbmIdToNameMap = authUsers.stream()
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));

        Map<String, RbMRatingModel> rbmNameToRatingMap = rbmRatingRepository
                .findAverageRatingByRbmId(new ArrayList<>(rbmIdToNameMap.keySet())).stream().collect(Collectors.toMap(
                        x -> rbmIdToNameMap.get(x.getRbmId()),
                        x -> x
                ));


        LOGGER.info("rbmArrViewModels {}", rbmArrViewModels);
        model.addAttribute("rbmArrViewModels", rbmArrViewModels);
        model.addAttribute("rbmNameToRatingMap", rbmNameToRatingMap);

        model.addAttribute("totalTargetSum", decimalFormat.format(totalTargetSum));
        model.addAttribute("totalAchieved", decimalFormat.format(totalAchieved));

        model.addAttribute("totalHidSum", decimalFormat.format(totalHidSum));
        model.addAttribute("totalHidAchievedSum", decimalFormat.format(totalHidAchievedSum));

        model.addAttribute("totalFastSum", decimalFormat.format(totalFastSum));
        model.addAttribute("totalFastAchievedSum", decimalFormat.format(totalFastAchievedSum));

        model.addAttribute("totalSlowSum", decimalFormat.format(totalSlowSum));
        model.addAttribute("totalSlowAchievedSum", decimalFormat.format(totalSlowAchievedSum));

        model.addAttribute("totalRunningSum", decimalFormat.format(totalRunningSum));
        model.addAttribute("totalRunningAchievedSum", decimalFormat.format(totalRunningAchievedSum));

        model.addAttribute("totalOtherSum", decimalFormat.format(totalOtherSum));
        model.addAttribute("totalOtherAchievedSum", decimalFormat.format(totalOtherAchievedSum));

        model.addAttribute("our15DaysOldAgingStocks", our15DaysOldAgingStocks);
        model.addAttribute("sold15daysOldAgingModels", sold15daysOldAgingModels);
        model.addAttribute("totalSoldSlow", totalSoldSlow);
        model.addAttribute("totalSoldRun", totalSoldRun);
        model.addAttribute("totalSoldFast", totalSoldFast);
        model.addAttribute("totalSoldHid", totalSoldHid);
        model.addAttribute("totalSoldOther", totalSoldOther);
        model.addAttribute("totalSoldAging", totalSoldAging);

        model.addAttribute("rbmTargetedFofoIdCountMap", rbmTargetedFofoIdCountMap);
        model.addAttribute("rbmBilledCountMapFirstWeek", rbmBilledCountMapFirstWeek);
        model.addAttribute("rbmBilledCountMapSecondWeek", rbmBilledCountMapSecondWeek);
        model.addAttribute("rbmBilledCountMapThirdWeek", rbmBilledCountMapThirdWeek);
        model.addAttribute("rbmBilledCountMapFourthWeek", rbmBilledCountMapFourthWeek);
        model.addAttribute("rbmBilledCountMapMtd", rbmBilledCountMapMtd);
        model.addAttribute("zeroBilledCountMap", zeroBilledCountMap);
        model.addAttribute("totalFirstWeekCount", totalFirstWeekCount);
        model.addAttribute("totalTargetedCount", totalTargetedCount);
        model.addAttribute("totalSecondWeekCount", totalSecondWeekCount);
        model.addAttribute("totalThirdWeekCount", totalThirdWeekCount);
        model.addAttribute("totalFourthWeekCount", totalFourthWeekCount);
        model.addAttribute("totalMtdCount", totalMtdCount);
        model.addAttribute("totalZeroBilledCount", totalZeroBilledCount);

        return "rbm-today-arr";
    }


    @RequestMapping(value = "/partnerHealth", method = RequestMethod.GET)
    public String partnerHealth(HttpServletRequest request, @RequestParam(name = "email", required = false) String email, Model model) throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        if (StringUtils.isEmpty(email)) {
            email = loginDetails.getEmailId();
        } else {
            AuthUser selectedUser = authRepository.selectByEmailOrMobile(email);

            model.addAttribute("selectedUser", selectedUser);

        }

        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());

        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
        List<Integer> fofoIds = new ArrayList<>(storeGuyMap.get(email));
        LocalDateTime startDate = LocalDate.now().atStartOfDay();
        if (fofoIds != null && fofoIds.size() > 0) {
            List<Integer> fofoIdList = fofoStoreRepository.selectByRetailerIds(fofoIds).stream().filter(x -> !x.isInternal()).map(x -> x.getId()).collect(Collectors.toList());

            Map<Integer, PartnerCollectionPlanModel> foundCollectionMap = partnerCollectionService.getCollectionMap(fofoIdList, startDate);

            List<Integer> remarkIds = partnerCollectionRemarkRepository.selectMaxRemarkId(fofoIdList);

            LOGGER.info("remarkIds {}", remarkIds);

            long todayOverallCall = 0;
            if (!remarkIds.isEmpty()) {

                if (authUser.getEmailId().equals(email)) {

                    todayOverallCall = partnerCollectionRemarkRepository.selectByIds(remarkIds).stream().filter(x -> x.getCreateTimestamp().toLocalDate().equals(LocalDate.now())).collect(Collectors.counting());
                } else {

                    todayOverallCall = partnerCollectionRemarkRepository.selectByAuthIdAndIds(authRepository.selectByEmailOrMobile(email).getId(), remarkIds).stream().filter(x -> x.getCreateTimestamp().toLocalDate().equals(LocalDate.now())).collect(Collectors.counting());

                }

            }
            ChartLeadModel cm = new ChartLeadModel();

            if (!foundCollectionMap.isEmpty()) {
                cm = this.getCollectionCount(foundCollectionMap.values().stream().collect(Collectors.toList()));

            }
            model.addAttribute("chartPartnerHealth", gson.toJson(cm));
            Map<Integer, PartnerDailyInvestment> partnerDailyInvestmentMap = new HashMap<>();

            List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository.selectAll(fofoIdList, startDate.toLocalDate().minusDays(1));
            if (!partnerDailyInvestments.isEmpty()) {
                partnerDailyInvestmentMap = partnerDailyInvestments.stream().collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
            }

            Map<LocalDate, Map<Integer, PartnerCollectionPlanModel>> pcpmMap = new TreeMap<>();
            for (int i = 0; i <= 6; i++) {

                Map<Integer, PartnerCollectionPlanModel> collectionMap = partnerCollectionService.getCollectionMap(fofoIdList, startDate.minusDays(i));

                pcpmMap.put(startDate.minusDays(i).toLocalDate(), collectionMap);
            }

            Map<Integer, PartnerCollectionPlanModel> todayPcpmMap = pcpmMap.get(startDate.toLocalDate());
            model.addAttribute("todayPcpmMap", todayPcpmMap);

            TotalTargetColectionModel totalTargetCollection = partnerCollectionService.getTotalTargetCollection(todayPcpmMap, startDate);
            model.addAttribute("totalPartnerTargetCollection", totalTargetCollection.getTotalTarget());

            model.addAttribute("totalPartnerAchievement", totalTargetCollection.getTotalAchievement());

            Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();
            Map<Integer, CustomRetailer> customRetailers = fofoIdList.stream().distinct().map(x -> customRetailerMap.get(x)).filter(x -> x != null).collect(Collectors.toList()).stream().collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));
            List<Integer> allReportees = authService.getAllReportees(authUser.getId());

            List<Integer> salesPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_SALES).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());
            List<Integer> rbmPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());

            salesPositionsAuthIds.addAll(rbmPositionsAuthIds);

            Set<Integer> empHierarchy = allReportees.stream().filter(x -> salesPositionsAuthIds.contains(x)).collect(Collectors.toSet());
            List<AuthUser> authUsers = new ArrayList<>();
            if (!empHierarchy.isEmpty()) {
                authUsers = authRepository.selectByIds(new ArrayList<>(empHierarchy));
            }


            Map<Integer, AuthUser> authUserMap = authRepository.selectAll().stream().collect(Collectors.toMap(x -> x.getId(), x -> x));

            LOGGER.info("todayPcpmMap {}", todayPcpmMap);

            model.addAttribute("authUsers", authUsers);
            model.addAttribute("authUserMap", authUserMap);
            model.addAttribute("partnerCollectionPlanMap", pcpmMap);
            model.addAttribute("partnerDailyInvestmentMap", partnerDailyInvestmentMap);
            model.addAttribute("customRetailers", customRetailers);
            model.addAttribute("rankColorMap", ProfitMandiConstants.Rank_Color_Map);
            model.addAttribute("todayOverallCall", todayOverallCall);

        }
        return "partner-health";

    }

    public ChartLeadModel getCollectionCount(List<PartnerCollectionPlanModel> pcpm) throws ProfitMandiBusinessException {

        Map<Integer, Long> rankCount = pcpm.stream().collect(Collectors.groupingBy(x -> x.getRank(), Collectors.mapping(PartnerCollectionPlanModel::getRank, Collectors.counting())));

        ChartLeadModel cm = new ChartLeadModel();

        List<String> labels = new ArrayList<>();
        labels.add("Plan for Today");
        labels.add("Carry Forward");
        labels.add("Untouched");
        labels.add("Plan for Future");
        labels.add("Normal");

        List<String> backgroundColor = new ArrayList<>();
        List<Long> values = new ArrayList<>();

        for (String label : labels) {

            if (label.equals("Plan for Today")) {
                backgroundColor.add("#007bff");
                values.add(rankCount.get(1));
            }
            if (label.equals("Carry Forward")) {
                backgroundColor.add("#ffc107");
                values.add(rankCount.get(2));
            }
            if (label.equals("Untouched")) {
                backgroundColor.add("#dc3545");
                values.add(rankCount.get(3));
            }
            if (label.equals("Plan for Future")) {
                backgroundColor.add("#6c757d");
                values.add(rankCount.get(4));
            }
            if (label.equals("Normal")) {
                backgroundColor.add("White");
                values.add(rankCount.get(5));
            }

        }

        LOGGER.info("backgroundColor" + backgroundColor);
        LOGGER.info("labelsChartLead" + labels);
        LeadStatusData data = new LeadStatusData();
        data.setData(values);
        data.setBackgroundColor(backgroundColor);
        data.setLabel("DataSet 1");

        PieLables label = new PieLables();
        label.setFontColor("black");
        label.setFontSize(15);

        Legend legend = new Legend();
        legend.setLabels(label);
        legend.setPosition("left");

        List<LeadStatusData> dataList = new ArrayList<>();
        dataList.add(data);

        DataLeadModel datasets = new DataLeadModel();
        datasets.setDatasets(dataList);
        datasets.setLabels(labels);

        OptionModel om = new OptionModel();
        om.setLegend(legend);

        cm.setType("pie");
        cm.setData(datasets);
        cm.setOptions(om);

        return cm;
    }

    @RequestMapping(value = "/franchiseVisit", method = RequestMethod.GET)
    public String franchiseVisit(HttpServletRequest request, @RequestParam(name = "email", required = false) String email, Model model) throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        AuthUser authUser = authRepository.selectByEmailOrMobile(loginDetails.getEmailId());

        List<Integer> salesPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_SALES).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());
        List<Integer> rbmPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM).stream().map(x -> x.getAuthUserId()).collect(Collectors.toList());

        salesPositionsAuthIds.addAll(rbmPositionsAuthIds);

        List<Integer> allReportees = authService.getAllReportees(authUser.getId());

        Set<Integer> empHierarchy = allReportees.stream().filter(x -> salesPositionsAuthIds.contains(x)).collect(Collectors.toSet());

        List<AuthUser> authUsers = authRepository.selectByIds(new ArrayList<>(empHierarchy));

        Map<Integer, String> monthValueMap = new HashMap<>();
        for (int i = 0; i <= 5; i++) {
            LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).minusMonths(i);
            monthValueMap.put(i, startOfMonth.format(DateTimeFormatter.ofPattern("MMM''uu")));
        }

        model.addAttribute("authUsers", authUsers);
        model.addAttribute("monthValueMap", monthValueMap);

        return "franchise-visit";

    }

    @RequestMapping(value = "/getFranchiseVisit", method = RequestMethod.GET)
    public String getFranchiseVisit(HttpServletRequest request, @RequestParam(name = "authId", required = false) int authId, int yearMonth, Model model) throws Exception {

        LocalDateTime startDate = LocalDate.now().minusMonths(8).withDayOfMonth(1).atStartOfDay();
        LocalDateTime endDate = startDate.plusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay();

        DateRangeModel drm = DateRangeModel.of(startDate, endDate);

        List<FranchiseeVisit> visits = franchiseeVisitRepository.selectByAuthUserAndDateRange(drm, authId);

        if (!visits.isEmpty()) {

            Map<Integer, List<FranchiseeVisit>> franchiseeVisitMap = visits.stream().collect(Collectors.groupingBy(x -> x.getScheduleTimestamp().getDayOfMonth()));

            model.addAttribute("franchiseeVisitMap", franchiseeVisitMap);

        }

        model.addAttribute("visits", visits);
        model.addAttribute("monthLength", startDate.toLocalDate().lengthOfMonth());

        // Calender

        int Year = startDate.getYear(); // year
        int startDayOfMonth = 5;
        int spaces = startDayOfMonth;

        int month = startDate.getMonthValue();

        int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        LOGGER.info("visits {} ", visits);

        if ((((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0)) && month == 2) {
            days[month] = 29;
        }

        spaces = (days[month - 1] + spaces) % 7;

        model.addAttribute("month", month);
        model.addAttribute("spaces", spaces);
        model.addAttribute("days", days);

        return "franchise-visit-container";

    }

    @RequestMapping(value = "/getFranchiseeActivity", method = RequestMethod.GET)
    public String getFranchiseeActivity(HttpServletRequest request, int visitId, Model model) throws Exception {

        List<FranchiseeActivity> franchiseeActivities = franchiseeActivityRepository.selectByFranchiseeVisitId(visitId);

        FranchiseeVisit franchiseeVisit = franchiseeVisitRepository.selectById(visitId);

        Map<Integer, AuthUser> authIdAndAuthUserMap = authRepository.selectAll().stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
        model.addAttribute("authIdAndAuthUserMap", authIdAndAuthUserMap);

        model.addAttribute("franchiseeVisit", franchiseeVisit);
        model.addAttribute("franchiseeActivity", franchiseeActivities.get(0));

        return "franchie-visit-detail";

    }

    @RequestMapping(value = "/indent/today_target", method = RequestMethod.GET)
    public String todayTarget(HttpServletRequest request, Model model) throws Exception {
        List<RBMPerformanceSummaryModel> summaryModels = new ArrayList<>();
        List<Integer> rbmPositionsAuthIds = positionRepository.selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_RBM).stream().filter(x -> Arrays.asList(EscalationType.L1, EscalationType.L2).contains(x.getEscalationType())).map(x -> x.getAuthUserId()).distinct().collect(Collectors.toList());
        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
        List<TeamCommitmentModel> teamCommitmentModels = partnerCollectionPlanRepository.selectTeamCommitmentByDate(LocalDate.now());
        Map<Integer, Double> rbmSecondaryTargetMap = teamCommitmentModels.stream().filter(x -> rbmPositionsAuthIds.contains(x.getAuthId())).collect(Collectors.groupingBy(x -> x.getAuthId(), Collectors.summingDouble(x -> x.getTotalTarget() == null ? 0 : x.getTotalTarget())));
        Map<Integer, Double> rbmSecondaryMap = teamCommitmentModels.stream().filter(x -> rbmPositionsAuthIds.contains(x.getAuthId())).collect(Collectors.groupingBy(x -> x.getAuthId(), Collectors.summingDouble(x -> x.getTotalAchievement() == null ? 0 : x.getTotalAchievement())));
        LocalDateTime startDate = LocalDate.now().atStartOfDay();
        for (int rbmAuthId : rbmPositionsAuthIds) {
            RBMPerformanceSummaryModel rbmPerformanceSummaryModel = new RBMPerformanceSummaryModel();
            rbmPerformanceSummaryModel.setAuthId(rbmAuthId);
            AuthUser authUser = authRepository.selectById(rbmAuthId);
            rbmPerformanceSummaryModel.setAuthName(authUser.getFullName());
            List<Integer> fofoIds = new ArrayList<>(storeGuyMap.get(authUser.getEmailId()));

            if (fofoIds.size() > 0) {
                fofoIds = fofoStoreRepository.selectByRetailerIds(fofoIds).stream().filter(x -> !x.isInternal()).map(x -> x.getId()).collect(Collectors.toList());

                /*
                 * Map<Integer, PartnerCollectionPlanModel> foundCollectionMap =
                 * partnerCollectionService .getCollectionMap(fofoIds, startDate);
                 */

                List<Integer> remarkIds = partnerCollectionRemarkRepository.selectMaxRemarkId(fofoIds);

                LOGGER.info("remarkIds {}", remarkIds);

                long todayOverallCall = 0;
                if (!remarkIds.isEmpty()) {
                    todayOverallCall = partnerCollectionRemarkRepository.selectByIds(remarkIds).stream().filter(x -> x.getCreateTimestamp().toLocalDate().equals(LocalDate.now())).collect(Collectors.counting());

                }

                Map<Integer, PartnerCollectionPlanModel> collectionMap = partnerCollectionService.getCollectionMap(fofoIds, startDate);

                ChartLeadModel cm = this.getCollectionCount(collectionMap.values().stream().collect(Collectors.toList()));

                long collectionTarget = collectionMap.values().stream().filter(x -> x.getTargetPlan() != null).collect(Collectors.summingLong(x -> x.getTargetPlan()));
                long collection = collectionMap.values().stream().filter(
                        x -> x.getTargetPlan() != null && x.getTargetPlan() != 0 && x.getAchievementPlan() != null).collect(Collectors.summingLong(x -> x.getAchievementPlan()));
                rbmPerformanceSummaryModel.setChartLeadModel(cm);
                rbmPerformanceSummaryModel.setPartnersCommunicated(todayOverallCall);
                rbmPerformanceSummaryModel.setCollectionTarget(collectionTarget);
                rbmPerformanceSummaryModel.setCollection(collection);
                rbmPerformanceSummaryModel.setSecondaryTarget(rbmSecondaryTargetMap.get(rbmAuthId) == null ? 0 : rbmSecondaryTargetMap.get(rbmAuthId).floatValue());
                rbmPerformanceSummaryModel.setSecondary(
                        rbmSecondaryMap.get(rbmAuthId) == null ? 0 : rbmSecondaryMap.get(rbmAuthId).floatValue());
                summaryModels.add(rbmPerformanceSummaryModel);
                // cm.getData().getDatasets().get(0).getData().;
                // cm.getData().getDatasets().get(0).getBackgroundColor();
                // cm.getData().getLabels()

            }
        }
        model.addAttribute("summaryModels", summaryModels);
        return "today_target";
    }

    @RequestMapping(value = "/visitPlan", method = RequestMethod.GET)
    public String visitPlan(HttpServletRequest request, Model model) throws Exception {

        return "visit-request-plan";
    }

    @RequestMapping(value = "/visit/getVisitPlan", method = RequestMethod.GET)
    public String getVisitPlan(HttpServletRequest request, @RequestParam LocalDate date, Model model) throws Exception {
        List<VisitRequest> visitRequests = visitRequestRepository.selectByAuthIdAndDate(date);

        List<Integer> leadIds = visitRequests.stream().filter(x -> x.getVisitType().equals("lead")).map(x -> x.getVisitId()).collect(Collectors.toList());
        Map<Integer, Lead> leadMap = new HashMap<>();
        if (!leadIds.isEmpty()) {
            List<Lead> leads = leadRepository.selectAllByIds(leadIds);

            for (Lead lead : leads) {
                List<LeadActivity> leadActivities = leadActivityRepository.selectBYLeadId(lead.getId());
                lead.setScheduledTimestamp(leadActivities.get(0).getSchelduleTimestamp());
                lead.setLeadActivity(leadActivities.get(0));

                leadMap.put(lead.getId(), lead);
            }

        }
        List<Integer> franchiseeIds = visitRequests.stream().filter(x -> x.getVisitType().equals("franchiseeVisit")).map(x -> x.getVisitId()).collect(Collectors.toList());
        Map<Integer, FranchiseeVisit> franchiseeVisitsMap = new HashMap<>();
        if (!franchiseeIds.isEmpty()) {
            List<FranchiseeVisit> franchiseeVisits = franchiseeVisitRepository.selectAllByIds(franchiseeIds);
            LOGGER.info("franchiseeVisits {}", franchiseeVisits);

            for (FranchiseeVisit franchiseeVisit : franchiseeVisits) {
                List<FranchiseeActivity> franchiseeActivities = franchiseeActivityRepository.selectByFranchiseeVisitId(franchiseeVisit.getId());
                LOGGER.info("franchiseeActivities {}", franchiseeActivities);

                franchiseeVisit.setScheduleTimestamp(franchiseeActivities.get(0).getSchelduleTimestamp());
                franchiseeVisit.setFranchiseeActivity(franchiseeActivities.get(0));

                franchiseeVisitsMap.put(franchiseeVisit.getId(), franchiseeVisit);
            }

        }

        Map<Integer, List<VisitRequest>> visitRequestMap = visitRequests.stream().collect(Collectors.groupingBy(x -> x.getCreatedBy()));
        List<AuthUser> authUsers = authRepository.selectAllActiveUser();
        List<UserVisitModel> userVisits = new ArrayList<>();

        for (AuthUser authUser : authUsers) {

            List<VisitRequest> authVisitRequests = visitRequestMap.get(authUser.getId());

            if (authVisitRequests != null) {
                UserVisitModel userVisitModel = new UserVisitModel();
                userVisitModel.setAuthUser(authUser.getFullName());
                List<VisitDescriptionModel> visitDescriptions = new ArrayList<>();

                for (VisitRequest authVisitRequest : authVisitRequests) {
                    VisitDescriptionModel visitDescriptionModel = new VisitDescriptionModel();
                    visitDescriptionModel.setVisitId(authVisitRequest.getVisitId());

                    if (authVisitRequest.getVisitType().equals("lead")) {
                        Lead lead = leadMap.get(authVisitRequest.getVisitId());

                        visitDescriptionModel.setVisitName(lead.getFirstName());
                        visitDescriptionModel.setCity(lead.getCity());
                        visitDescriptionModel.setState(lead.getState());
                        visitDescriptionModel.setScheduleTime(lead.getScheduledTimestamp());
                        visitDescriptionModel.setRemarks(lead.getLeadActivity().getRemark());

                    } else {
                        FranchiseeVisit franchiseeVisit = franchiseeVisitsMap.get(authVisitRequest.getVisitId());
                        CustomRetailer customRetailer = retailerService.getFofoRetailer(franchiseeVisit.getFofoId());

                        visitDescriptionModel.setVisitName(franchiseeVisit.getPartnerName());
                        visitDescriptionModel.setCity(customRetailer.getAddress().getCity());
                        visitDescriptionModel.setState(customRetailer.getAddress().getState());
                        visitDescriptionModel.setScheduleTime(franchiseeVisit.getFranchiseeActivity().getSchelduleTimestamp());
                        visitDescriptionModel.setRemarks(franchiseeVisit.getAgenda());

                    }

                    if (authVisitRequest.getActionedBy() != 0) {
                        AuthUser au = authRepository.selectById(authVisitRequest.getActionedBy());

                        visitDescriptionModel.setActionBy(au.getFullName());
                    }
                    visitDescriptionModel.setStatus(authVisitRequest.getStatus());
                    visitDescriptionModel.setVisitType(authVisitRequest.getVisitType());
                    visitDescriptions.add(visitDescriptionModel);
                }

                userVisitModel.setVisitDescriptions(visitDescriptions);
                userVisits.add(userVisitModel);
            }

        }

        model.addAttribute("userVisits", userVisits);

        return "visit-request-plan";
    }
}