/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.syncope.fit.core;

import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import javax.ws.rs.core.Response;
import javax.xml.ws.WebServiceException;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.log.AuditEntry;
import org.apache.syncope.common.lib.log.EventCategory;
import org.apache.syncope.common.lib.log.LogAppender;
import org.apache.syncope.common.lib.log.LogStatement;
import org.apache.syncope.common.lib.log.LoggerTO;
import org.apache.syncope.common.lib.to.ConnInstanceTO;
import org.apache.syncope.common.lib.to.ConnPoolConfTO;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.PushTaskTO;
import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
import org.apache.syncope.common.lib.types.AuditLoggerName;
import org.apache.syncope.common.lib.types.LoggerLevel;
import org.apache.syncope.common.lib.types.LoggerType;
import org.apache.syncope.common.lib.types.MatchingRule;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.UnmatchingRule;
import org.apache.syncope.common.rest.api.LoggerWrapper;
import org.apache.syncope.common.rest.api.beans.AuditQuery;
import org.apache.syncope.common.rest.api.beans.ReconQuery;
import org.apache.syncope.core.logic.ConnectorLogic;
import org.apache.syncope.core.logic.ReportLogic;
import org.apache.syncope.core.logic.ResourceLogic;
import org.apache.syncope.core.logic.GroupLogic;
import org.apache.syncope.core.logic.UserLogic;
import org.apache.syncope.fit.AbstractITCase;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class LoggerITCase extends AbstractITCase {

    @Test
    public void listMemoryAppenders() {
        List<LogAppender> memoryAppenders = loggerService.memoryAppenders();
        assertNotNull(memoryAppenders);
        assertFalse(memoryAppenders.isEmpty());
        memoryAppenders.forEach(appender -> {
            assertNotNull(appender);
            assertNotNull(appender.getName());
        });
    }

    @Test
    public void lastStatements() {
        List<LogStatement> statements = loggerService.getLastLogStatements("connid");
        assertNotNull(statements);
        assertFalse(statements.isEmpty());

        LogStatement statement = statements.get(0);
        assertNotNull(statement);
        assertNotNull(statement.getLoggerName());
        assertNotNull(statement.getLevel());
        assertNotNull(statement.getMessage());
        assertNotNull(statement.getTimeMillis());
    }

    @Test
    public void listLogs() {
        List<LoggerTO> loggers = loggerService.list(LoggerType.LOG);
        assertNotNull(loggers);
        assertFalse(loggers.isEmpty());
        loggers.forEach(Assertions::assertNotNull);
    }

    @Test
    public void listAudits() throws ParseException {
        List<LoggerTO> audits = loggerService.list(LoggerType.AUDIT);
        assertNotNull(audits);
        assertFalse(audits.isEmpty());
        for (LoggerTO audit : audits) {
            assertNotNull(AuditLoggerName.fromLoggerName(audit.getKey()));
        }
    }

    @Test
    public void setLevel() {
        List<LoggerTO> loggers = loggerService.list(LoggerType.LOG);
        assertNotNull(loggers);
        int startSize = loggers.size();

        LoggerTO logger = new LoggerTO();
        logger.setKey("TEST");
        logger.setLevel(LoggerLevel.INFO);
        loggerService.update(LoggerType.LOG, logger);
        logger = loggerService.read(LoggerType.LOG, logger.getKey());
        assertNotNull(logger);
        assertEquals(LoggerLevel.INFO, logger.getLevel());

        loggers = loggerService.list(LoggerType.LOG);
        assertNotNull(loggers);
        assertEquals(startSize + 1, loggers.size());

        // TEST Delete
        loggerService.delete(LoggerType.LOG, "TEST");
        loggers = loggerService.list(LoggerType.LOG);
        assertNotNull(loggers);
        assertEquals(startSize, loggers.size());
    }

    @Test
    public void enableDisableAudit() {
        AuditLoggerName auditLoggerName = new AuditLoggerName(
                EventCategoryType.LOGIC,
                ReportLogic.class.getSimpleName(),
                null,
                "deleteExecution",
                AuditElements.Result.FAILURE);

        List<AuditLoggerName> audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
        assertNotNull(audits);
        assertFalse(audits.contains(auditLoggerName));

        LoggerTO loggerTO = new LoggerTO();
        loggerTO.setKey(auditLoggerName.toLoggerName());
        loggerTO.setLevel(LoggerLevel.DEBUG);
        loggerService.update(LoggerType.AUDIT, loggerTO);

        audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
        assertNotNull(audits);
        assertTrue(audits.contains(auditLoggerName));

        loggerService.delete(LoggerType.AUDIT, auditLoggerName.toLoggerName());

        audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
        assertNotNull(audits);
        assertFalse(audits.contains(auditLoggerName));
    }

    @Test
    public void listAuditEvents() {
        final List<EventCategory> events = loggerService.events();

        boolean found = false;

        for (EventCategory eventCategoryTO : events) {
            if (UserLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
                assertEquals(EventCategoryType.LOGIC, eventCategoryTO.getType());
                assertTrue(eventCategoryTO.getEvents().contains("create"));
                assertTrue(eventCategoryTO.getEvents().contains("search"));
                assertFalse(eventCategoryTO.getEvents().contains("doCreate"));
                assertFalse(eventCategoryTO.getEvents().contains("setStatusOnWfAdapter"));
                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
                found = true;
            }
        }
        assertTrue(found);

        found = false;
        for (EventCategory eventCategoryTO : events) {
            if (GroupLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
                assertEquals(EventCategoryType.LOGIC, eventCategoryTO.getType());
                assertTrue(eventCategoryTO.getEvents().contains("create"));
                assertTrue(eventCategoryTO.getEvents().contains("search"));
                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
                found = true;
            }
        }
        assertTrue(found);

        found = false;
        for (EventCategory eventCategoryTO : events) {
            if (ResourceLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
                assertEquals(EventCategoryType.LOGIC, eventCategoryTO.getType());
                assertTrue(eventCategoryTO.getEvents().contains("create"));
                assertTrue(eventCategoryTO.getEvents().contains("read"));
                assertTrue(eventCategoryTO.getEvents().contains("delete"));
                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
                found = true;
            }
        }
        assertTrue(found);

        found = false;
        for (EventCategory eventCategoryTO : events) {
            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
                if (RESOURCE_NAME_LDAP.equals(eventCategoryTO.getSubcategory())
                        && EventCategoryType.PULL == eventCategoryTO.getType()) {

                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
                    found = true;
                }
            }
        }
        assertTrue(found);

        found = false;
        for (EventCategory eventCategoryTO : events) {
            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
                if (RESOURCE_NAME_CSV.equals(eventCategoryTO.getSubcategory())
                        && EventCategoryType.PROPAGATION == eventCategoryTO.getType()) {

                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.CREATE.name().toLowerCase()));
                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.UPDATE.name().toLowerCase()));
                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
                    found = true;
                }
            }
        }
        assertTrue(found);

        found = false;
        for (EventCategory eventCategoryTO : events) {
            if (EventCategoryType.TASK == eventCategoryTO.getType()
                    && "PullJobDelegate".equals(eventCategoryTO.getCategory())) {
                found = true;
            }
        }
        assertTrue(found);
    }

    private static void checkLogFileFor(
            final Path path,
            final Function<String, Boolean> checker,
            final int maxWaitSeconds)
            throws IOException {

        await().atMost(maxWaitSeconds, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
            try {
                return checker.apply(Files.readString(path, StandardCharsets.UTF_8));
            } catch (Exception e) {
                return false;
            }
        });
    }

    @Test
    public void saveAuditEvent() {
        AuditEntry auditEntry = new AuditEntry();
        auditEntry.setWho("syncope-user " + UUID.randomUUID().toString());
        auditEntry.setLogger(new AuditLoggerName(
                EventCategoryType.WA,
                "LoggerLogic",
                AuditElements.AUTHENTICATION_CATEGORY.toUpperCase(),
                "validate",
                AuditElements.Result.SUCCESS));
        auditEntry.setDate(new Date());
        auditEntry.setBefore(UUID.randomUUID().toString());
        auditEntry.setOutput(UUID.randomUUID().toString());
        assertDoesNotThrow(() -> loggerService.create(auditEntry));

        PagedResult<AuditEntry> events = loggerService.search(new AuditQuery.Builder().
                size(1).
                type(auditEntry.getLogger().getType()).
                category(auditEntry.getLogger().getCategory()).
                subcategory(auditEntry.getLogger().getSubcategory()).
                event(auditEntry.getLogger().getEvent()).
                result(auditEntry.getLogger().getResult()).
                build());
        assertNotNull(events);
        assertEquals(1, events.getSize());
    }
    
    @Test
    public void saveAuthEvent() {
        AuditEntry auditEntry = new AuditEntry();
        auditEntry.setWho("syncope-user " + UUID.randomUUID().toString());
        auditEntry.setLogger(new AuditLoggerName(
                EventCategoryType.WA,
                "LoggerLogic",
                "AuthenticationEvent",
                "auth",
                AuditElements.Result.SUCCESS));
        auditEntry.setDate(new Date());
        auditEntry.setBefore(UUID.randomUUID().toString());
        auditEntry.setOutput(UUID.randomUUID().toString());
        assertDoesNotThrow(() -> loggerService.create(auditEntry));

        PagedResult<AuditEntry> events = loggerService.search(new AuditQuery.Builder().
                size(1).
                type(auditEntry.getLogger().getType()).
                category(auditEntry.getLogger().getCategory()).
                subcategory(auditEntry.getLogger().getSubcategory()).
                event(auditEntry.getLogger().getEvent()).
                result(auditEntry.getLogger().getResult()).
                build());
        assertNotNull(events);
        assertEquals(1, events.getSize());
    }

    @Test
    public void customAuditAppender() throws IOException, InterruptedException {
        AuditLoggerName auditLoggerResUpd = new AuditLoggerName(
                EventCategoryType.LOGIC,
                ResourceLogic.class.getSimpleName(),
                null,
                "update",
                AuditElements.Result.SUCCESS);
        LoggerTO resUpd = new LoggerTO();
        resUpd.setKey(auditLoggerResUpd.toLoggerName());

        AuditLoggerName auditLoggerConnUpd = new AuditLoggerName(
                EventCategoryType.LOGIC,
                ConnectorLogic.class.getSimpleName(),
                null,
                "update",
                AuditElements.Result.SUCCESS);
        LoggerTO connUpd = new LoggerTO();
        connUpd.setKey(auditLoggerConnUpd.toLoggerName());

        try (InputStream propStream = getClass().getResourceAsStream("/test.properties")) {
            Properties props = new Properties();
            props.load(propStream);

            Path auditFilePath = Paths.get(props.getProperty("test.log.dir")
                    + File.separator + "audit_for_Master_file.log");
            Files.write(auditFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);

            Path auditNoRewriteFilePath = Paths.get(props.getProperty("test.log.dir")
                    + File.separator + "audit_for_Master_norewrite_file.log");
            Files.write(auditNoRewriteFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);

            // 1. Enable audit for resource update -> catched by FileRewriteAuditAppender
            resUpd.setLevel(LoggerLevel.DEBUG);
            loggerService.update(LoggerType.AUDIT, resUpd);

            // 2. Enable audit for connector update -> NOT catched by FileRewriteAuditAppender
            connUpd.setLevel(LoggerLevel.DEBUG);
            loggerService.update(LoggerType.AUDIT, connUpd);

            // 3. check that resource update is transformed and logged onto an audit file.
            ResourceTO resource = resourceService.read(RESOURCE_NAME_CSV);
            assertNotNull(resource);
            resource.setPropagationPriority(100);
            resourceService.update(resource);

            ConnInstanceTO connector = connectorService.readByResource(RESOURCE_NAME_CSV, null);
            assertNotNull(connector);
            connector.setPoolConf(new ConnPoolConfTO());
            connectorService.update(connector);

            // check audit_for_Master_file.log, it should contain only a static message
            checkLogFileFor(
                    auditFilePath,
                    content -> content.contains(
                            "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
                            + " - This is a static test message"),
                    10);

            // nothing expected in audit_for_Master_norewrite_file.log instead
            checkLogFileFor(
                    auditNoRewriteFilePath,
                    content -> !content.contains(
                            "DEBUG Master.syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]"
                            + " - This is a static test message"),
                    10);

            // clean audit_for_Master_file.log
            Files.write(auditFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
            loggerService.delete(LoggerType.AUDIT, "syncope.audit.[LOGIC]:[ResourceLogic]:[]:[update]:[SUCCESS]");

            resource = resourceService.read(RESOURCE_NAME_CSV);
            assertNotNull(resource);
            resource.setPropagationPriority(200);
            resourceService.update(resource);

            // check that nothing has been written to audit_for_Master_file.log
            assertTrue(StringUtils.isEmpty(Files.readString(auditFilePath, StandardCharsets.UTF_8)));
        } catch (IOException e) {
            fail("Unable to read/write log files", e);
        } finally {
            resUpd.setLevel(LoggerLevel.ERROR);
            loggerService.update(LoggerType.AUDIT, resUpd);

            connUpd.setLevel(LoggerLevel.ERROR);
            loggerService.update(LoggerType.AUDIT, connUpd);
        }
    }

    @Test
    public void issueSYNCOPE708() {
        try {
            loggerService.read(LoggerType.LOG, "notExists");
            fail("Reading non-existing logger, it should go in exception");
        } catch (final WebServiceException ex) {
            fail("Exception is WebServiceException but it should be SyncopeClientException");
        } catch (final SyncopeClientException ex) {
            assertEquals(Response.Status.NOT_FOUND, ex.getType().getResponseStatus());
        }
    }

    @Test
    public void issueSYNCOPE976() {
        List<EventCategory> events = loggerService.events();
        assertNotNull(events);

        EventCategory userLogic = events.stream().
                filter(object -> "UserLogic".equals(object.getCategory())).findAny().get();
        assertNotNull(userLogic);
        assertEquals(1, userLogic.getEvents().stream().filter("create"::equals).count());
    }

    @Test
    public void issueSYNCOPE1446() {
        AuditLoggerName createSuccess = new AuditLoggerName(
                AuditElements.EventCategoryType.PROPAGATION,
                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
                RESOURCE_NAME_DBSCRIPTED,
                "create",
                AuditElements.Result.SUCCESS);
        AuditLoggerName createFailure = new AuditLoggerName(
                AuditElements.EventCategoryType.PROPAGATION,
                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
                RESOURCE_NAME_DBSCRIPTED,
                "create",
                AuditElements.Result.FAILURE);
        AuditLoggerName updateSuccess = new AuditLoggerName(
                AuditElements.EventCategoryType.PROPAGATION,
                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
                RESOURCE_NAME_DBSCRIPTED,
                "update",
                AuditElements.Result.SUCCESS);
        AuditLoggerName updateFailure = new AuditLoggerName(
                AuditElements.EventCategoryType.PROPAGATION,
                AnyTypeKind.ANY_OBJECT.name().toLowerCase(),
                RESOURCE_NAME_DBSCRIPTED,
                "update",
                AuditElements.Result.FAILURE);
        try {
            // 1. setup audit for propagation
            LoggerTO loggerTO = new LoggerTO();
            loggerTO.setKey(createSuccess.toLoggerName());
            loggerTO.setLevel(LoggerLevel.DEBUG);
            loggerService.update(LoggerType.AUDIT, loggerTO);

            loggerTO.setKey(createFailure.toLoggerName());
            loggerService.update(LoggerType.AUDIT, loggerTO);

            loggerTO.setKey(updateSuccess.toLoggerName());
            loggerService.update(LoggerType.AUDIT, loggerTO);

            loggerTO.setKey(updateFailure.toLoggerName());
            loggerService.update(LoggerType.AUDIT, loggerTO);

            // 2. push on resource
            PushTaskTO pushTask = new PushTaskTO();
            pushTask.setPerformCreate(true);
            pushTask.setPerformUpdate(true);
            pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
            pushTask.setMatchingRule(MatchingRule.UPDATE);
            reconciliationService.push(new ReconQuery.Builder(PRINTER, RESOURCE_NAME_DBSCRIPTED).
                    anyKey("fc6dbc3a-6c07-4965-8781-921e7401a4a5").build(), pushTask);
        } catch (Exception e) {
            LOG.error("Unexpected exception", e);
            fail(e::getMessage);
        } finally {
            try {
                loggerService.delete(LoggerType.AUDIT, createSuccess.toLoggerName());
            } catch (Exception e) {
                // ignore
            }
            try {
                loggerService.delete(LoggerType.AUDIT, createFailure.toLoggerName());
            } catch (Exception e) {
                // ignore
            }
            try {
                loggerService.delete(LoggerType.AUDIT, updateSuccess.toLoggerName());
            } catch (Exception e) {
                // ignore
            }
            try {
                loggerService.delete(LoggerType.AUDIT, updateFailure.toLoggerName());
            } catch (Exception e) {
                // ignore
            }
        }
    }
}
