/*
 * 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, 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, 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, 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, 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, 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(30, 31, "green", null /* employee */);
            CubiclePrimaryKeyClass cubKey = new CubiclePrimaryKeyClass(30, 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, dep.getId());
            env.markTransactionForRollback(em);
            em.remove(dep);
            verify(!em.contains(dep), "entity still contained in persistence context");
            env.rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }
}
