package mailer

import (
	"context"
	"errors"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestSMTPMailerSendVerificationEmail(t *testing.T) {
	t.Parallel()

	transport := smtpTransportConfig{
		host:     "smtp.feishu.cn",
		port:     587,
		username: "agentteam@pingcap.com",
		password: "secret",
		security: smtpSecurityStartTLS,
	}
	var captured struct {
		transport smtpTransportConfig
		from      string
		to        string
		subject   string
		body      string
	}
	mailer := newSMTPMailer("https://agentteam.example.com", "agentteam@pingcap.com", transport, func(_ context.Context, transport smtpTransportConfig, fromAddress string, toAddress string, subject string, body string) error {
		captured.transport = transport
		captured.from = fromAddress
		captured.to = toAddress
		captured.subject = subject
		captured.body = body
		return nil
	})

	err := mailer.SendVerificationEmail(context.Background(), "user@example.com", "tok_verification")
	require.NoError(t, err)
	require.Equal(t, transport, captured.transport)
	require.Equal(t, "agentteam@pingcap.com", captured.from)
	require.Equal(t, "user@example.com", captured.to)
	require.Equal(t, "Verify your AgentTeam email", captured.subject)
	require.Contains(t, captured.body, "tok_verification")
	require.Contains(t, captured.body, "https://agentteam.example.com/?verify=tok_verification")
}

func TestSMTPMailerSendWorkspaceInviteEmail(t *testing.T) {
	t.Parallel()

	mailer := newSMTPMailer("https://agentteam.example.com", "agentteam@pingcap.com", smtpTransportConfig{
		host:     "smtp.feishu.cn",
		port:     465,
		username: "agentteam@pingcap.com",
		password: "secret",
		security: smtpSecuritySSL,
	}, func(_ context.Context, _ smtpTransportConfig, _ string, _ string, subject string, body string) error {
		require.Equal(t, "Your AgentTeam workspace invite", subject)
		require.Contains(t, body, "Ops HQ")
		require.Contains(t, body, "tok_invite")
		require.Contains(t, body, "https://agentteam.example.com/?invite=tok_invite")
		return nil
	})

	err := mailer.SendWorkspaceInviteEmail(context.Background(), "invitee@example.com", "Ops HQ", "tok_invite")
	require.NoError(t, err)
}

func TestSMTPMailerSendOrganizationInviteEmail(t *testing.T) {
	t.Parallel()

	mailer := newSMTPMailer("https://agentteam.example.com", "agentteam@pingcap.com", smtpTransportConfig{
		host:     "smtp.feishu.cn",
		port:     465,
		username: "agentteam@pingcap.com",
		password: "secret",
		security: smtpSecuritySSL,
	}, func(_ context.Context, _ smtpTransportConfig, _ string, _ string, subject string, body string) error {
		require.Equal(t, "Your AgentTeam organization invite", subject)
		require.Contains(t, body, "PingCAP Org")
		require.Contains(t, body, "tok_org_invite")
		require.Contains(t, body, "https://agentteam.example.com/?invite=tok_org_invite")
		return nil
	})

	err := mailer.SendOrganizationInviteEmail(context.Background(), "invitee@example.com", "PingCAP Org", "tok_org_invite")
	require.NoError(t, err)
}

func TestSMTPMailerPropagatesSendError(t *testing.T) {
	t.Parallel()

	mailer := newSMTPMailer("https://agentteam.example.com", "agentteam@pingcap.com", smtpTransportConfig{
		host:     "smtp.feishu.cn",
		port:     587,
		username: "agentteam@pingcap.com",
		password: "secret",
		security: smtpSecurityStartTLS,
	}, func(_ context.Context, _ smtpTransportConfig, _ string, _ string, _ string, _ string) error {
		return errors.New("boom")
	})

	err := mailer.SendVerificationEmail(context.Background(), "user@example.com", "tok_verification")
	require.EqualError(t, err, "send email via SMTP server smtp.feishu.cn:587: boom")
}

func TestNewSMTPRejectsInvalidSecurity(t *testing.T) {
	t.Parallel()

	_, err := NewSMTP(
		"https://agentteam.example.com",
		"agentteam@pingcap.com",
		"smtp.feishu.cn",
		587,
		"agentteam@pingcap.com",
		"secret",
		"plaintext",
	)
	require.EqualError(t, err, `mail SMTP security must be "ssl" or "starttls"`)
}

func TestEncodeSMTPPlainTextMessageNormalizesHeaderAndBody(t *testing.T) {
	t.Parallel()

	encoded := string(encodeSMTPPlainTextMessage("agentteam@pingcap.com", "user@example.com", "subject\rbad\nline", "line1\r\nline2\nline3\rline4"))
	require.Contains(t, encoded, "Subject: subject bad line\r\n")
	require.Contains(t, encoded, "\r\n\r\nline1\r\nline2\r\nline3\r\nline4\r\n")
}
