/*
 * Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2005, 2015 SAP. 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:
//     SAP - initial API and implementation

package org.eclipse.persistence.testing.tests.wdf.jpa1.lock;

import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.naming.NamingException;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.RollbackException;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.testing.framework.wdf.Bugzilla;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.Skip;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Review;
import org.eclipse.persistence.testing.models.wdf.jpa1.node.Node;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

// TODO remove restrictions
public class TestOptimistic extends JPA1Base {

    @Test
    public void testOptimisticLockExceptionUpdateUpdate() {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        int id = 10;
        Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "one");
        try {
            env.beginTransaction(em1);
            em1.persist(rev1);
            env.commitTransactionAndClear(em1);

            env.beginTransaction(em1);
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            rev1.getVersion();

            EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
            try {
                env.beginTransaction(em2);
                Review rev2 = em2.find(Review.class, id);
                rev2.setReviewText("two"); // 1 update
                env.commitTransactionAndClear(em2);
            } finally {
                closeEntityManager(em2);
            }

            rev1.setReviewText("1"); // 2 update
            env.commitTransactionAndClear(em1);
            flop("OptimisticLockException not thrown");
        } catch (RollbackException rbe) {
            assertExceptionWrapsOLE(rev1, rbe);
        } catch (OptimisticLockException ole) {
            assertFailingEntity(rev1, ole);
        } finally {
            closeEntityManager(em1);
        }
        // bug 309681: version is incremented in spite of roll back -> not an
        // issue
        // verify(version == rev1.getVersion(), "wrong version:" + version +
        // " != " + rev1.getVersion());
    }

    private static void assertFailingEntity(Object entity, OptimisticLockException ole) {
        // $JL-EXC$ expected behavior
        Object failingEntity = ole.getEntity();
        if (failingEntity != null) {
            verify(entity.equals(failingEntity), "wrong entity");
        }
    }

    @Test
    public void testOptimisticLockExceptionDeleteUpdate() {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
        int id = 20;
        Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "one");
        try {
            env.beginTransaction(em1);
            em1.persist(rev1);
            env.commitTransactionAndClear(em1);

            env.beginTransaction(em1);
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            env.beginTransaction(em2);
            Review rev2 = em2.find(Review.class, id);
            em2.remove(rev2); // 1 delete
            env.commitTransactionAndClear(em2);
            rev1.setReviewText("1"); // 2 update
            env.commitTransactionAndClear(em1);
            flop("OptimisticLockException not thrown");
        } catch (RollbackException rbe) {
            assertExceptionWrapsOLE(rev1, rbe);
        } catch (OptimisticLockException ole) {
            assertFailingEntity(rev1, ole);
        } finally {
            closeEntityManager(em1);
            closeEntityManager(em2);
        }
    }

    private static void assertExceptionWrapsOLE(Object entity, PersistenceException rbe) {
        Throwable cause = rbe.getCause();
        if (cause instanceof OptimisticLockException) {
            assertFailingEntity(entity, (OptimisticLockException) cause);
        } else {
            Assert.fail("Rollback not caused by OLE");
        }
    }

    @Test
    public void testOptimisticLockExceptionUpdateDelete() {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
        int id = 30;
        Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "one");
        try {
            env.beginTransaction(em1);
            em1.persist(rev1);
            env.commitTransactionAndClear(em1);
            env.beginTransaction(em1);
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            env.beginTransaction(em2);
            Review rev2 = em2.find(Review.class, id);
            rev2.setReviewDate(Date.valueOf("2005-12-23")); // 1 update
            env.commitTransactionAndClear(em2);
            em1.remove(rev1); // 2 delete
            env.commitTransactionAndClear(em1);
            flop("OptimisticLockException not thrown");
        } catch (RollbackException rbe) {
            assertExceptionWrapsOLE(rev1, rbe);
        } catch (OptimisticLockException ole) {
            assertFailingEntity(rev1, ole);
            try {
                env.rollbackTransactionAndClear(em1);
                flop("no rollback after OptimisticLockException");
            } catch (IllegalStateException ise) {
                // $JL-EXC$ expected behavior
            }
        } finally {
            closeEntityManager(em1);
            closeEntityManager(em2);
        }
    }

    @Test
    public void testOptimisticLockExceptionDeleteDelete() {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
        int id = 40;
        Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "one");
        try {
            env.beginTransaction(em1);
            em1.persist(rev1);
            env.commitTransactionAndClear(em1);
            env.beginTransaction(em1);
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            env.beginTransaction(em2);
            Review rev2 = em2.find(Review.class, id);
            em2.remove(rev2); // 1 delete
            env.commitTransactionAndClear(em2);
            em1.remove(rev1); // 2 delete
            env.commitTransactionAndClear(em1);
            flop("OptimisticLockException not thrown");
        } catch (RollbackException rbe) {
            assertExceptionWrapsOLE(rev1, rbe);
        } catch (OptimisticLockException ole) {
            assertFailingEntity(rev1, ole);
        } finally {
            closeEntityManager(em1);
            closeEntityManager(em2);
        }
    }

    @Test
    public void testNoChange() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        try {
            int id = 50;
            int version = 0;
            Review rev = new Review(id, Date.valueOf("2005-12-07"), "1");
            env.beginTransaction(em);
            em.persist(rev);
            env.commitTransactionAndClear(em);
            version = rev.getVersion();
            env.beginTransaction(em);
            rev = em.find(Review.class, id);
            verify(rev != null, "Review is null");
            rev.setReviewText(rev.getReviewText()); // no change
            env.commitTransactionAndClear(em);
            verify(version == rev.getVersion(), "wrong version");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testIllegalVersionAccessNew() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        boolean caughtException = false;
        try {
            int id = 60;
            Review rev = new Review(id, Date.valueOf("2005-12-07"), "1");
            env.beginTransaction(em);
            em.persist(rev);
            rev.setVersion(5);
            env.commitTransactionAndClear(em);
        } catch (PersistenceException e) {
            // $JL-EXC$ expected behavior
            caughtException = true;
        } finally {
            closeEntityManager(em);
            verify(caughtException, "PersistenceException not thrown for versionModification");
        }
    }

    @Test
    public void testIllegalVersionAccessManaged() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        boolean caughtException = false;
        try {
            int id = 70;
            Review rev = new Review(id, Date.valueOf("2005-12-07"), "1");
            env.beginTransaction(em);
            em.persist(rev);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            rev = em.merge(rev);
            rev.setVersion(7);
            env.commitTransactionAndClear(em);
        } catch (PersistenceException e) {
            // $JL-EXC$ expected behavior
            caughtException = true;
        } finally {
            closeEntityManager(em);
        }
        verify(caughtException, "PersistenceException not thrown for versionModification");
    }

    @Test
    public void testFlushWithVersion() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        try {
            int id = 80;
            Review rev = new Review(id, Date.valueOf("2005-12-07"), "1");
            env.beginTransaction(em);
            em.persist(rev);
            em.flush(); // 1st version
            int startVersion = rev.getVersion();
            rev.setReviewDate(Date.valueOf("2005-12-23"));
            env.commitTransactionAndClear(em); // 2nd version
            env.beginTransaction(em);
            rev = em.merge(rev);
            rev.setReviewText("AAA");
            em.flush(); // 3rd version
            rev.setReviewText("BBB");
            env.commitTransactionAndClear(em); // 4th version
            env.beginTransaction(em);
            rev = em.merge(rev);
            em.flush();
            env.commitTransactionAndClear(em); // still 4th version
            rev = em.find(Review.class, id);
            verify(rev.getReviewText().equals("BBB"), "wrong reviewText");
            verify(rev.getReviewDate().equals(Date.valueOf("2005-12-23")), "wrong reviewDate");
            verify(rev.getVersion() == startVersion + 3, "wrong version");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testMergeWithVersion() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        int id = 90;
        Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "a");
        Review rev2 = new Review(id, Date.valueOf("2005-12-07"), "b");
        try {
            env.beginTransaction(em);
            em.persist(rev1);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            rev1 = em.merge(rev2);
            flop("OptimisticLockException not thrown for merge with old version");
        } catch (OptimisticLockException ole) {
            assertFailingEntity(rev2, ole);
            verify(env.isTransactionMarkedForRollback(em), "transaction not marked for rollback on OptimisticLockException");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRefreshWithVersion() {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
        try {
            int id = 100;
            Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "x");
            env.beginTransaction(em1);
            em1.persist(rev1);
            env.commitTransactionAndClear(em1);
            env.beginTransaction(em1);
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            env.beginTransaction(em2);
            Review rev2 = em2.find(Review.class, id);
            rev2.setReviewDate(Date.valueOf("2005-12-23"));
            env.commitTransactionAndClear(em2);
            em1.refresh(rev1);
            rev1.setReviewText("y");
            env.commitTransactionAndClear(em1);
        } finally {
            closeEntityManager(em1);
            closeEntityManager(em2);
        }
    }

    @Test
    public void testVersion() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        try {
            int id = 110;
            int version = 0;
            Review rev = new Review(id, Date.valueOf("2005-12-07"), "1");
            env.beginTransaction(em);
            em.persist(rev);
            env.commitTransactionAndClear(em);
            for (int i = 0; i < 3; i++) {
                env.beginTransaction(em);
                rev = em.find(Review.class, id);
                verify(rev != null, "Review is null");
                rev.setReviewText(Integer.valueOf(i).toString());
                env.commitTransactionAndClear(em);
                verify(version < rev.getVersion(), "new version to small");
                version = rev.getVersion();
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPersistAgain() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        try {
            int id = 120;
            Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "x");
            env.beginTransaction(em);
            em.persist(rev1);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            rev1 = em.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            em.persist(rev1);
            verify(rev1.getVersion() > 0, "Version reset");
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Ignore
    // this only works on oracle
    public void testIsoLevel() throws SQLException {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
        boolean caughtException = false;
        try {
            Connection con = env.getDataSource().getConnection();
            verify(con.getTransactionIsolation() == Connection.TRANSACTION_READ_COMMITTED, "wrong isoLevel");
            int id = 130;
            Review rev1 = new Review(id, Date.valueOf("2005-12-07"), "1");
            env.beginTransaction(em1); // create entity
            em1.persist(rev1);
            env.commitTransactionAndClear(em1);
            env.beginTransaction(em1); // Tx1 read and flush change
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            rev1.setReviewText("2");
            em1.flush();
            env.beginTransaction(em2); // Tx2 read flushed entity ?
            Review rev2 = em2.find(Review.class, id);
            verify(rev2 != null, "Review is null");
            env.rollbackTransactionAndClear(em1); // Tx1 rollback first change
                                                  // and commit second
            env.beginTransaction(em1);
            rev1 = em1.find(Review.class, id);
            verify(rev1 != null, "Review is null");
            rev1.setReviewText("3");
            env.commitTransactionAndClear(em1);
            rev2.setReviewText("4"); // Tx2 commit based on rollback version
            env.commitTransactionAndClear(em2);
        } catch (OptimisticLockException ole) {
            // $JL-EXC$ expected behavior
            caughtException = true;
        } finally {
            closeEntityManager(em1);
            closeEntityManager(em2);
            verify(caughtException, "OptimisticLockException not thrown");
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testNode() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManagerFactory().createEntityManager();
        int NUMBER_OF_NODES = 7;
        int NUMBER_OF_UPDATES = 3;
        try {
            Node first = new Node(0, null);
            first.setName("!0");
            Node parent = first;
            env.beginTransaction(em);
            em.persist(first);
            for (int i = 1; i < NUMBER_OF_NODES; i++) {
                Node tmp = new Node(i, parent);
                tmp.setName(Integer.valueOf(i).toString());
                em.persist(tmp);
                parent = tmp;
            }
            env.commitTransactionAndClear(em);
            for (int i = 0; i < NUMBER_OF_UPDATES; i++) {
                updateNodes(env, em, Integer.toString(i));
            }
        } finally {
            closeEntityManager(em);
        }
    }

    private void updateNodes(JPAEnvironment env, EntityManager em, String newName) {
        env.beginTransaction(em);
        Node tmp = em.find(Node.class, 0);
        verify(tmp.getVersion() != 0, "wrong version");
        while (tmp != null) {
            tmp.setName(newName);
            Set<Node> children = tmp.getChildren();
            if (!children.isEmpty()) {
                tmp = children.iterator().next(); // linkedList
                verify(tmp.getVersion() != 0, "wrong version");
            } else {
                tmp = null;
            }
        }
        env.commitTransactionAndClear(em);
    }

    private abstract class BatchTester {
        private final boolean throwsRollbackException;

        BatchTester(boolean rollback) {
            throwsRollbackException = rollback;
        }

        abstract void trigger(EntityManager em);
    }

    @Test
    @Skip(server = true)
    // RESOURCE_LOCAL only
    public void testBatchOLECommit() throws SQLException, NamingException {
        BatchTester tester = new BatchTester(true) {

            @Override
            void trigger(EntityManager em) {
                em.getTransaction().commit();
            }
        };
        verifyBatchOLE(tester, true);
        clearAllTables();
        verifyBatchOLE(tester, false);
    }

    @Test
    @Skip(server = true)
    // RESOURCE_LOCAL only
    public void testBatchOLEFlush() throws SQLException, NamingException {
        BatchTester tester = new BatchTester(true) {

            @Override
            void trigger(EntityManager em) {
                em.flush();
            }
        };
        verifyBatchOLE(tester, true);
        clearAllTables();
        verifyBatchOLE(tester, false);
    }

    @Test
    @Skip(server = true)
    // RESOURCE_LOCAL only
    public void testBatchOLEQuery() throws SQLException, NamingException {
        BatchTester tester = new BatchTester(true) {

            @Override
            void trigger(EntityManager em) {
                em.createQuery("select d from Department d").setFlushMode(FlushModeType.AUTO).getResultList();
                em.flush();
            }
        };
        verifyBatchOLE(tester, true);
        clearAllTables();
        verifyBatchOLE(tester, false);
    }

    private void verifyBatchOLE(BatchTester tester, boolean batch) throws NamingException {
        JPAEnvironment env = getEnvironment();
        final Map map = new HashMap();
        map.put(PersistenceUnitProperties.DDL_GENERATION, "none");
        map.put(PersistenceUnitProperties.BATCH_WRITING, batch ? "JDBC" : "None");
        EntityManagerFactory emf = env.createNewEntityManagerFactory(map);
        try {

            EntityManager em1 = emf.createEntityManager(map);

            try {
                em1.getTransaction().begin();
                em1.persist(new Department(1, "1"));
                em1.persist(new Department(2, "2"));
                em1.persist(new Department(3, "3"));
                em1.persist(new Department(4, "4"));
                em1.persist(new Department(5, "5"));
                em1.getTransaction().commit();
                em1.clear();

                em1.getTransaction().begin();
                Department i13 = em1.find(Department.class, 3);
                Department i14 = em1.find(Department.class, 4);
                Department i15 = em1.find(Department.class, 5);
                i13.setName("x");
                i14.setName("y");
                i15.setName("z");

                EntityManager em2 = emf.createEntityManager(map);
                try {
                    em2.getTransaction().begin();
                    Department i21 = em2.find(Department.class, 1);
                    Department i22 = em2.find(Department.class, 2);
                    Department i23 = em2.find(Department.class, 3);

                    i21.setName("a");
                    i22.setName("b");
                    i23.setName("c");

                    em2.getTransaction().commit();

                } finally {
                    em2.close();
                }

                try {
                    tester.trigger(em1);
                    flop("OptimisticLockException not thrown");
                } catch (RollbackException rbe) {
                    if (tester.throwsRollbackException) {
                        assertExceptionWrapsOLE(i13, rbe);
                    } else {
                        // no RollbackException expected
                        throw rbe;
                    }
                } catch (OptimisticLockException ole) {
                    assertFailingEntity(i13, ole);
                } catch (PersistenceException pe) {
                    if (!tester.throwsRollbackException) {
                        assertExceptionWrapsOLE(i13, pe);
                    } else {
                        // RollbackException expected
                        throw pe;
                    }
                } finally {
                    if (em1.getTransaction().isActive()) {
                        em1.getTransaction().rollback();
                    }
                }

            } finally {
                em1.close();
            }
        } finally {
            emf.close();
        }
    }
}
