package webui

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

// TestWebmailSaveDraftThenSend confirms saving a draft stores it in Drafts without
// sending, reopening it via the Drafts row prefills the compose form, re-saving
// replaces the old copy (no duplicates), and finally sending it delivers the message
// and removes it from Drafts.
func TestWebmailSaveDraftThenSend(t *testing.T) {
	app := newTestApp(t)
	mux := app.Mux()
	domains, _ := app.DB.ListDomains()
	domainID := domains[0].ID

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

	// Save a draft with no recipient at all — a draft can be incomplete.
	saveForm := url.Values{"subject": {"WIP"}, "body_html": {"not done yet"}}
	saveReq := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/save-draft", strings.NewReader(saveForm.Encode()))
	saveReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	saveReq.AddCookie(cookie)
	saveRec := httptest.NewRecorder()
	mux.ServeHTTP(saveRec, saveReq)
	if saveRec.Code != http.StatusFound {
		t.Fatalf("save draft: status=%d body=%s", saveRec.Code, saveRec.Body.String())
	}

	drafts, err := app.DB.ListMessagesInFolder(senderID, "Drafts")
	if err != nil || len(drafts) != 1 {
		t.Fatalf("expected 1 draft, got %d (err=%v)", len(drafts), err)
	}
	draftID := drafts[0].ID

	// Reopening it via the Drafts prefill route shows the saved content.
	openReq := httptest.NewRequest(http.MethodGet, MailboxPrefix+"/mail/compose?draft="+strconv.FormatInt(draftID, 10)+"&folder=Drafts", nil)
	openReq.AddCookie(cookie)
	openRec := httptest.NewRecorder()
	mux.ServeHTTP(openRec, openReq)
	if openRec.Code != http.StatusOK {
		t.Fatalf("open draft: status=%d", openRec.Code)
	}
	body := openRec.Body.String()
	if !strings.Contains(body, "WIP") || !strings.Contains(body, "not done yet") {
		t.Fatalf("expected the draft's subject/body prefilled, got body: %s", body)
	}
	if !strings.Contains(body, `value="`+strconv.FormatInt(draftID, 10)+`"`) {
		t.Fatalf("expected draft_id round-tripped into the form, got body: %s", body)
	}

	// Re-save with the recipient now filled in and draft_id carried — should replace,
	// not duplicate.
	resaveForm := url.Values{
		"to": {"draft-recip@example.com"}, "subject": {"WIP"}, "body_html": {"still not done"},
		"draft_id": {strconv.FormatInt(draftID, 10)},
	}
	resaveReq := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/save-draft", strings.NewReader(resaveForm.Encode()))
	resaveReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resaveReq.AddCookie(cookie)
	mux.ServeHTTP(httptest.NewRecorder(), resaveReq)

	drafts, err = app.DB.ListMessagesInFolder(senderID, "Drafts")
	if err != nil || len(drafts) != 1 {
		t.Fatalf("expected still 1 draft after re-save, got %d (err=%v)", len(drafts), err)
	}
	newDraftID := drafts[0].ID

	// Finally send it — the message is delivered and the draft is gone.
	sendForm := url.Values{
		"to": {"draft-recip@example.com"}, "subject": {"WIP"}, "body_html": {"finally done"},
		"draft_id": {strconv.FormatInt(newDraftID, 10)},
	}
	sendReq := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/compose", strings.NewReader(sendForm.Encode()))
	sendReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	sendReq.AddCookie(cookie)
	sendRec := httptest.NewRecorder()
	mux.ServeHTTP(sendRec, sendReq)
	if sendRec.Code != http.StatusFound {
		t.Fatalf("send: status=%d body=%s", sendRec.Code, sendRec.Body.String())
	}

	msgs, err := app.DB.ListMessagesInFolder(recipientID, "INBOX")
	if err != nil || len(msgs) != 1 {
		t.Fatalf("expected 1 message delivered, got %d (err=%v)", len(msgs), err)
	}
	remainingDrafts, err := app.DB.ListMessagesInFolder(senderID, "Drafts")
	if err != nil || len(remainingDrafts) != 0 {
		t.Fatalf("expected the draft gone after sending, got %d (err=%v)", len(remainingDrafts), err)
	}
}
