import java.nio.charset.CharsetEncoder
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.UUID
import java.util.stream.Collectors
import java.util.Map.Entry

import org.slf4j.Logger
import org.slf4j.LoggerFactory

import com.gridnine.xtrip.common.Environment
import com.gridnine.xtrip.common.model.EntityContainer
import com.gridnine.xtrip.common.model.EntityReference
import com.gridnine.xtrip.common.model.asset.AssetsStorage
import com.gridnine.xtrip.common.model.assets.UserAccount
import com.gridnine.xtrip.common.model.dict.ContractType
import com.gridnine.xtrip.common.model.entity.EntityStorage
import com.gridnine.xtrip.common.model.profile.BaseProfile
import com.gridnine.xtrip.common.model.profile.Card
import com.gridnine.xtrip.common.model.profile.CardIndex
import com.gridnine.xtrip.common.model.profile.Contract
import com.gridnine.xtrip.common.model.profile.ContractCustomerIndex
import com.gridnine.xtrip.common.model.profile.Organization
import com.gridnine.xtrip.common.model.profile.OrganizationType
import com.gridnine.xtrip.common.model.profile.Person
import com.gridnine.xtrip.common.model.profile.PersonEmployment
import com.gridnine.xtrip.common.search.SearchCriterion
import com.gridnine.xtrip.common.search.SearchQuery
import com.gridnine.xtrip.common.search.SortOrder
import com.gridnine.xtrip.common.security.acl.principal.AclGroup
import com.gridnine.xtrip.common.security.acl.principal.AclUser
import com.gridnine.xtrip.common.util.MiscUtil.Pair
import com.gridnine.xtrip.common.util.TextUtil

Logger logger = LoggerFactory.getLogger('groovy-script')

logger.info("Account and acl user compare: statistics started")

Map<String, UserAccount> accounts = new HashMap()
Map<String, AclUser> users = new HashMap()
Map<String, AclGroup> groups = new HashMap()

List<String> orphanAccounts = new ArrayList()
List<String> orphanUsers = new ArrayList()
List<String> matchPrincipals = new ArrayList()

try {

    accounts = AssetsStorage.get().search(UserAccount.class, new SearchQuery()).getData().stream().collect(Collectors.toMap({item -> item.getLoginName()}, {item -> item}))
    users = AssetsStorage.get().search(AclUser.class, new SearchQuery()).getData().stream().collect(Collectors.toMap({item -> item.getId()}, {item -> item}))
    groups = AssetsStorage.get().search(AclGroup.class, new SearchQuery()).getData().stream().collect(Collectors.toMap({item -> item.getId()}, {item -> item}))
    
    logger.info("Account and acl user compare: found " + accounts.size() + " accounts")
    logger.info("Account and acl user compare: found " + users.size() + " users")
    logger.info("Account and acl user compare: found " + groups.size() + " groups")
    
    orphanAccounts = accounts.keySet().stream().filter({item -> users.get(item) == null}).collect(Collectors.toList())
    orphanUsers = users.keySet().stream().filter({item -> accounts.get(item) == null}).collect(Collectors.toList())
    matchPrincipals = users.keySet().stream().filter({item -> groups.get(item) != null}).collect(Collectors.toList())

    logger.info("Account and acl user compare: found " + orphanAccounts.size() + " orphan accounts")
    logger.info("Account and acl user compare: found " + orphanUsers.size() + " orphan users")
    logger.info("Account and acl user compare: found " + matchPrincipals.size() + " matched principals")

    Files.write(Files.createDirectories(Environment.getDataFolder().toPath().resolve('export/compare')).resolve('orphan_accounts.csv'), orphanAccounts, StandardCharsets.UTF_8)
    Files.write(Files.createDirectories(Environment.getDataFolder().toPath().resolve('export/compare')).resolve('orphan_users.csv'), orphanUsers, StandardCharsets.UTF_8)
    Files.write(Files.createDirectories(Environment.getDataFolder().toPath().resolve('export/compare')).resolve('match_principals.csv'), matchPrincipals, StandardCharsets.UTF_8)
    
} catch(Throwable t) {
    logger.error('', t)
}

logger.info("Account and acl user compare: statistics finished")
