package user

import (
	"Yimaru-Backend/internal/domain"
	"Yimaru-Backend/internal/pkgs/helpers"
	"context"
	"fmt"
	"time"

	"golang.org/x/crypto/bcrypt"
)

func (s *Service) ResendOtp(
	ctx context.Context,
	email, phone string,
) error {

	user, err := s.userStore.GetUserByEmailPhone(ctx, email, phone)
	if err != nil {
		return err
	}

	otpCode := helpers.GenerateOTP()

	message := fmt.Sprintf(
		"Welcome to Yimaru Online Learning Platform, your OTP is %s please don't share with anyone.",
		otpCode,
	)

	otp, err := s.otpStore.GetOtp(ctx, user.ID)
	if err != nil {
		return err
	}

	// Broadcast OTP (same logic as SendOtp)
	switch otp.Medium {
	case domain.OtpMediumSms:
		if err := s.messengerSvc.SendAfroMessageSMS(ctx, otp.SentTo, message); err != nil {
			return err
		}
	case domain.OtpMediumEmail:
		if err := s.messengerSvc.SendEmail(
			ctx,
			otp.SentTo,
			message,
			message,
			"Yimaru - One Time Password",
		); err != nil {
			return err
		}

	default:
		return fmt.Errorf("invalid otp medium: %s", otp.Medium)
	}

	if err := s.otpStore.UpdateOtp(ctx, otpCode, user.ID); err != nil {
		return err
	}

	return nil
}

func (s *Service) SendOtp(ctx context.Context, userID int64, sentTo string, otpFor domain.OtpFor, medium domain.OtpMedium, provider domain.SMSProvider) error {
	otpCode := helpers.GenerateOTP()

	message := fmt.Sprintf("Welcome to Yimaru Online Learning Platform, your OTP is %s please don't share with anyone.", otpCode)

	switch medium {
	case domain.OtpMediumSms:

		switch provider {
		case domain.TwilioSms:
			if err := s.messengerSvc.SendTwilioSMS(ctx, sentTo, message); err != nil {
				return err
			}
		case domain.AfroMessage:
			if err := s.messengerSvc.SendAfroMessageSMS(ctx, sentTo, message); err != nil {
				return err
			}
		default:
			return fmt.Errorf("invalid sms provider: %s", provider)
		}
	case domain.OtpMediumEmail:
		if err := s.messengerSvc.SendEmail(ctx, sentTo, message, message, "Yimaru - One Time Password"); err != nil {
			return err
		}
	}

	otp := domain.Otp{
		UserID:    userID,
		SentTo:    sentTo,
		Medium:    medium,
		For:       otpFor,
		Otp:       otpCode,
		Used:      false,
		CreatedAt: time.Now(),
		ExpiresAt: time.Now().Add(OtpExpiry),
	}

	return s.otpStore.CreateOtp(ctx, otp)
}

func hashPassword(plaintextPassword string) ([]byte, error) {
	hash, err := bcrypt.GenerateFromPassword([]byte(plaintextPassword), 12)
	if err != nil {
		return []byte{}, err
	}

	return hash, nil
}
