/*
 * 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.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import jakarta.persistence.EntityManager;
import jakarta.persistence.LockModeType;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.RollbackException;
import jakarta.persistence.TransactionRequiredException;

import org.junit.Assert;

import org.eclipse.persistence.testing.framework.wdf.Bugzilla;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.ToBeInvestigated;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Hobby;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

public class TestLockMethod extends JPA1Base {
    @Test
    public void testNonManagedEntity() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(1, "dep1");
            env.beginTransaction(em);
            em.lock(dep, LockModeType.READ);
            flop("no exception NonManagedEntity");
        } catch (IllegalArgumentException e) {
            Assert.assertTrue(true);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testEntityForInsert() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(1, "dep1");
            env.beginTransaction(em);
            em.persist(dep);
            em.lock(dep, LockModeType.READ);
            flop("no exception NonManagedEntity");
        } catch (IllegalArgumentException e) {
            Assert.assertTrue(true);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testEntityForDelete() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(100, "dep1");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(100));
            em.remove(dep);
            em.lock(dep, LockModeType.READ);
            flop("no exception NonManagedEntity");
        } catch (IllegalArgumentException e) {
            Assert.assertTrue(true);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testEntityDeleteExecuted() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(101, "dep1");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(101));
            em.remove(dep);
            em.flush();
            em.lock(dep, LockModeType.READ);
            flop("no exception NonManagedEntity");
        } catch (IllegalArgumentException e) {
            Assert.assertTrue(true);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNonVersionedEntity() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Hobby hobby = new Hobby("blah-muh");
            env.beginTransaction(em);
            em.persist(hobby);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            hobby = em.merge(hobby);
            try {
                em.lock(hobby, LockModeType.READ);
                flop("no exception NonVersionedEntity");
            } catch (IllegalArgumentException e) {
                Assert.assertTrue(true);
            } catch (PersistenceException e) {
                Assert.assertTrue(true);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testIllegalArgument() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        String illegal = "pfui";
        try {
            env.beginTransaction(em);
            em.lock(illegal, LockModeType.READ);
            flop("no exception IllegalArgument");
        } catch (IllegalArgumentException iae) {
            Assert.assertTrue(true);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNoTransaction() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(2, "dep2");
            em.lock(dep, LockModeType.READ);
            flop("no exception TransactionRequired");
        } catch (TransactionRequiredException tre) {
            Assert.assertTrue(true);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testReadLock() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(3, "dep3");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.merge(dep);
            em.lock(dep, LockModeType.READ);
            env.commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testWriteLock() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(4, "dep4");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.merge(dep);
            int version = dep.getVersion();
            em.lock(dep, LockModeType.WRITE);
            env.commitTransaction(em);
            verify(dep.getVersion() > version, "version not incremented");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testNewEntity() throws SQLException {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            Department dep = new Department(5, "dep5");
            env.beginTransaction(em);
            em.persist(dep);
            em.lock(dep, LockModeType.READ);
            // verify entity is flushed to DB for locking
            con = env.getDataSource().getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery("select count(*) from TMP_DEP where ID = 3");
            rs.next();
            verify(rs.getInt(1) == 1, "entity not flushed for lock");
            env.commitTransaction(em);
        } finally {
            rs.close();
            stmt.close();
            con.close();
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid=309681)
    public void testLockOldVersion() {
        lockOldVersion(5, LockModeType.READ);
        lockOldVersion(6, LockModeType.WRITE);
    }

    private void lockOldVersion(int id, LockModeType lockMode) {
        JPAEnvironment env = getEnvironment();
        EntityManager em1 = env.getEntityManagerFactory().createEntityManager();
        EntityManager em2 = env.getEntityManagerFactory().createEntityManager();
        Department dep1 = new Department(id, "dep" + id);
        try {
            // create entity in DB
            env.beginTransaction(em1);
            em1.persist(dep1);
            env.commitTransactionAndClear(em1);
            // read first version
            env.beginTransaction(em1);
            dep1 = em1.find(Department.class, Integer.valueOf(id));
            verify(dep1 != null, "Department is null");
            // change entity meanwhile
            env.beginTransaction(em2);
            Department dep2 = em2.find(Department.class, Integer.valueOf(id));
            dep2.setName("dep" + id + "x");
            env.commitTransactionAndClear(em2);
            // try to lock first version
            em1.lock(dep1, lockMode);
            env.commitTransactionAndClear(em1);
            flop("OptimisticLockException not thrown");
        } catch (RollbackException rbe) {
          Throwable cause = rbe.getCause();
          if (cause instanceof OptimisticLockException) {
              OptimisticLockException ole = (OptimisticLockException) cause;
              verify(dep1.equals(ole.getEntity()), "wrong entity");
          } else {
              Assert.fail("cause is no OLE");
          }
        } catch (OptimisticLockException ole) {
            verify(dep1.equals(ole.getEntity()), "wrong entity");
        } finally {
            closeEntityManager(em1);
            closeEntityManager(em2);
        }
    }

    @Test
    public void testDetachedEntity() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            // case 1: detached because entity exists on db but is not known by persistence context
            Department dep = new Department(7, "dep7");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            try {
                em.lock(dep, LockModeType.READ);
                flop("exception not thrown as expected");
            } catch (IllegalArgumentException e) {
                // $JL-EXC$ expected behavior
            }
            env.rollbackTransaction(em);
            em.clear();
            // case 2: detached because an object with same pk but different object identity is known by persistence context
            // case 2a: state of known object: FOR_INSERT
            dep = new Department(8, "dep8");
            Department depDetached = new Department(dep.getId(), "detached");
            env.beginTransaction(em);
            em.persist(dep);
            try {
                em.lock(depDetached, LockModeType.READ);
                flop("exception not thrown as expected");
            } catch (IllegalArgumentException e) {
                // $JL-EXC$ expected behavior
            }
            env.rollbackTransaction(em);
            em.clear();
            // case 2b: state of known object: FOR_UPDATE
            dep = new Department(9, "dep9");
            depDetached = new Department(dep.getId(), "detached");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(dep.getId()));
            try {
                em.lock(depDetached, LockModeType.READ);
                flop("exception not thrown as expected");
            } catch (IllegalArgumentException e) {
                // $JL-EXC$ expected behavior
            }
            env.rollbackTransaction(em);
            em.clear();
            // case 2c: state of known object: FOR_DELETE
            dep = new Department(10, "dep10");
            depDetached = new Department(dep.getId(), "detached");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(dep.getId()));
            em.remove(dep);
            try {
                em.lock(depDetached, LockModeType.READ);
                flop("exception not thrown as expected");
            } catch (IllegalArgumentException e) {
                // $JL-EXC$ expected behavior
            }
            env.rollbackTransaction(em);
            em.clear();
            // case 2d: state of known object: DELETE_EXECUTED
            dep = new Department(11, "dep11");
            depDetached = new Department(dep.getId(), "detached");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(dep.getId()));
            em.remove(dep);
            em.flush();
            try {
                em.lock(depDetached, LockModeType.READ);
                flop("exception not thrown as expected");
            } catch (IllegalArgumentException e) {
                // $JL-EXC$ expected behavior
            }
            env.rollbackTransaction(em);
            em.clear();
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testTransactionMarkedForRollback() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(12, "dep12");
            env.beginTransaction(em);
            em.persist(dep);
            em.flush();
            env.markTransactionForRollback(em);
            em.lock(dep, LockModeType.WRITE);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testReadLockTwice() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(13, "dep13");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.merge(dep);
            em.lock(dep, LockModeType.READ);
            em.lock(dep, LockModeType.READ);
            env.commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testWriteLockTwice() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(14, "dep14");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.merge(dep);
            em.lock(dep, LockModeType.WRITE);
            em.lock(dep, LockModeType.WRITE);
            env.commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPromoteLock() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(15, "dep15");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.merge(dep);
            em.lock(dep, LockModeType.READ);
            em.lock(dep, LockModeType.WRITE);
            env.commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

}
