package webui

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"

	"mailgoserver/internal/db"
	"mailgoserver/internal/mailstore"
)

// TestWebmailComposeSendBouncesFailedRecipientToSenderInbox confirms that when one
// recipient in a multi-recipient send fails (here: an over-quota local mailbox, caught
// only at delivery time — RCPT-equivalent resolution succeeds), the sender still gets
// their flash "sent, but..." feedback AND a persistent bounce notification lands in
// their own INBOX, mirroring a real mail provider's delivery-failure notice.
func TestWebmailComposeSendBouncesFailedRecipientToSenderInbox(t *testing.T) {
	app := newTestApp(t)
	mux := app.Mux()
	domains, _ := app.DB.ListDomains()
	domainID := domains[0].ID

	senderID := createTestMailboxWithPassword(t, app, "sender@example.com", domainID, "sender-password-1!")

	// A second local mailbox with an effectively-zero quota, so StoreMessage always
	// fails with ErrQuotaExceeded — a hermetic, deterministic delivery failure with no
	// network dependency (unlike a relay-to-external-domain failure would be).
	hash, err := db.HashPassword("full-password-1!")
	if err != nil {
		t.Fatal(err)
	}
	wrapped, nonce, err := app.Mailstore.WrapDEK(mailstore.GenerateDEK())
	if err != nil {
		t.Fatal(err)
	}
	fullID, err := app.DB.CreateMailbox("full@example.com", hash, domainID, 1, wrapped, nonce)
	if err != nil {
		t.Fatal(err)
	}

	cookie := webmailLoginSession(t, app, senderID)
	form := url.Values{
		"to": {"full@example.com"}, "subject": {"Big attachment incoming"}, "body_html": {"body text"},
	}
	req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/compose", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.AddCookie(cookie)
	rec := httptest.NewRecorder()
	mux.ServeHTTP(rec, req)
	if rec.Code != http.StatusFound {
		t.Fatalf("compose send: status=%d body=%s", rec.Code, rec.Body.String())
	}

	fullMsgs, err := app.DB.ListMessagesInFolder(fullID, "INBOX")
	if err != nil {
		t.Fatal(err)
	}
	if len(fullMsgs) != 0 {
		t.Fatalf("expected no message delivered to the over-quota mailbox, got %d", len(fullMsgs))
	}

	bounces, err := app.DB.ListMessagesInFolder(senderID, "INBOX")
	if err != nil {
		t.Fatal(err)
	}
	if len(bounces) != 1 {
		t.Fatalf("expected 1 bounce message in the sender's own INBOX, got %d", len(bounces))
	}
	if bounces[0].CachedSubject != "Undelivered Mail Returned to Sender" {
		t.Errorf("bounce subject = %q", bounces[0].CachedSubject)
	}
}
