package com.utopiaindustries.service;

import com.utopiaindustries.dao.ctp.InventoryAccountDAO;
import com.utopiaindustries.dao.ctp.ProcessDAO;
import com.utopiaindustries.dao.ctp.UserInventoryAccountDAO;
import com.utopiaindustries.dao.uind.LocationSiteDAO;
import com.utopiaindustries.model.ctp.InventoryAccount;
import com.utopiaindustries.model.ctp.Process;
import com.utopiaindustries.model.ctp.UserInventoryAccount;
import com.utopiaindustries.querybuilder.ctp.InventoryAccountQueryBuilder;
import com.utopiaindustries.util.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class InventoryAccountService {

    private final InventoryAccountDAO inventoryAccountDAO;
    private final ProcessDAO processDAO;
    private final LocationSiteDAO locationSiteDAO;
    private final UserInventoryAccountDAO userInventoryAccountDAO;

    public InventoryAccountService(InventoryAccountDAO inventoryAccountDAO, ProcessDAO processDAO, LocationSiteDAO locationSiteDAO, UserInventoryAccountDAO userInventoryAccountDAO) {
        this.inventoryAccountDAO = inventoryAccountDAO;
        this.processDAO = processDAO;
        this.locationSiteDAO = locationSiteDAO;
        this.userInventoryAccountDAO = userInventoryAccountDAO;
    }

    public List<InventoryAccount> getInventoryAccounts( String id, String title, String active, String createdBy, String startDate, String endDate,
                                                        String siteId, Long count, String parentEntityType, String parentEntityId, boolean isPackaging ){
        List<InventoryAccount> accounts = new ArrayList<>();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<UserInventoryAccount> userInventoryAccounts = userInventoryAccountDAO.findByUsername( authentication.getName() );
        List<Long> userInventoryAccountIds = userInventoryAccounts.stream().map( UserInventoryAccount::getAccountId ).collect(Collectors.toList());
        if( count == null ){
            count = 100L;
        }
        if( StringUtils.isAnyNotNullOrEmpty( id,title, active, createdBy, startDate, endDate, siteId ) ){
            String query = InventoryAccountQueryBuilder.buildQuery(
                    id,
                    title,
                    active,
                    createdBy,
                    startDate,
                    endDate,
                    siteId,
                    count,
                    userInventoryAccountIds,
                    parentEntityType,
                    parentEntityId,
                    isPackaging

            );
            System.out.println( query );
            accounts = inventoryAccountDAO.findByQuery( query );
        } else {
            if( isPackaging ){
                accounts = inventoryAccountDAO.findByIdsAndPackagingAndIdAndLimit( userInventoryAccountIds, count, isPackaging );
            } else {
                accounts = inventoryAccountDAO.findByIdsAndParentTypeAndIdAndLimit( userInventoryAccountIds, count, parentEntityType, parentEntityId );
            }
        }
        return accounts;
    }

    public List<InventoryAccount> findInventoryAccounts(){
        List<InventoryAccount> accounts = inventoryAccountDAO.findAll();
        for( InventoryAccount account : accounts ){
            account.setLocationTitle( locationSiteDAO.find( account.getLocationSiteId() ).getTitle() );
        }
        return accounts;
    }

    public List<InventoryAccount> findInventoryAccountsByFilter(String id, String title, String active, String createdBy, String startDate, String endDate,
                                                        String siteId, Long count){
        List<InventoryAccount> accounts;
        if( StringUtils.isAnyNotNullOrEmpty( id,title, active, createdBy, startDate, endDate, siteId ) ){
            String query = InventoryAccountQueryBuilder.buildQuery(
                    id,
                    title,
                    active,
                    createdBy,
                    startDate,
                    endDate,
                    siteId,
                    count,
                    null,
                    "",
                    "",
                    null

            );
            System.out.println( query );
            accounts = inventoryAccountDAO.findByQuery( query );
        } else {
            accounts = inventoryAccountDAO.findAll();
        }
        for( InventoryAccount account : accounts ){
            account.setLocationTitle( locationSiteDAO.find( account.getLocationSiteId() ).getTitle() );
        }
        return accounts;
    }

    public InventoryAccount createNewAccount(){
        // get login user
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        InventoryAccount account = new InventoryAccount();
        account.setCreatedBy( authentication.getName()  );
        account.setCreatedAt( LocalDateTime.now() );
        return account;
    }

    public void saveAccount( InventoryAccount account ){
        inventoryAccountDAO.save( account );
    }

    public InventoryAccount find( long id ){
       InventoryAccount account =  inventoryAccountDAO.find( id );
       account.setLocationTitle( locationSiteDAO.find( account.getLocationSiteId() ).getTitle() );
       return account;
    }

    public List<Process> getAllProcess(){

        return processDAO.findAll();
    }

    /*
    *  get all
    * */
    public List<InventoryAccount> findInventoryAccounts(  long processId ){
        // get list of accounts tagged to user
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<UserInventoryAccount> userInventoryAccounts = userInventoryAccountDAO.findByUsername( authentication.getName() );
        List<Long> userInventoryAccountIds = userInventoryAccounts.stream().map( UserInventoryAccount::getAccountId ).collect(Collectors.toList());
        return inventoryAccountDAO.findByIdsAndProcessId( userInventoryAccountIds, processId );
    }

    public List<InventoryAccount> findInventoryAccountsForFinishedItems( ){
        // get list of accounts tagged to user
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<UserInventoryAccount> userInventoryAccounts = userInventoryAccountDAO.findByUsername( authentication.getName() );
        List<Long> userInventoryAccountIds = userInventoryAccounts.stream().map( UserInventoryAccount::getAccountId ).collect(Collectors.toList());
        List<Long> processIds = new ArrayList<>();
        processIds.add(6L);
        processIds.add(7L);
        processIds.add(8L);
        return inventoryAccountDAO.findByIdsAndProcessIds( userInventoryAccountIds, processIds );
    }

    public List<InventoryAccount> getAllCuttingAccounts(){
        return inventoryAccountDAO.findByParentEntityTypeAndParentId( "PROCESS", 1L );
    }
}
