/*
 * 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 static org.junit.Assert.fail;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.Query;
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.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Review;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Ignore;
import org.junit.Test;

public class TestRefresh extends JPA1Base {

    @Test
    public void testRefreshNew() {
        /*
         * Refresh on an entity that is not under control of the entity manager
         * should throw an IllegalArgumentException.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            id = 1;
            dep = new Department(id, "NEW");
            env.beginTransaction(em);
            try {
                em.refresh(dep);
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testRefreshManagedNew() throws SQLException {
        /*
         * Note: The specification doesn't state explicitly how to behave in
         * this case, so we test our interpretation: - If the entity doesn't
         * exist on the database, nothing is changed - If the entity exists on
         * the database, the data is loaded and the state changes from
         * FOR_INSERT to FOR_UPDATE (in order to avoid errors at flush time)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            // case 2: state MANAGED_NEW, but exists on DB (inserted in
            // different tx)
            id = 12;
            dep = new Department(id, "MANAGED_NEW");
            Department depInserted = new Department(id, "INSERTED");
            env.beginTransaction(em);
            em.persist(dep);
            insertDepartmentIntoDatabase(depInserted);
            verifyExistenceOnDatabase(id);
            // entity is now in state MANAGED_NEW, but record exists on db
            em.refresh(dep);
            checkDepartment(dep, id, "INSERTED"); // this should now be in state
                                                  // MANAGED
            verify(em.contains(dep), "Department is not managed");
            dep.setName("UPDATED");
            env.commitTransactionAndClear(em);
            // verify that updated name present on db
            dep = em.find(Department.class, id);
            checkDepartment(dep, id, "UPDATED");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testRefreshManagedNewNotOnDB() throws SQLException {
        /*
         * Note: The specification doesn't state explicitly how to behave in
         * this case, so we test our interpretation: - If the entity doesn't
         * exist on the database, nothing is changed - If the entity exists on
         * the database, the data is loaded and the state changes from
         * FOR_INSERT to FOR_UPDATE (in order to avoid errors at flush time)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            // case 1: state MANAGED_NEW and does not exist on DB
            id = 11;
            dep = new Department(id, "MANAGED_NEW");
            env.beginTransaction(em);
            em.persist(dep); // this is now in state MANAGED_NEW, but not on db
            em.refresh(dep); // nothing should happen
            verify(em.contains(dep), "Department is not managed");
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(id);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRefreshManaged() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        Department updatedDep;
        try {
            // case 1: undo own changes
            id = 21;
            dep = new Department(id, "MANAGED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, id); // this is now in
                                                              // state MANAGED
            dep.setName("UPDATED");
            em.refresh(dep);
            checkDepartment(dep, id, "MANAGED");
            verify(em.contains(dep), "Department is not managed");
            env.commitTransactionAndClear(em);
            // verify that original name present on db
            dep = em.find(Department.class, id);
            checkDepartment(dep, id, "MANAGED");
            // case 2: refresh with data changed on db in a different tx
            id = 22;
            dep = new Department(id, "MANAGED");
            updatedDep = new Department(id, "UPDATED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, id); // this is now in
                                                              // state MANAGED
            updateDepartmentOnDatabase(updatedDep);
            em.refresh(dep);
            checkDepartment(dep, id, "UPDATED");
            verify(em.contains(dep), "Department is not managed");
            dep.setName("MANAGED");
            env.commitTransactionAndClear(em);
            // verify that original name present on db
            dep = em.find(Department.class, id);
            checkDepartment(dep, id, "MANAGED");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testRefreshManagedCheckContains() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            // case 3: try to refresh, but record has been deleted on db in a
            // different tx
            /*
             * We expect an EntityNotFoundException. However, the specification
             * does not state explicitly in which state the managed entity
             * should be after the exception. We are going to remove the entity
             * from the persistence context, so it is detached afterwards.
             */
            id = 23;
            dep = new Department(id, "MANAGED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, id); // this is now in
                                                              // state MANAGED
            deleteDepartmentFromDatabase(id);
            verifyAbsenceFromDatabase(em, id);
            try {
                em.refresh(dep);
                flop("refresh did not throw EntityNotFoundException");
            } catch (EntityNotFoundException e) {
                verify(true, "");
            }
            verify(!em.contains(dep), "entity still managed after EntityNotFoundException");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private void doRefreshDeleted(int id, boolean flush) throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(id, "DELETED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            dep = em.find(Department.class, id);
            em.remove(dep);
            if (flush) {
                em.flush(); // this is now in state DELETE_EXECUTED
                verifyAbsenceFromDatabase(em, id);
            }
            try {
                em.refresh(dep);
                fail("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                // expected
            }
            if (env.isTransactionActive(em)) {
                env.rollbackTransactionAndClear(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * Refreshing an entity in state "removed" should raise an
     * IllegalArgumentException
     */
    @Test
    public void testRefreshDeleted() throws SQLException {
        doRefreshDeleted(31, false);
        doRefreshDeleted(32, true);
    }

    @Test
    public void testRefreshDetached() {
        /*
         * Refresh on a detached entity should throw an
         * IllegalArgumentException.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        Department detachedDep;
        try {
            // case 1: entity exists on DB, but not contained in persistence
            // context
            id = 41;
            dep = new Department(id, "DETACHED");
            // firstly, we create a department on the database
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            try {
                em.refresh(dep);
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
            // case 2: entity is contained in persistence context, but object to
            // be merged has different object identity
            // case 2a: state of known object: MANAGED_NEW
            id = 42;
            dep = new Department(id, "MANAGED_NEW");
            detachedDep = new Department(id, "DETACHED");
            env.beginTransaction(em);
            em.persist(dep); // this is now in state new
            try {
                em.refresh(detachedDep); // this object is detached
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
            // case 2b: state of known object: MANAGED
            id = 43;
            dep = new Department(id, "MANAGED");
            detachedDep = new Department(id, "DETACHED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, id); // this is now in
                                                              // state MANAGED
            try {
                em.refresh(detachedDep); // this object is detached
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
            // case 2c: state of known object: DELETED
            id = 44;
            dep = new Department(id, "DELETED");
            detachedDep = new Department(id, "DETACHED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, id);
            em.remove(dep); // this is now in state DELETED
            try {
                em.refresh(detachedDep); // this object is detached
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNotAnEntity() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            try {
                em.refresh("Hutzliputz");
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
            env.beginTransaction(em);
            try {
                em.refresh(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();
        int id;
        Department dep;
        try {
            id = 61;
            dep = new Department(id, "NO_TX");
            verify(!env.isTransactionActive(em), "transaction is active, can't execute test");
            try {
                em.refresh(dep);
                flop("refresh did not throw TransactionRequiredException");
            } catch (TransactionRequiredException e) {
                verify(true, "");
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRefreshManagedWithRelationships() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 1: undo own changes
            Department dep = new Department(101, "Evangelists");
            Employee emp = new Employee(102, "First", "Last", dep);
            Review rev1 = new Review(103, Date.valueOf("2006-02-03"), "Code inspection");
            Review rev2 = new Review(104, Date.valueOf("2006-02-04"), "Design review");
            emp.addReview(rev1);
            emp.addReview(rev2);
            env.beginTransaction(em);
            em.persist(dep);
            em.persist(emp);
            em.persist(rev1);
            em.persist(rev2);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            emp = em.find(Employee.class, emp.getId());
            rev1 = em.find(Review.class, rev1.getId());
            Review rev3 = new Review(105, Date.valueOf("2006-02-05"), "Test coverage");
            Set<Review> reviews = new HashSet<Review>();
            reviews.add(rev1);
            reviews.add(rev3);
            emp.setReviews(reviews);
            rev1.setReviewText("UPDATED");
            em.refresh(emp);
            verify(em.contains(emp), "Employee is not managed");
            Set<Review> reviewsAfterRefresh = emp.getReviews();
            verify(reviewsAfterRefresh.size() == 2, "Employee contains wrong number of reviews: " + reviewsAfterRefresh.size());
            for (Review rev : reviewsAfterRefresh) {
                int id = rev.getId();
                verify(id == rev1.getId() || id == rev2.getId(), "Employee has wrong review: " + id);
                verify(em.contains(rev), "Review " + id + " is not managed");
            }
            env.commitTransactionAndClear(em);
            // verify that original name present on db
            rev1 = em.find(Review.class, rev1.getId());
            verify("UPDATED".equals(rev1.getReviewText()), "Rev1 has wrong text: " + rev1.getReviewText());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testTransactionMarkedForRollback() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        Department dep = new Department(111, "dep111");
        try {
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            dep = em.find(Department.class, dep.getId());
            dep.setName("updated");
            env.markTransactionForRollback(em);
            em.refresh(dep);
            checkDepartment(dep, dep.getId(), "dep111");
            verify(em.contains(dep), "entity not contained in persistence context");
            env.rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyExistenceOnDatabase(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(), "no department with id " + departmentId + " found using JDBC.");
                } finally {
                    rs.close();
                }
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void verifyAbsenceFromDatabase(EntityManager em, int id) {
        Query query = em.createQuery("SELECT d.id from Department d where d.id = ?1");
        query.setFlushMode(FlushModeType.COMMIT);
        query.setParameter(1, id);
        verify(query.getResultList().size() == 0, "wrong result list size");
    }

    private void deleteDepartmentFromDatabase(int departmentId) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("delete from TMP_DEP where ID = ?");
            try {
                stmt.setInt(1, departmentId);
                stmt.executeUpdate();
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void insertDepartmentIntoDatabase(Department department) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("insert into TMP_DEP (ID, NAME, VERSION) values (?, ?, ?)");
            try {
                stmt.setInt(1, department.getId());
                stmt.setString(2, department.getName());
                stmt.setShort(3, (short) 0);
                stmt.executeUpdate();
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void updateDepartmentOnDatabase(Department department) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("update TMP_DEP set NAME = ? where ID = ?");
            try {
                stmt.setString(1, department.getName());
                stmt.setInt(2, department.getId());
                stmt.executeUpdate();
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void checkDepartment(Department department, int id, String name) {
        verify(department != null, "department is null");
        verify(id == department.getId(), "department has wrong id: " + department.getId());
        verify(name.equals(department.getName()), "department has wrong name: " + department.getName());
    }
}
