package text

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/rs/zerolog/log"
	"source.gleipnir.technology/Gleipnir/nidus-sync/config"
	"source.gleipnir.technology/Gleipnir/nidus-sync/lint"
)

var VOIP_MS_API = "https://voip.ms/api/v1/rest.php"

type VoipMSResponse struct {
	MMS     int    `json:"mms"`
	Message string `json:"message"`
	Status  string `json:"status"`
	SMS     int    `json:"sms"`
}

func sendTextVoipms(ctx context.Context, to string, content string, media ...string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()

	if len(content) > 2048 {
		return "", errors.New("Message content is more than 160 characters")
	}
	params := url.Values{}
	params.Add("api_password", config.VoipMSPassword)
	params.Add("api_username", config.VoipMSUsername)
	params.Add("method", "sendMMS")
	params.Add("did", config.VoipMSNumber)
	params.Add("dst", to)
	params.Add("message", content)
	/*
	   for i, med := range media {
	           // These should be one of:
	           //  1. A full URL that the service cat GET
	           //  2. A base64-encoded image starting with "data:image/png;base64,iVBORw0KGgoAAAANSUh..."
	           params.Add(fmt.Sprintf("media%d", i+1), med)
	   }
	   params.Add(fmt.Sprintf("media%d", len(media)+1), "")
	*/

	response, err := makeVoipMSRequest(params)
	if err != nil {
		return "", fmt.Errorf("Failed to send MMS: %w", err)
	}
	if response.Status == "ip_not_enabled" {
		return "", fmt.Errorf("Failed to send SMS: the IP address of the server is not enabled with voip.ms. You'll need to enable this server's IP with them.")
	}
	log.Info().Str("status", response.Status).Int("mms", response.MMS).Msg("Sent MMS message")
	return strconv.Itoa(response.MMS), nil
}

func makeVoipMSRequest(params url.Values) (VoipMSResponse, error) {
	result := VoipMSResponse{}
	// Construct the URL with query parameters
	full_url := VOIP_MS_API + "?" + params.Encode()

	// Make the HTTP request
	log.Debug().Str("full_url", full_url).Msg("Sending command to VoIP.ms")
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, "GET", full_url, nil)
	if err != nil {
		return result, fmt.Errorf("Error creating request: %w", err)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Warn().Err(err).Str("url", full_url).Msg("Failed to make request to Voip.MS")
		return result, fmt.Errorf("Error making request: %w", err)
	}
	defer lint.LogOnErr(resp.Body.Close, "failed closing response body")

	// Read the response body
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Warn().Err(err).Str("url", full_url).Msg("Failed to read Voip.MS response body")
		return result, fmt.Errorf("Failed to read response: %w", err)
	}
	log.Info().Str("response", string(body)).Msg("Response from Voip.MS")

	// Parse the JSON response
	var response VoipMSResponse
	err = json.Unmarshal(body, &response)
	if err != nil {
		return result, fmt.Errorf("Failed to unmarshal JSON response: %w", err)
	}
	return response, nil
}
