package worker

import (
	"github.com/hibiken/asynq"
	"github.com/rs/zerolog/log"
)

// Task types for email jobs
const (
	TypeWelcomeEmail         = "email:welcome"
	TypeVerificationEmail    = "email:verification"
	TypePasswordResetEmail   = "email:password_reset"
	TypePasswordChangedEmail = "email:password_changed"
)

// EmailPayload is the base payload for email tasks
type EmailPayload struct {
	To        string `json:"to"`
	FirstName string `json:"first_name"`
}

// WelcomeEmailPayload is the payload for welcome emails
type WelcomeEmailPayload struct {
	EmailPayload
	ConfirmationCode string `json:"confirmation_code"`
}

// VerificationEmailPayload is the payload for verification emails
type VerificationEmailPayload struct {
	EmailPayload
	Code string `json:"code"`
}

// PasswordResetEmailPayload is the payload for password reset emails
type PasswordResetEmailPayload struct {
	EmailPayload
	Code       string `json:"code"`
	ResetToken string `json:"reset_token"`
}

// TaskClient wraps the asynq client for enqueuing tasks
type TaskClient struct {
	client *asynq.Client
}

// NewTaskClient creates a new task client
func NewTaskClient(redisAddr string) *TaskClient {
	client := asynq.NewClient(asynq.RedisClientOpt{Addr: redisAddr})
	return &TaskClient{client: client}
}

// Close closes the task client
func (c *TaskClient) Close() error {
	return c.client.Close()
}

// EnqueueWelcomeEmail enqueues a welcome email task
func (c *TaskClient) EnqueueWelcomeEmail(to, firstName, code string) error {
	payload, err := BuildWelcomeEmailPayload(to, firstName, code)
	if err != nil {
		return err
	}

	task := asynq.NewTask(TypeWelcomeEmail, payload)
	_, err = c.client.Enqueue(task, asynq.Queue("default"), asynq.MaxRetry(3))
	if err != nil {
		log.Error().Err(err).Str("to", to).Msg("Failed to enqueue welcome email")
		return err
	}

	log.Debug().Str("to", to).Msg("Welcome email task enqueued")
	return nil
}

// EnqueueVerificationEmail enqueues a verification email task
func (c *TaskClient) EnqueueVerificationEmail(to, firstName, code string) error {
	payload, err := BuildVerificationEmailPayload(to, firstName, code)
	if err != nil {
		return err
	}

	task := asynq.NewTask(TypeVerificationEmail, payload)
	_, err = c.client.Enqueue(task, asynq.Queue("default"), asynq.MaxRetry(3))
	if err != nil {
		log.Error().Err(err).Str("to", to).Msg("Failed to enqueue verification email")
		return err
	}

	log.Debug().Str("to", to).Msg("Verification email task enqueued")
	return nil
}

// EnqueuePasswordResetEmail enqueues a password reset email task
func (c *TaskClient) EnqueuePasswordResetEmail(to, firstName, code, resetToken string) error {
	payload, err := BuildPasswordResetEmailPayload(to, firstName, code, resetToken)
	if err != nil {
		return err
	}

	task := asynq.NewTask(TypePasswordResetEmail, payload)
	_, err = c.client.Enqueue(task, asynq.Queue("default"), asynq.MaxRetry(3))
	if err != nil {
		log.Error().Err(err).Str("to", to).Msg("Failed to enqueue password reset email")
		return err
	}

	log.Debug().Str("to", to).Msg("Password reset email task enqueued")
	return nil
}

// EnqueuePasswordChangedEmail enqueues a password changed confirmation email
func (c *TaskClient) EnqueuePasswordChangedEmail(to, firstName string) error {
	payload, err := BuildPasswordChangedEmailPayload(to, firstName)
	if err != nil {
		return err
	}

	task := asynq.NewTask(TypePasswordChangedEmail, payload)
	_, err = c.client.Enqueue(task, asynq.Queue("default"), asynq.MaxRetry(3))
	if err != nil {
		log.Error().Err(err).Str("to", to).Msg("Failed to enqueue password changed email")
		return err
	}

	log.Debug().Str("to", to).Msg("Password changed email task enqueued")
	return nil
}
