package com.utopiaindustries.service;

import com.utopiaindustries.dao.ctp.*;
import com.utopiaindustries.model.ctp.*;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DashboardService {

    private final InventoryTransactionLegDAO inventoryTransactionLegDAO;
    private final JobCardDAO jobCardDAO;
    private final FinishedItemDAO finishedItemDAO;
    private final StitchingOfflineItemDAO stitchingOfflineItemDAO;
    private final InventoryAccountDAO inventoryAccountDAO;
    private final PackagingItemsDAO packagingItemsDAO;


    public DashboardService(InventoryTransactionLegDAO inventoryTransactionLegDAO, JobCardDAO jobCardDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, InventoryAccountDAO inventoryAccountDAO, PackagingItemsDAO packagingItemsDAO) {
        this.inventoryTransactionLegDAO = inventoryTransactionLegDAO;
        this.jobCardDAO = jobCardDAO;
        this.finishedItemDAO = finishedItemDAO;
        this.stitchingOfflineItemDAO = stitchingOfflineItemDAO;
        this.inventoryAccountDAO = inventoryAccountDAO;
        this.packagingItemsDAO = packagingItemsDAO;
    }

    public Map<String, Float> getPhasesProgressDayWise(String lineNo) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        String cuttingAccount = "CUTTING ACCOUNT " + lineNo;
        String stitchingAccount = "STITCHING ACCOUNT " + lineNo;
        String finishingAccount = "FINISHING ACCOUNT " + lineNo;
        String packagingAccount = "A GRADE ACCOUNT " + lineNo;

        String startDate1 = LocalDateTime.now().withHour(0).withMinute(0).withSecond(1).format(formatter);
        String endDate1 = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).format(formatter);
        String startDateWithHour = LocalDateTime.now().minusHours(1).format(formatter);
        String endDateWithHour = LocalDateTime.now().format(formatter);


        HashMap<String, Float> progress = new HashMap<>();

        List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findAll();

        Map<String, Integer> inventoryAccountMap = inventoryAccounts.stream()
                .filter(e -> cuttingAccount.equals(e.getTitle()) ||
                        stitchingAccount.equals(e.getTitle()) ||
                        finishingAccount.equals(e.getTitle()) ||
                        packagingAccount.equals(e.getTitle()))
                .collect(Collectors.toMap(InventoryAccount::getTitle, e -> (int) e.getId()));


        List<Long> stitchingItemIds = inventoryTransactionLegDAO.getParentIDsOFRemainingINVENTORY("STITCHING_OFFLINE", inventoryAccountMap.get(stitchingAccount));
        List<Long> finishing = inventoryTransactionLegDAO.getInParentIdIdByDate("FINISHED_ITEM", inventoryAccountMap.get(finishingAccount));

        List<Long> packagingItemIDs = inventoryTransactionLegDAO.getParentIDsOFRemainingINVENTORY("PACKAGING", inventoryAccountMap.get(packagingAccount));

        Long approvedStitchingOfflineItems = 0L;
        Long qcReject = 0L;
        if (stitchingItemIds != null && !stitchingItemIds.isEmpty()) {
            approvedStitchingOfflineItems = stitchingOfflineItemDAO.findByQCDoneDateApproved(startDate1, endDate1, "APPROVED");
            qcReject = stitchingOfflineItemDAO.findByQCDoneDate(null, endDate1, "REJECT", stitchingItemIds);
        }

        Long alterationPieceFinish = 0L;
        Long rejectFinishedItem = 0L;
        Long washFinishedItem = 0L;
        Long approved = 0L;
        Long operationNotPerformed = 0L;

        if (finishing != null && !finishing.isEmpty()) {
            approved = finishedItemDAO.findByOperationDoneDate(startDate1, endDate1, "APPROVED", finishing);
            operationNotPerformed = finishedItemDAO.findByOperationDoneDate(null, endDate1, "-", finishing);
            rejectFinishedItem = finishedItemDAO.findByOperationDoneDate(null, endDate1, "REJECT", finishing);
            washFinishedItem = finishedItemDAO.findByOperationDoneDate(startDate1, endDate1, "WASHED", finishing);
            alterationPieceFinish = finishedItemDAO.findByOperationDoneDate(null, endDate1, "ALTER", finishing);
        }


        Long packagingItems = 0L;
        Long packagingItemsHourly = 0L;
        if (packagingItemIDs != null && !packagingItemIDs.isEmpty()) {
            packagingItems = packagingItemsDAO.findByDateANDIDs(startDate1, endDate1, packagingItemIDs);
            packagingItemsHourly = packagingItemsDAO.findByDateANDIDs(startDateWithHour, endDateWithHour, packagingItemIDs);
        }

        progress.put("Stitching", (float) approvedStitchingOfflineItems + qcReject);
        progress.put("totalWips", (float) stitchingItemIds.size() - qcReject);
        progress.put("Alteration", (float) qcReject);

        progress.put("finishing", (float) approved + operationNotPerformed);
        progress.put("ALTER", (float) alterationPieceFinish);
        progress.put("Reject", (float) rejectFinishedItem);
        progress.put("wash", (float) washFinishedItem);
        progress.put("packaging", (float) packagingItems);

        progress.put("Shift Achieved", (float) packagingItems);
        progress.put("Efficiency", (float) packagingItems / 1000 * 100);
        progress.put("Hourly Achieved", Float.valueOf(packagingItemsHourly));


        return progress;
    }

    public Map<String, String> getLineDetails(String lineNo) {
        String cuttingAccount = "CUTTING ACCOUNT " + lineNo;
        List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findAll();
        String articleNote = inventoryAccounts.stream()
                .filter(e -> cuttingAccount.equals(e.getTitle()))
                .map(InventoryAccount::getNotes).findFirst().orElse(null);

        HashMap<String, String> details = new HashMap<>();
        List<JobCard> jobCards = jobCardDAO.findAll();
        details.put("Shift Target", 1000 + " Pcs");
        details.put("articleNote", articleNote);
        details.put("Hourly Target", 1000 / 24 + " Pcs");
        details.put("Total Induction", String.valueOf(jobCards.size()));
        details.put("Total Machine", String.valueOf(30));
        details.put("Total Worker", String.valueOf(30));
        details.put("line", "Line " + lineNo);
        return details;
    }
}
