/*
 * Copyright (c) 1998, 2020 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:
//     dminsky - initial API and implementation
package org.eclipse.persistence.testing.tests.jpa.advanced;

import java.util.List;

import jakarta.persistence.EntityManager;
import jakarta.persistence.LockModeType;

import org.eclipse.persistence.testing.framework.QuerySQLTracker;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator;

import junit.framework.TestSuite;

/**
 * Bug 389265 - OptimisticLock Force Increment increments version both on flush
 * and on commit
 *
 * - Test LockModeType.OPTIMISTIC_FORCE_INCREMENT with combinations of
 * flush/commit/changes/no-op
 */
public class OptimisticLockForceIncrementTestSuite extends JUnitTestCase {

    public OptimisticLockForceIncrementTestSuite() {
        super();
    }

    public OptimisticLockForceIncrementTestSuite(String name) {
        super(name);
    }

    public static TestSuite suite() {
        TestSuite suite = new TestSuite("OptimisticLockForceIncrementTestSuite");
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testSetup"));

        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementNoChanges"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementPreFlushChanges"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementPostFlushChanges"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementPreAndPostFlushChanges"));

        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementCommitNoChanges"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementPreCommitChanges"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementFlushCommitNoChanges"));

        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementMultipleEntities"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementBasicPromoteLock"));
        suite.addTest(new OptimisticLockForceIncrementTestSuite("testVersionIncrementPromoteLock"));

        return suite;
    }

    public void testSetup() {
        new AdvancedTableCreator().replaceTables(JUnitTestCase.getServerSession());

        EmployeePopulator employeePopulator = new EmployeePopulator();
        employeePopulator.buildExamples();
        employeePopulator.persistExample(JUnitTestCase.getServerSession());

        clearCache();
    }

    public void testVersionIncrementNoChanges() {
        if (usesSOP()) {
            // with SOP it fails with: 1 SQL update statement execution(s)
            // expected:<1> but was:<2>
            // Looks like a bug: cascade versioning (used with SOP) adds an
            // extra version increment.
            return;
        }
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();
            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            counter.getSqlStatements().clear();
            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            em.flush();

            em.getTransaction().commit();
            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            // SQL statements expected - 1 x update
            assertEquals("1 SQL update statement execution(s)", 1, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementPreFlushChanges() {
        if (usesSOP()) {
            // with SOP it fails with: 1 SQL update statement execution(s)
            // expected:<1> but was:<2>
            // Looks like a bug: cascade versioning (used with SOP) adds an
            // extra version increment.
            return;
        }
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();

            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();

            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
            entity.setCity("Vancouver");
            entity.setProvince("BC");
            entity.setCountry("Canada");

            em.flush();

            em.getTransaction().commit();
            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            assertEquals("Entity's name should be changed", "Vancouver", entity.getCity());
            // SQL statements expected - 1 x update
            assertEquals("1 SQL update statement execution(s)", 1, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementPostFlushChanges() {
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();

            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            em.flush();

            entity.setCity("Toronto");
            entity.setProvince("ON");
            entity.setCountry("Canada");

            em.getTransaction().commit();
            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            assertEquals("Entity's name should be changed", "Toronto", entity.getCity());
            // SQL statements expected - 2 x update
            assertEquals("2 SQL update statement execution(s)", 2, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementPreAndPostFlushChanges() {
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();

            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            entity.setCity("Moncton");
            entity.setProvince("NB");
            entity.setCountry("Canada");

            em.flush();

            entity.setCity("Halifax");
            entity.setProvince("NS");
            entity.setCountry("Canada");

            em.getTransaction().commit();
            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            assertEquals("Entity's name should be changed", "Halifax", entity.getCity());
            // SQL statements expected - 2 x update
            assertEquals("2 SQL update statement execution(s)", 2, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementCommitNoChanges() {
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();

            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            em.getTransaction().commit();
            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            // SQL statements expected - 1 x update
            assertEquals("1 SQL update statement execution(s)", 1, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementPreCommitChanges() {
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();

            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            entity.setCity("Calgary");
            entity.setProvince("AB");
            entity.setCountry("Canada");

            em.getTransaction().commit();

            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            assertEquals("Entity's name should be changed", "Calgary", entity.getCity());
            // SQL statements expected - 1 x update
            assertEquals("1 SQL update statement execution(s)", 1, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementFlushCommitNoChanges() {
        if (usesSOP()) {
            // with SOP it fails with: 1 SQL update statement execution(s)
            // expected:<1> but was:<2>
            // Looks like a bug: cascade versioning (used with SOP) adds an
            // extra version increment.
            return;
        }
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();
            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            em.flush();

            em.getTransaction().commit();
            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            // SQL statements expected - 1 x update
            assertEquals("1 SQL update statement execution(s)", 1, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementMultipleEntities() {
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();
            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity1 = addresses.get(0);
            Address entity2 = addresses.get(1);

            assertNotNull("Entity 1: Address cannot be null", entity1);
            assertNotNull("Entity 2: Address cannot be null", entity2);

            int startVersion1 = entity1.getVersion();
            int startVersion2 = entity2.getVersion();
            em.lock(entity1, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            // update entity 2
            entity2.setCity("Kamloops");
            entity2.setProvince("BC");
            entity2.setCountry("Canada");

            em.flush();

            // update entity 1
            entity1.setCity("New Glasgow");
            entity1.setProvince("NS");
            entity1.setCountry("Canada");

            em.flush();

            int expectedVersion1 = (startVersion1 + 1);
            int actualVersion1 = entity1.getVersion();

            int expectedVersion2 = (startVersion2 + 1);
            int actualVersion2 = entity2.getVersion();

            em.getTransaction().rollback();
            em.close();

            assertEquals("Entity 1: Version number incremented incorrectly: ", expectedVersion1, actualVersion1);
            assertEquals("Entity 2: Version number incremented incorrectly: ", expectedVersion2, actualVersion2);

            // 3 SQL update statements expected
            assertEquals("3 SQL update statement execution(s)", 3, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementBasicPromoteLock() {
        if (usesSOP()) {
            // with SOP it fails with: 1 SQL update statement execution(s)
            // expected:<1> but was:<2>
            // Looks like a bug: cascade versioning (used with SOP) adds an
            // extra version increment.
            return;
        }
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();
            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC);

            entity.setCity("Churchill");
            entity.setProvince("MB");
            entity.setCountry("Canada");

            em.flush();
            em.getTransaction().commit();

            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            // SQL statements expected
            assertEquals("1 SQL update statement execution(s)", 1, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    public void testVersionIncrementPromoteLock() {
        QuerySQLTracker counter = null;
        try {
            counter = new QuerySQLTracker(getServerSession());
            EntityManager em = getEntityManagerFactory().createEntityManager();
            em.getTransaction().begin();

            List<Address> addresses = em.createQuery("select a from Address a").getResultList();
            counter.getSqlStatements().clear();
            assertNotNull("Null query results returned", addresses);
            assertNotSame("No query results returned", addresses.size(), 0);
            Address entity = addresses.get(0);
            assertNotNull("Entity: Address cannot be null", entity);

            int startVersion = entity.getVersion();
            em.lock(entity, LockModeType.OPTIMISTIC);

            entity.setCity("Banff");
            entity.setProvince("AB");
            entity.setCountry("Canada");

            em.flush();

            em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);

            entity.setCity("London");
            entity.setProvince("ON");
            entity.setCountry("Canada");

            em.getTransaction().commit();

            int expectedVersion = (startVersion + 1);
            int actualVersion = entity.getVersion();

            em.close();

            assertEquals("Version number incremented incorrectly: ", expectedVersion, actualVersion);
            // SQL statements expected
            assertEquals("2 SQL update statement execution(s)", 2, countNumberOfUpdateStatements(counter));
        } finally {
            if (counter != null) {
                counter.remove();
            }
        }
    }

    protected int countNumberOfUpdateStatements(QuerySQLTracker counter) {
        if (counter == null || counter.getSqlStatements().size() == 0) {
            return 0;
        }

        int numberOfStatements = 0;
        List<String> statements = counter.getSqlStatements();
        for (String statement : statements) {
            if (statement != null && statement.trim().toUpperCase().startsWith("UPDATE")) {
                numberOfStatements++;
            }
        }
        return numberOfStatements;
    }

}
