package mail

import (
	"context"
	"encoding/json"
	"errors"

	"github.com/jackc/pgx/v5"
	"github.com/ultisuite/ulti-backend/internal/mail/webhooks"
)

func (s *Service) UpdateWebhook(ctx context.Context, externalID, webhookID string, req *updateWebhookRequest, method string, maxRetries int) error {
	headersJSON, _ := json.Marshal(req.Headers)

	tx, err := s.db.Begin(ctx)
	if err != nil {
		return err
	}
	defer tx.Rollback(ctx)

	var version int
	eventTypesJSON, err := marshalWebhookEventTypes(req.EventTypes)
	if err != nil {
		return err
	}
	mailScopeJSON, err := marshalWebhookMailScope(req.MailScope)
	if err != nil {
		return err
	}
	driveScopeJSON, err := marshalWebhookDriveScope(req.DriveScope)
	if err != nil {
		return err
	}
	contactsScopeJSON, err := marshalWebhookContactsScope(req.ContactsScope)
	if err != nil {
		return err
	}

	err = tx.QueryRow(ctx, `
		UPDATE webhook_templates
		SET
			name = $1,
			url = $2,
			method = $3,
			headers = $4,
			body_template = $5,
			signing_secret = $6,
			max_retries = $7,
			event_types = $8,
			mail_scope = $9,
			drive_scope = $10,
			contacts_scope = $11,
			version = version + 1,
			updated_at = NOW()
		WHERE id = $12
		  AND user_id = (SELECT id FROM users WHERE external_id = $13)
		RETURNING version
	`, req.Name, req.URL, method, headersJSON, req.BodyTemplate, req.SigningSecret, maxRetries,
		eventTypesJSON, mailScopeJSON, driveScopeJSON, contactsScopeJSON, webhookID, externalID).Scan(&version)
	if err != nil {
		if errors.Is(err, pgx.ErrNoRows) {
			return ErrNotFound
		}
		return err
	}

	if _, err := tx.Exec(ctx, `
		INSERT INTO webhook_template_versions (template_id, version, method, headers, body_template)
		VALUES ($1, $2, $3, $4, $5)
	`, webhookID, version, method, headersJSON, req.BodyTemplate); err != nil {
		return err
	}

	return tx.Commit(ctx)
}

func (s *Service) PreviewWebhookTemplate(_ context.Context, _ string, req *previewWebhookRequest) (map[string]any, error) {
	msgCtx := &webhooks.MessageContext{
		SenderName:    req.Message.SenderName,
		SenderEmail:   req.Message.SenderEmail,
		Subject:       req.Message.Subject,
		BodyText:      req.Message.BodyText,
		BodyHTML:      req.Message.BodyHTML,
		Date:          req.Message.Date,
		Recipients:    req.Message.Recipients,
		HasAttachment: req.Message.HasAttachment,
		MessageID:     req.Message.MessageID,
	}
	return map[string]any{
		"payload": webhooks.RenderBodyTemplate(req.BodyTemplate, msgCtx),
	}, nil
}
