/*
 * 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.EntityManager;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.TransactionRequiredException;

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.Cubicle;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.CubiclePrimaryKeyClass;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Ignore;
import org.junit.Test;

public class TestRemove extends JPA1Base {

    private void verifyAbsenceOnDatabase(int departmentId) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("select ID, NAME from TMP_DEP where ID = ?");
            try {
                stmt.setInt(1, departmentId);
                ResultSet rs = stmt.executeQuery();
                try {
                    verify(!rs.next(), "department with id " + departmentId + " found using JDBC.");
                } finally {
                    rs.close();
                }
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    @Test
    public void testRemoveNew() throws SQLException {
        /*
         * If X is a new entity, it is ignored by the remove operation. However, the remove operation is cascaded to entities
         * referenced by X, if the relationships from X to these other entities is annotated with the cascade=REMOVE or
         * cascade=ALL annotation element value.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        env.evictAll(em);
        try {
            Department dep = new Department(1, "HUGO");
            env.beginTransaction(em);
            em.remove(dep);
            // TODO verify remove is ignored on this entity using lifecycle callbacks
            // TODO verify
            env.commitTransactionAndClear(em);
            verifyAbsenceOnDatabase(1);
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyRemoveManaged(boolean flushBeforeRemove) throws SQLException {
        /*
         * If X is a managed entity, the remove operation causes it to become removed. The remove operation is cascaded to
         * entities referenced by X, if the relationships from X to these other entities is annotated with the cascade=REMOVE or
         * cascade=ALL annotation element value.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // 1. managed and in state MANAGED
            final int id1 = (flushBeforeRemove ? 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, Integer.valueOf(id1));
            verify(dep != null, "department not found");
            dep.setName("NEW");
            if (flushBeforeRemove) {
                em.flush();
            }
            em.remove(dep);
            env.commitTransactionAndClear(em);
            verifyAbsenceOnDatabase(id1);
            // 2. managed and in state NEW
            final int id2 = (flushBeforeRemove ? 100 : 0) + 12;
            dep = new Department(id2, "OLD");
            env.beginTransaction(em);
            em.persist(dep);
            dep.setName("NEW");
            if (flushBeforeRemove) {
                em.flush();
            }
            em.remove(dep);
            env.commitTransactionAndClear(em);
            verifyAbsenceOnDatabase(id2);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRemoveManaged() throws SQLException {
        verifyRemoveManaged(false);
    }

    @Test
    public void testRemoveManagedFlushed() throws SQLException {
        verifyRemoveManaged(true);
    }

    private void verifyRemoveRemoved(boolean flushBeforePersist) throws SQLException {
        /*
         * If X is a removed entity, it is ignored by the remove operation.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        env.evictAll(em);
        try {
            // 1. find an existing department, remove it and remove it again
            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, Integer.valueOf(id1));
            em.remove(dep);
            // no, the entity should be REMOVED
            if (flushBeforePersist) {
                em.flush();
            }
            em.remove(dep);
            env.commitTransactionAndClear(em);
            // now, the entity should be managed again
            verifyAbsenceOnDatabase(id1);
            // 2. persist a new depatrment, remove it and call remove
            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.remove(dep);
            env.commitTransactionAndClear(em);
            verifyAbsenceOnDatabase(id2);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRemoveRemoved() throws SQLException {
        verifyRemoveRemoved(false);
    }

    @Test
    public void testRemoveRemovedFlushed() throws SQLException {
        verifyRemoveRemoved(true);
    }

    @Test
    public void testRemoveDetached() {
        /*
         * If X is a detached entity, an IllegalArgumentException will be thrown by the remove operation (or the transaction
         * commit will fail).
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        Department detachedDep;
        try {
            // case 1: detached because entity exists on db but is not known by persistence context
            id = 31;
            dep = new Department(id, "DETACHED");
            // firstly, we create a department on the database
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            // now the department is detached, we try to remove it
            env.beginTransaction(em);
            boolean failed = false;
            try {
                em.remove(dep);
            } catch (IllegalArgumentException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (PersistenceException e) {
                failed = true;
            }
            verify(failed, "remove succeeded 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, "MANAGED_NEW");
            detachedDep = new Department(id, "DETACHED");
            failed = false;
            env.beginTransaction(em);
            em.persist(dep); // object is now in state MANAGED_NEW
            try {
                em.remove(detachedDep);
            } catch (IllegalArgumentException e) {
                failed = true;
                env.rollbackTransaction(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (PersistenceException e) {
                failed = true;
            }
            verify(failed, "remove succeeded on a detached instance.");
            // case 2b: state of known object: FOR_UPDATE
            id = 33;
            dep = new Department(id, "MANAGED");
            detachedDep = new Department(id, "DETACHED");
            failed = false;
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(id)); // object is now in state MANAGED
            try {
                em.remove(detachedDep);
            } catch (IllegalArgumentException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (PersistenceException e) {
                failed = true;
            }
            verify(failed, "remove succeeded on a detached instance.");
            // case 2c: state of known object: FOR_DELETE
            id = 34;
            dep = new Department(id, "DELETED");
            detachedDep = new Department(id, "DETACHED");
            failed = false;
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(id));
            em.remove(dep); // object is now in state DELETED
            try {
                em.remove(detachedDep);
            } catch (IllegalArgumentException e) {
                failed = true;
                env.rollbackTransactionAndClear(em);
            }
            try {
                if (env.isTransactionActive(em)) {
                    env.commitTransactionAndClear(em);
                }
            } catch (PersistenceException e) {
                failed = true;
            }
            verify(failed, "remove succeeded on a detached instance.");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid=309681) // INTERPRETATION: SAP JPA has special state DELETED_EXECUTED, which EclipseLink hasn't
    public void testRemoveFlushRemoveAgain() {
        /*
         * If X is a detached entity, an IllegalArgumentException will be thrown by the remove operation (or the transaction
         * commit will fail).
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        Department detachedDep;
        try {
        // case 2d: state of known object: DELETE_EXECUTED
        id = 35;
        dep = new Department(id, "DELETED");
        detachedDep = new Department(id, "DETACHED");
        boolean failed = false;
        env.beginTransaction(em);
        em.persist(dep);
        env.commitTransactionAndClear(em);
        env.beginTransaction(em);
        dep = em.find(Department.class, Integer.valueOf(id));
        em.remove(dep);
        em.flush();
        try {
            em.remove(detachedDep);
        } catch (IllegalArgumentException e) {
            failed = true;
            env.rollbackTransactionAndClear(em);
        }
        try {
            if (env.isTransactionActive(em)) {
                env.commitTransactionAndClear(em);
            }
        } catch (PersistenceException e) {
            failed = true;
        }
        verify(failed, "remove succeeded on a detached instance.");
    } finally {
        closeEntityManager(em);
    }
    }

    @Test
    public void testNotAnEntity() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            try {
                em.remove("Hutzliputz");
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
            env.beginTransaction(em);
            try {
                em.remove(null);
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRemoveWithCompositeKey() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Cubicle cub = new Cubicle(Integer.valueOf(30), Integer.valueOf(31), "green", null /* employee */);
            CubiclePrimaryKeyClass cubKey = new CubiclePrimaryKeyClass(Integer.valueOf(30), Integer.valueOf(31));
            env.beginTransaction(em);
            em.persist(cub);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            cub = em.find(Cubicle.class, cubKey);
            em.remove(cub);
            env.commitTransactionAndClear(em);
            cub = em.find(Cubicle.class, cubKey);
            verify(cub == null, "cubicle not removed");
        } 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(40, "dep40");
        try {
            em.remove(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();
        Department dep = new Department(41, "dep41");
        try {
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(dep.getId()));
            env.markTransactionForRollback(em);
            em.remove(dep);
            verify(!em.contains(dep), "entity still contained in persistence context");
            env.rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }
}
