/*
 * 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.entitymanager;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import jakarta.persistence.EntityExistsException;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceException;
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.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.timestamp.Nasty;
import org.eclipse.persistence.testing.models.wdf.jpa1.timestamp.Timestamp;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.BasicTypesFieldAccess;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Ignore;
import org.junit.Test;



public class TestPersist extends JPA1Base {

    private void verifyExistenceOnDatabase(int departmentId, String tableName) throws SQLException {
        if (tableName == null || !tableName.startsWith("TMP_")) {
            throw new IllegalArgumentException(
                    "None or illegal tableName was submitted to this method. Valid tableNames have to begin with 'TMP_'.");
        }
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            StringBuilder builder = new StringBuilder();
            builder.append("select ID from ").append(tableName).append(" where ID = ?");
            PreparedStatement stmt = conn.prepareStatement(builder.toString());
            try {
                stmt.setInt(1, departmentId);
                ResultSet rs = stmt.executeQuery();
                try {
                    verify(rs.next(), "no department with id " + departmentId + " found using JDBC.");
                } finally {
                    rs.close();
                }
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    @Test
    public void testPersistNewDepartment() throws SQLException {
        /*
         * If X is a new entity, it becomes managed. The entity X will be entered into the database at or before transaction
         * commit or as a result of the flush operation.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(1, "R&D");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(1, "TMP_DEP");
            Department dep2 = new Department(2, "QM");
            env.beginTransaction(em);
            em.persist(dep2);
            em.flush();
            // will not work on Oracle!
            // verify existence after flush
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(2, "TMP_DEP");
            // TODO verify cascading
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPersistNewBasicTypesFieldAccess() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            BasicTypesFieldAccess btfa = new BasicTypesFieldAccess(1);
            btfa.fill();
            env.beginTransaction(em);
            em.persist(btfa);
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(1, "TMP_BASIC_TYPES_FA");
            BasicTypesFieldAccess btfa2 = new BasicTypesFieldAccess(2);
            btfa2.fill();
            env.beginTransaction(em);
            em.persist(btfa2);
            em.flush();
            // will not work on Oracle!
            // verify existence after flush
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(2, "TMP_BASIC_TYPES_FA");
            // TODO verify cascading
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyPersistManaged(boolean flushBeforePersist) {
        /*
         * If X is a pre-existing managed entity, it is ignored by the persist operation. However, the persist operation is
         * cascaded to entities referenced by X, if the relationships from X to these other entities is annotated with the
         * cascade=PERSIST or cascade=ALL annotation element value or specified with the equivalent XML descriptor element.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // 1. managed via find
            final int id1 = (flushBeforePersist ? 100 : 0) + 11;
            Department dep = new Department(id1, "OLD");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            // find a department in the state MANAGED
            dep = em.find(Department.class, id1);
            verify(dep != null, "department not found");
            dep.setName("CHANGED");
            if (flushBeforePersist) {
                em.flush();
            }
            // this persist should be ignored as object is already managed
            em.persist(dep);
            // TODO verify that persist is ignored (use callback methods)
            // TODO verify cascading
            env.commitTransactionAndClear(em);
            // 2. managed via persist
            final int id2 = (flushBeforePersist ? 100 : 0) + 12;
            dep = new Department(id2, "OLD");
            env.beginTransaction(em);
            em.persist(dep);
            dep.setName("CHANGED");
            if (flushBeforePersist) {
                em.flush();
            }
            // this persist should be ignored as object is already managed
            em.persist(dep);
            // TODO verify that persist is ignored (use callback methods)
            // TODO verify cascading
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyPersistRemoved(boolean flushBeforePersist) {
        /*
         * If X is a removed entity, it becomes managed.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // 1. find an existing department, remove it and call persist
            final int id1 = (flushBeforePersist ? 100 : 0) + 21;
            Department dep = new Department(id1, "REMOVE");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            dep = em.find(Department.class, id1);
            em.remove(dep);
            // now, the entity should be REMOVED
            if (flushBeforePersist) {
                em.flush();
            }
            em.persist(dep);
            // now, the entity should be managed again
            dep.setName("REINVIGORATED");
            env.commitTransactionAndClear(em);

            dep = em.find(Department.class, id1);
            verify(dep != null, "department not found");
            verify("REINVIGORATED".equals(dep.getName()), "department has wrong name: " + dep.getName());

            // 2. persist a new department, remove it and call persist
            env.beginTransaction(em);
            final int id2 = (flushBeforePersist ? 100 : 0) + 22;
            dep = new Department(id2, "REMOVE");
            em.persist(dep);
            em.remove(dep);
            if (flushBeforePersist) {
                em.flush();
            }
            em.persist(dep);
            dep.setName("REINVIGORATED");
            env.commitTransactionAndClear(em);

            dep = em.find(Department.class, id2);
            verify(dep != null, "department not found");
            verify("REINVIGORATED".equals(dep.getName()), "department has wrong name: " + dep.getName());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPersistManaged() {
        verifyPersistManaged(false);
    }

    @Test
    public void testPersistManagedFlushed() {
        verifyPersistManaged(true);
    }

    @Test
    public void testPersistRemoved() {
        verifyPersistRemoved(false);
    }

    @Test
    public void testPersistRemovedFlushed() {
        verifyPersistRemoved(true);
    }

    @Test
    public void testPersistDetached() throws SQLException {
        /*
         * <li>If X is a detached object, the EntityExistsException may be thrown when the persist operation is invoked,
         * or the EntityExistsException or another PersistenceException may be thrown at flush or commit time.</li>
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        try {
            // case 1: detached because entity exists on db but is not known by persistence context
            id = 31;
            Department dep = new Department(id, "DETACHED");
            // firstly, we create a department on the database
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(id, "TMP_DEP");
            // now, the department is detached, we try to persist it again
            env.beginTransaction(em);
            boolean failed = false;
            try {
                em.persist(dep);
            } catch (EntityExistsException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                failed = true;
            }
            verify(failed, "persist did succeed on a detached instance.");
            // 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
            id = 32;
            dep = new Department(id, "ORIGINAL");
            Department detachedDep = new Department(id, "DETACHED");
            failed = false;
            env.beginTransaction(em);
            em.persist(dep); // this is now in state new
            try {
                em.persist(detachedDep);
            } catch (EntityExistsException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                failed = true;
            }
            verify(failed, "persist did succeed on a detached instance.");
            // case 2b: state of known object: FOR_UPDATE
            id = 33;
            dep = new Department(id, "ORIGINAL");
            detachedDep = new Department(id, "DETACHED");
            failed = false;
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(id, "TMP_DEP");
            env.beginTransaction(em);
            dep = em.find(Department.class, id); // this is now in state managed
            try {
                em.persist(detachedDep);
            } catch (EntityExistsException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                failed = true;
            }
            verify(failed, "persist did succeed on a detached instance.");
            // case 2c: state of known object: FOR_DELETE
            id = 34;
            dep = new Department(id, "ORIGINAL");
            detachedDep = new Department(id, "DETACHED");
            failed = false;
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(id, "TMP_DEP");
            env.beginTransaction(em);
            dep = em.find(Department.class, id);
            em.remove(dep); // this is now in state deleted
            try {
                em.persist(detachedDep);
            } catch (EntityExistsException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                failed = true;
            }
            verify(failed, "persist did succeed on a detached instance.");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid=309681)
    public void testPersistDeleteExecuted() throws SQLException {
        /*
         * If X is a detached object, an IllegalArgumentException will be thrown by the persist operation (or the transaction
         * commit will fail).
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        try {
            // case 2d: state of known object: DELETE_EXECUTED
            id = 35;
            Department dep = new Department(id, "ORIGINAL");
            Department detachedDep = new Department(id, "DETACHED");
            boolean failed = false;
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(id, "TMP_DEP");
            env.beginTransaction(em);
            dep = em.find(Department.class, id);
            em.remove(dep);
            em.flush();
            try {
                em.persist(detachedDep);
            } catch (IllegalArgumentException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                failed = true;
            }
            verify(failed, "persist did succeed on a detached instance.");
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * throws IllegalArgumentException, if instance is not an entity
     */
    @Test
    public void testNotAnEntity() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            try {
                em.persist("Hutzliputz");
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
            env.beginTransaction(em);
            try {
                em.persist(null);
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Ignore // @TestProperties(unsupportedEnvironments={JTANonSharedPCEnvironment.class, ResourceLocalEnvironment.class})
    public void testNoTransaction() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        Department dep = new Department(41, "dep41");
        try {
            em.persist(dep);
            flop("exception not thrown as expected");
        } catch (TransactionRequiredException e) {
            // $JL-EXC$ expected behavior
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testTransactionMarkedForRollback() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 1: persistence context already available when tx marked for rollback
            Department dep = new Department(42, "dep42");
            env.beginTransaction(em);
            verify(!em.contains(dep), "entity contained in persistence context"); // this ensures that the pc is available
            env.markTransactionForRollback(em);
            em.persist(dep);
            verify(em.contains(dep), "entity not contained in persistence context");
            env.rollbackTransaction(em);
            // case 2: persistence context not yet available when tx marked for rollback
            // will throw an exception in the container-managed JTA case
            if (!(env instanceof /* JTASharedPCEnvironment */Object)) {
                dep = new Department(43, "dep43");
                env.beginTransaction(em);
                env.markTransactionForRollback(em);
                em.persist(dep);
                verify(em.contains(dep), "entity not contained in persistence context");
                env.rollbackTransaction(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPersistNewEntityWithIdModifiedInPrePersist() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Timestamp timestamp = new Timestamp();
            verify(timestamp.getId() == null, "id is not null");
            env.beginTransaction(em);
            em.persist(timestamp);
            Long value = timestamp.getId();
            verify(value != null, "id is null");
            env.commitTransactionAndClear(em);
            verify(em.find(Timestamp.class, value) != null, "not found");
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyPersistRemovedEntityWithIdModifiedInPrePersist(boolean removeExecuted) {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Timestamp timestamp = new Timestamp();
            verify(timestamp.getId() == null, "id is not null");
            env.beginTransaction(em);
            em.persist(timestamp);
            env.commitTransaction(em);

            env.beginTransaction(em);
            final Long id1 = timestamp.getId();
            timestamp = em.find(Timestamp.class, id1);
            em.remove(timestamp);
            if (removeExecuted) {
                em.flush();
            }

            em.persist(timestamp);

            env.commitTransactionAndClear(em);
            final Long id2 = timestamp.getId();

            Assert.assertFalse(id2.equals(id1));

            Assert.assertNull(em.find(Timestamp.class, id1));
            Assert.assertNotNull(em.find(Timestamp.class, id1));


        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid=309681)
    public void testPersistRemovedEntityWithIdModifiedInPrePersist() {
        verifyPersistRemovedEntityWithIdModifiedInPrePersist(false);
    }

    @Test
    @Bugzilla(bugid=309681)
    public void testPersistRemovedEntityWithIdModifiedInPrePersistFlushed() {
        verifyPersistRemovedEntityWithIdModifiedInPrePersist(true);
    }

    @Test
    public void testNastyTimestampTwice() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Nasty nasty = new Nasty();
            verify(nasty.getId() == null, "id is not null");
            env.beginTransaction(em);
            em.persist(nasty);
            Long value = nasty.getId();
            verify(value != null, "id is null");
            try {
                em.persist(new Nasty());
                env.commitTransaction(em);
                flop("persisting second nasty timestamp succeeded");
            } catch (PersistenceException ex) {
                Assert.assertTrue(true);
            }
            if (env.isTransactionActive(em)) {
                env.rollbackTransactionAndClear(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testDuprec() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Department department = new Department(999, "X");
            em.persist(department);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            try {
                em.persist(department); // exception here
                env.commitTransaction(em); // or here
                flop("duprec not detected");
            } catch (PersistenceException ex) {
                // OK
            } catch (/* JTARollback */Exception ex) {
                // JTA OK
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testDuprecBatch() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Department d1 = new Department(998, "X");
            em.persist(d1);
            Department d2 = new Department(997, "X");
            em.persist(d2);
            Department d3 = new Department(996, "X");
            em.persist(d3);
            Department d4 = new Department(995, "X");
            em.persist(d4);
            Department d5 = new Department(994, "X");
            em.persist(d5);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            try {
                d1 = new Department(993, "X");
                em.persist(d1);
                d2 = new Department(992, "X");
                em.persist(d2);
                d3 = new Department(991, "X");
                em.persist(d3);
                em.persist(d4); // duprec: 995
                d5 = new Department(990, "X");
                em.persist(d5);
                env.commitTransaction(em); // or here
                flop("duprec not detected");
            } catch (PersistenceException ex) {
                // OK
            } catch (/* JTARollback */Exception ex) {
                // JTA OK
            }
        } finally {
            closeEntityManager(em);
        }
    }

}
