// Path: src/main/java/de/gessnerfl/fakesmtp/model/Email.java
// @Entity
// @Table(name = "email")
// public class Email {
//     @Id
//     @SequenceGenerator(name = "email_generator", sequenceName = "email_sequence", allocationSize = 1)
//     @GeneratedValue(generator = "email_generator")
//     private Long id;
// 
//     @Column(name="from_address", length = 255, nullable = false)
//     @Basic(optional = false)
//     private String fromAddress;
// 
//     @Column(name="to_address", length = 255, nullable = false)
//     @Basic(optional = false)
//     private String toAddress;
// 
//     @Lob
//     @Column(name="subject", nullable = false)
//     @Basic(optional = false)
//     private String subject;
// 
//     @Column(name="received_on", nullable = false)
//     @Basic(optional = false)
//     @Temporal(TemporalType.TIMESTAMP)
//     private Date receivedOn;
// 
//     @Lob
//     @Column(name="raw_data", nullable = false)
//     @Basic(optional = false)
//     private String rawData;
// 
//     @OneToMany(mappedBy="email", cascade = CascadeType.ALL, orphanRemoval=true)
//     private List<EmailContent> contents = new ArrayList<>();
// 
//     @OneToMany(mappedBy="email", cascade = CascadeType.ALL, orphanRemoval=true)
//     private List<EmailAttachment> attachments = new ArrayList<>();
// 
//     public Long getId() {
//         return id;
//     }
// 
//     public void setId(Long id) {
//         this.id = id;
//     }
// 
//     public String getFromAddress() {
//         return fromAddress;
//     }
// 
//     public void setFromAddress(String fromAddress) {
//         this.fromAddress = fromAddress;
//     }
// 
//     public String getToAddress() {
//         return toAddress;
//     }
// 
//     public void setToAddress(String toAddress) {
//         this.toAddress = toAddress;
//     }
// 
//     public String getSubject() {
//         return subject;
//     }
// 
//     public void setSubject(String subject) {
//         this.subject = subject;
//     }
// 
//     public Date getReceivedOn() {
//         return receivedOn;
//     }
// 
//     public void setReceivedOn(Date receivedOn) {
//         this.receivedOn = receivedOn;
//     }
// 
//     public void setRawData(String rawData){
//         this.rawData = rawData;
//     }
// 
//     public String getRawData() {
//         return rawData;
//     }
// 
//     public void addContent(EmailContent content) {
//         content.setEmail(this);
//         contents.add(content);
//     }
// 
//     @JsonIgnore
//     public List<EmailContent> getContents() {
//         return contents.stream().sorted(comparing(EmailContent::getContentType)).collect(toList());
//     }
// 
//     @JsonIgnore
//     public Optional<EmailContent> getPlainContent(){
//         return getContentOfType(ContentType.PLAIN);
//     }
// 
//     @JsonIgnore
//     public Optional<EmailContent> getHtmlContent(){
//         return getContentOfType(ContentType.HTML);
//     }
// 
//     private Optional<EmailContent> getContentOfType(ContentType contentType){
//         return contents.stream().filter(c -> contentType.equals(c.getContentType())).findFirst();
//     }
// 
//     public void addAttachment(EmailAttachment attachment) {
//         attachment.setEmail(this);
//         attachments.add(attachment);
//     }
// 
//     public List<EmailAttachment> getAttachments() {
//         return attachments;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         var email = (Email) o;
// 
//         return id.equals(email.id);
//     }
// 
//     @Override
//     public int hashCode() {
//         return id.hashCode();
//     }
// }
// 
// Path: src/main/java/de/gessnerfl/fakesmtp/repository/EmailRepository.java
// @Repository
// public interface EmailRepository extends JpaRepository<Email,Long>{
// 
//     @Transactional
//     @Modifying
//     @Query(value = "DELETE email o WHERE o.id IN ( SELECT i.id FROM email i ORDER BY i.received_on DESC OFFSET ?1)", nativeQuery = true)
//     int deleteEmailsExceedingDateRetentionLimit(int maxNumber);
// }


import de.gessnerfl.fakesmtp.model.Email;
import de.gessnerfl.fakesmtp.repository.EmailRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatcher;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.info.BuildProperties;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import java.util.Optional;
import static org.mockito.Mockito.*;
        when(emailRepository.findById(id)).thenReturn(Optional.of(mail));
        when(buildProperties.getVersion()).thenReturn(appVersion);

        var result = sut.getEmailById(id, model);

        Assertions.assertEquals(EmailController.SINGLE_EMAIL_VIEW, result);

        verify(emailRepository).findById(id);
        verify(model).addAttribute(EmailController.SINGLE_EMAIL_MODEL_NAME, mail);
        verify(buildProperties).getVersion();
        verify(model).addAttribute(EmailController.APP_VERSION_MODEL_NAME, appVersion);
        verifyNoMoreInteractions(emailRepository, buildProperties, model);
    }

    @Test
    void shouldReturnRedirectToListPageWhenIdIsNotValid() {
        var id = 12L;
        when(emailRepository.findById(id)).thenReturn(Optional.empty());

        var result = sut.getEmailById(id, model);

        Assertions.assertEquals(EmailController.REDIRECT_EMAIL_LIST_VIEW, result);

        verify(emailRepository).findById(id);
        verifyNoMoreInteractions(emailRepository);
        verifyNoInteractions(buildProperties, model);
    }

    private Page<Email> createFirstPageEmail() {
        var page = mock(Page.class);
// Path: src/main/java/de/gessnerfl/fakesmtp/model/Email.java
// @Entity
// @Table(name = "email")
// public class Email {
//     @Id
//     @SequenceGenerator(name = "email_generator", sequenceName = "email_sequence", allocationSize = 1)
//     @GeneratedValue(generator = "email_generator")
//     private Long id;
// 
//     @Column(name="from_address", length = 255, nullable = false)
//     @Basic(optional = false)
//     private String fromAddress;
// 
//     @Column(name="to_address", length = 255, nullable = false)
//     @Basic(optional = false)
//     private String toAddress;
// 
//     @Lob
//     @Column(name="subject", nullable = false)
//     @Basic(optional = false)
//     private String subject;
// 
//     @Column(name="received_on", nullable = false)
//     @Basic(optional = false)
//     @Temporal(TemporalType.TIMESTAMP)
//     private Date receivedOn;
// 
//     @Lob
//     @Column(name="raw_data", nullable = false)
//     @Basic(optional = false)
//     private String rawData;
// 
//     @OneToMany(mappedBy="email", cascade = CascadeType.ALL, orphanRemoval=true)
//     private List<EmailContent> contents = new ArrayList<>();
// 
//     @OneToMany(mappedBy="email", cascade = CascadeType.ALL, orphanRemoval=true)
//     private List<EmailAttachment> attachments = new ArrayList<>();
// 
//     public Long getId() {
//         return id;
//     }
// 
//     public void setId(Long id) {
//         this.id = id;
//     }
// 
//     public String getFromAddress() {
//         return fromAddress;
//     }
// 
//     public void setFromAddress(String fromAddress) {
//         this.fromAddress = fromAddress;
//     }
// 
//     public String getToAddress() {
//         return toAddress;
//     }
// 
//     public void setToAddress(String toAddress) {
//         this.toAddress = toAddress;
//     }
// 
//     public String getSubject() {
//         return subject;
//     }
// 
//     public void setSubject(String subject) {
//         this.subject = subject;
//     }
// 
//     public Date getReceivedOn() {
//         return receivedOn;
//     }
// 
//     public void setReceivedOn(Date receivedOn) {
//         this.receivedOn = receivedOn;
//     }
// 
//     public void setRawData(String rawData){
//         this.rawData = rawData;
//     }
// 
//     public String getRawData() {
//         return rawData;
//     }
// 
//     public void addContent(EmailContent content) {
//         content.setEmail(this);
//         contents.add(content);
//     }
// 
//     @JsonIgnore
//     public List<EmailContent> getContents() {
//         return contents.stream().sorted(comparing(EmailContent::getContentType)).collect(toList());
//     }
// 
//     @JsonIgnore
//     public Optional<EmailContent> getPlainContent(){
//         return getContentOfType(ContentType.PLAIN);
//     }
// 
//     @JsonIgnore
//     public Optional<EmailContent> getHtmlContent(){
//         return getContentOfType(ContentType.HTML);
//     }
// 
//     private Optional<EmailContent> getContentOfType(ContentType contentType){
//         return contents.stream().filter(c -> contentType.equals(c.getContentType())).findFirst();
//     }
// 
//     public void addAttachment(EmailAttachment attachment) {
//         attachment.setEmail(this);
//         attachments.add(attachment);
//     }
// 
//     public List<EmailAttachment> getAttachments() {
//         return attachments;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         var email = (Email) o;
// 
//         return id.equals(email.id);
//     }
// 
//     @Override
//     public int hashCode() {
//         return id.hashCode();
//     }
// }
// 
// Path: src/main/java/de/gessnerfl/fakesmtp/repository/EmailRepository.java
// @Repository
// public interface EmailRepository extends JpaRepository<Email,Long>{
// 
//     @Transactional
//     @Modifying
//     @Query(value = "DELETE email o WHERE o.id IN ( SELECT i.id FROM email i ORDER BY i.received_on DESC OFFSET ?1)", nativeQuery = true)
//     int deleteEmailsExceedingDateRetentionLimit(int maxNumber);
// }


// Path: src/test/java/de/gessnerfl/fakesmtp/controller/EmailControllerTest.java
import de.gessnerfl.fakesmtp.model.Email;
import de.gessnerfl.fakesmtp.repository.EmailRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentMatcher;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.info.BuildProperties;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import java.util.Optional;
import static org.mockito.Mockito.*;

        when(emailRepository.findById(id)).thenReturn(Optional.of(mail));
        when(buildProperties.getVersion()).thenReturn(appVersion);

        var result = sut.getEmailById(id, model);

        Assertions.assertEquals(EmailController.SINGLE_EMAIL_VIEW, result);

        verify(emailRepository).findById(id);
        verify(model).addAttribute(EmailController.SINGLE_EMAIL_MODEL_NAME, mail);
        verify(buildProperties).getVersion();
        verify(model).addAttribute(EmailController.APP_VERSION_MODEL_NAME, appVersion);
        verifyNoMoreInteractions(emailRepository, buildProperties, model);
    }

    @Test
    void shouldReturnRedirectToListPageWhenIdIsNotValid() {
        var id = 12L;
        when(emailRepository.findById(id)).thenReturn(Optional.empty());

        var result = sut.getEmailById(id, model);

        Assertions.assertEquals(EmailController.REDIRECT_EMAIL_LIST_VIEW, result);

        verify(emailRepository).findById(id);
        verifyNoMoreInteractions(emailRepository);
        verifyNoInteractions(buildProperties, model);
    }

    private Page<Email> createFirstPageEmail() {
        var page = mock(Page.class);
        when(page.getNumber()).thenReturn(0);