package messenger

import (
	"Yimaru-Backend/internal/domain"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"

	afro "github.com/amanuelabay/afrosms-go"
	"github.com/twilio/twilio-go"
	twilioApi "github.com/twilio/twilio-go/rest/api/v2010"
)

var (
	ErrSMSProviderNotFound = errors.New("SMS Provider Not Found")
)

// If the company id is valid, it is a company based notification else its a global notification (by the super admin)
func (s *Service) SendSMS(ctx context.Context, receiverPhone, message string) error {

	var settingsList domain.SettingList

	switch settingsList.SMSProvider {
	case domain.AfroMessage:
		return s.SendAfroMessageSMS(ctx, receiverPhone, message)
	case domain.TwilioSms:
		return s.SendTwilioSMS(ctx, receiverPhone, message)
	default:
		return ErrSMSProviderNotFound
	}
}

func (s *Service) SendAfroMessageSMS(ctx context.Context, receiverPhone, message string) error {
	apiKey := s.config.AFRO_SMS_API_KEY
	senderName := s.config.AFRO_SMS_SENDER_NAME
	hostURL := s.config.ADRO_SMS_HOST_URL
	endpoint := "/api/send"

	// API endpoint has been updated
	// TODO: no need for package for the afro message operations (pretty simple stuff)
	request := afro.GetRequest(apiKey, endpoint, hostURL)
	request.BaseURL = "https://api.afromessage.com"

	request.Method = "GET"
	request.Sender(senderName)
	request.To(receiverPhone, message)

	fmt.Printf("the afro SMS request is: %v", request)

	response, err := afro.MakeRequestWithContext(ctx, request)
	if err != nil {
		return err
	}

	if response["acknowledge"] == "success" {
		return nil
	} else {
		fmt.Println(response["response"].(map[string]interface{}))
		return errors.New("SMS delivery failed")
	}
}

func (s *Service) SendAfroMessageSMSLatest(
	ctx context.Context,
	receiverPhone string,
	message string,
	callbackURL *string, // optional
) error {

	baseURL := s.config.AFROSMSConfig.AfroSMSBaseURL

	// Build query parameters explicitly
	params := url.Values{}
	params.Set("to", receiverPhone)
	params.Set("message", message)
	params.Set("sender", s.config.AFROSMSConfig.AfroSMSSenderName)

	// Optional parameters
	if s.config.AFROSMSConfig.AfroSMSIdentifierID != "" {
		params.Set("from", s.config.AFROSMSConfig.AfroSMSIdentifierID)
	}

	if callbackURL != nil {
		params.Set("callback", *callbackURL)
	}

	// Construct full URL
	reqURL := fmt.Sprintf("%s?%s", baseURL+"/api/send", params.Encode())

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
	if err != nil {
		return err
	}

	// AfroMessage authentication (API key)
	req.Header.Set("Authorization", "Bearer "+s.config.AFROSMSConfig.AfroSMSAPIKey)
	req.Header.Set("Accept", "application/json")

	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf(
			"afromessage sms failed: status=%d response=%s",
			resp.StatusCode,
			string(body),
		)
	}

	// Parse response
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return err
	}

	ack, ok := result["acknowledge"].(string)
	if !ok || ack != "success" {
		return fmt.Errorf("sms delivery failed: %v", result)
	}

	return nil
}

func (s *Service) SendTwilioSMS(ctx context.Context, receiverPhone, message string) error {
	accountSid := s.config.TwilioAccountSid
	authToken := s.config.TwilioAuthToken
	senderPhone := s.config.TwilioSenderPhoneNumber

	client := twilio.NewRestClientWithParams(twilio.ClientParams{
		Username: accountSid,
		Password: authToken,
	})

	params := &twilioApi.CreateMessageParams{}
	params.SetTo(receiverPhone)
	params.SetFrom(senderPhone)
	params.SetBody(message)

	_, err := client.Api.CreateMessage(params)
	if err != nil {
		return fmt.Errorf("%s", "Error sending SMS message: %s"+err.Error())
	}

	return nil
}
