/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation.
//     04/12/2016-2.7 Tomas Kraus
//       - 490677: Allow Oracle NoSQL connection to be specified in build properties bundle
package org.eclipse.persistence.testing.tests.jpa.nosql;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.List;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;

import org.eclipse.persistence.eis.interactions.MappedInteraction;
import org.eclipse.persistence.internal.nosql.adapters.nosql.OracleNoSQLOperation;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.nosql.adapters.nosql.OracleNoSQLPlatform;
import org.eclipse.persistence.sessions.DataRecord;
import org.eclipse.persistence.testing.framework.junit.LogTestExecution;
import org.eclipse.persistence.testing.models.jpa.nosql.mapped.Address;
import org.eclipse.persistence.testing.models.jpa.nosql.mapped.Customer;
import org.eclipse.persistence.testing.models.jpa.nosql.mapped.Order;
import org.eclipse.persistence.testing.tests.nosql.EntityManagerHelper;
import org.eclipse.persistence.testing.tests.nosql.JPAModelHelper;
import org.eclipse.persistence.testing.tests.nosql.MappedJPAModelHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;

/**
 * Oracle NoSQL mapped database JPA database tests.
 */
public class NoSQLJPAMappedTest {

    /** Log the test being currently executed. */
    @Rule public LogTestExecution logExecution = new LogTestExecution();

    /** The persistence unit name. */
    private static final String PU_NAME = "nosql-mapped";

    /** Stored {@link Order} instances count. */
    private static final int ORDERS_COUNT = 10;

    /** Stored {@link Order} instances. */
    private static Order[] orders;

    /** Last Order primary key value. */
    private static long lastId = 0;

    /** Entity manager used by tests. */
    EntityManager em;

    /**
     * Local shortcut for entity manager with mapped property for database host and port pair.
     * @return New {@link EntityManager} instance.
     */
    private static EntityManager createEntityManager() {
        return EntityManagerHelper.createEntityManager(PU_NAME, true);
    }

    /**
     * Get random order instance from test setup.
     * @return Random order instance from test setup.
     */
    private static Order getRandomOrder() {
        final int index = (int)(Math.random() * ORDERS_COUNT);
        return orders[index];
    }

    /**
     * Initialize data model for tests.
     */
    @BeforeClass
    public static void initModel() {
        EntityManager em = createEntityManager();
        try {
            JPAModelHelper.deleteModel(em);
            orders = MappedJPAModelHelper.buildModel(em, ORDERS_COUNT, lastId);
            lastId = orders[orders.length-1].id;
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
    }

    /**
     * Delete data model after tests.
     */
    @AfterClass
    public static void deleteModel() {
        EntityManager em = createEntityManager();
        try {
            MappedJPAModelHelper.deleteModel(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
    }

    /**
     * Setup test.
     */
    @Before
    public void setUp() {
        em = createEntityManager();
    }

    /**
     * Cleanup test.
     */
    @After
    public void tearDown() {
        EntityManagerHelper.closeEntityManagerAndTransaction(em);
    }

    /**
     * Test inserts.
     */
    @Test
    public void testInsert() {
        Order order = new Order();
        EntityManagerHelper.beginTransaction(em);
        try {
            order.id = ++lastId;
            order.orderedBy = "ACME";
            order.address = new Address();
            order.address.city = "Ottawa";
            em.persist(order);
            order.customer = new Customer();
            order.customer.id = Long.toString(++lastId);
            order.customer.name = "ACME";
            em.persist(order.customer);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        Order fromDatabase = null;
        try {
            fromDatabase = em.find(Order.class, order.id);
            EntityManagerHelper.compareObjects(order, fromDatabase, em);
        } finally {
            if (fromDatabase != null) {
                em.remove(fromDatabase);
            }
        }
    }

    /**
     * Test find.
     */
    @Test
    public void testFind() {
        EntityManagerHelper.beginTransaction(em);
        final Order existingOrder = getRandomOrder();
        Order order = em.find(Order.class, existingOrder.id);
        EntityManagerHelper.compareObjects(existingOrder, order, em);
    }

    /**
     * Test updates.
     */
    @Test
    public void testUpdate() {
        EntityManagerHelper.beginTransaction(em);
        Order order = new Order();
        long orderId = ++lastId;
        try {
            order.id = orderId;
            order.orderedBy = "ACME";
            order.address = new Address();
            order.address.city = "Ottawa";
            em.persist(order);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            final Order existingOrder = getRandomOrder();
            order = em.find(Order.class, existingOrder.id);
            order.orderedBy = "Fred Jones";
            order.address.addressee = "Fred Jones";
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            Order fromDatabase = em.find(Order.class, order.id);
            EntityManagerHelper.compareObjects(order, fromDatabase, em);
        } finally {
            Order toDelete = em.find(Order.class, orderId);
            em.remove(toDelete);
        }
    }

    /**
     * Test merge.
     */
    @Test
    public void testMerge() {
        EntityManagerHelper.beginTransaction(em);
        Order order = new Order();
        long orderId = ++lastId;
        try {
            order.id = orderId;
            order.orderedBy = "ACME";
            order.address = new Address();
            order.address.city = "Ottawa";
            em.persist(order);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            order = em.find(Order.class, order.id);
            order.orderedBy = "Fred Jones";
            order.address.addressee = "Fred Jones";
        } finally {
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            em.merge(order);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            Order fromDatabase = em.find(Order.class, order.id);
            EntityManagerHelper.compareObjects(order, fromDatabase, em);
        } finally {
            Order toDelete = em.find(Order.class, orderId);
            em.remove(toDelete);
        }
    }

    /**
     * Test refresh.
     */
    @Test
    public void testRefresh() {
        EntityManagerHelper.beginTransaction(em);
        long orderId = ++lastId;
        Order order = new Order();
        try {
            order.id = orderId++;
            order.orderedBy = "ACME";
            order.address = new Address();
            order.address.city = "Ottawa";
            em.persist(order);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            order = em.find(Order.class, order.id);
            order.orderedBy = "Fred Jones";
            em.refresh(order);
            assertEquals(String.format("Refresh failed: %s", order.orderedBy), "ACME", order.orderedBy);
        } finally {
            em.remove(order);
        }
    }

    /**
     * Test JPQL.
     */
    @Test
    public void testJPQL() {
        // We need known amount of records in DB.
        initModel();
        final TypedQuery<Order> query1 = em.createQuery("Select o from Order o", Order.class);
        final int count1 = query1.getResultList().size();
        assertEquals(String.format("Find all did not work, expected 10 got: %d", count1), 10, count1);
        final Order existingOrder = getRandomOrder();
        final TypedQuery<Order> query2 = em.createQuery("Select o from Order o where o.id = :id", Order.class);
        query2.setParameter("id", existingOrder.id);
        final int count2 = query2.getResultList().size();
        assertEquals(String.format("Find all did not work, expected 1 got: %d", count2), 1, count2);
    }

    /**
     * Test native query.
     */
    @Test
    public void testNativeQuery() {
        MappedInteraction interaction = new MappedInteraction();
        final Order existingOrder = getRandomOrder();
        interaction.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.GET.name());
        interaction.addArgumentValue("[Order-mapped," + existingOrder.id + "]", "");
        final Query query1 = em.unwrap(JpaEntityManager.class).createQuery(interaction);
        @SuppressWarnings("unchecked")
        final List<Object> result1 = query1.getResultList();
        assertEquals(String.format("Expected result of size 1, got %d", result1.size()), 1, result1.size());
        assertTrue(String.format("Result is not instance of Record but %s", result1.get(0).getClass().getSimpleName()),
                (result1.get(0) instanceof DataRecord));
        assertTrue(String.format("Incorrect result: %s", result1),
                (((DataRecord)result1.get(0)).containsKey("[Order-mapped," + existingOrder.id + "]")));

        interaction = new MappedInteraction();
        interaction.setProperty(OracleNoSQLPlatform.OPERATION, OracleNoSQLOperation.GET.name());
        interaction.setProperty(OracleNoSQLPlatform.TIMEOUT, "1000");
        interaction.setProperty(OracleNoSQLPlatform.CONSISTENCY, "ABSOLUTE");
        interaction.addArgumentValue("ID", existingOrder.id);
        final Query query2 = em.unwrap(JpaEntityManager.class).createQuery(interaction, Order.class);
        @SuppressWarnings("unchecked")
        final List<Object> result2 = query2.getResultList();
        assertEquals(String.format("Expected result of size 1, got %d", result2.size()), 1, result2.size());
        assertTrue(String.format("Result is not instance of Order but %s", result2.get(0).getClass().getSimpleName()),
                (result2.get(0) instanceof Order));
    }

    /**
     * Test deletes.
     */
    @Test
    public void testDelete() {
        EntityManagerHelper.beginTransaction(em);
        long orderId = ++lastId;
        Order order = new Order();
        try {
            order.id = orderId;
            order.orderedBy = "ACME";
            order.address = new Address();
            order.address.city = "Ottawa";
            em.persist(order);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        try {
            order = em.find(Order.class, order.id);
            em.remove(order);
            EntityManagerHelper.commitTransaction(em);
        } finally {
            EntityManagerHelper.clearCache(em);
            EntityManagerHelper.closeEntityManagerAndTransaction(em);
        }
        em = createEntityManager();
        EntityManagerHelper.beginTransaction(em);
        final Order fromDatabase = em.find(Order.class, order.id);
        assertNull(String.format("Object not deleted: %s", fromDatabase), fromDatabase);
    }

}
