package services

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
)

const websmsAPIBase = "https://api.labsmobile.com/json/send"

type WebSmsRequest struct {
	Message   string           `json:"message"`
	TPOA      string           `json:"tpoa,omitempty"`
	Recipient []WebSmsRecipient `json:"recipient"`
}

type WebSmsRecipient struct {
	MSISDN string `json:"msisdn"`
}

type WebSmsResponse struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	ID      string `json:"id"`
	SubID   string `json:"subid"`
}

func (r *WebSmsResponse) MsgID() string {
	if r.ID != "" {
		return r.ID
	}
	return r.SubID
}

type WebSmsAckPayload struct {
	ID        string `json:"id"`
	Reference string `json:"reference"`
	Status    string `json:"status"`
	Msisdn    string `json:"msisdn"`
	Substatus string `json:"substatus"`
	Timestamp string `json:"timestamp"`
}

type WebSmsClickPayload struct {
	ID        string `json:"id"`
	Reference string `json:"reference"`
	Msisdn    string `json:"msisdn"`
	URL       string `json:"url"`
	Timestamp string `json:"timestamp"`
}

type WebSmsIncomingPayload struct {
	ID        string `json:"id"`
	Msisdn    string `json:"msisdn"`
	Message   string `json:"message"`
	Shortcode string `json:"shortcode"`
	Timestamp string `json:"timestamp"`
}

func SendWebSms(cfg *models.WebSmsConfig, para, mensaje string) (*WebSmsResponse, error) {
	auth := base64.StdEncoding.EncodeToString([]byte(cfg.Username + ":" + cfg.ApiToken))

	req := WebSmsRequest{
		Message: mensaje,
		Recipient: []WebSmsRecipient{{MSISDN: para}},
	}
	if cfg.Sender != "" {
		req.TPOA = cfg.Sender
	}

	body, err := json.Marshal(req)
	if err != nil {
		return nil, fmt.Errorf("websms: marshal: %w", err)
	}

	httpReq, err := http.NewRequest("POST", websmsAPIBase, bytes.NewReader(body))
	if err != nil {
		return nil, err
	}
	httpReq.Header.Set("Authorization", "Basic "+auth)
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Accept", "application/json")

	client := &http.Client{Timeout: 15 * time.Second}
	resp, err := client.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("websms: http: %w", err)
	}
	defer resp.Body.Close()

	respBody, _ := io.ReadAll(resp.Body)

	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
		return nil, fmt.Errorf("websms API status %d: %s", resp.StatusCode, string(respBody))
	}

	ct := resp.Header.Get("Content-Type")
	var result WebSmsResponse
	if err := json.Unmarshal(respBody, &result); err != nil {
		return nil, fmt.Errorf("websms: respuesta no JSON (Content-Type: %s, cuerpo: %.200s)", ct, string(respBody))
	}

	if result.Code != "0" {
		return nil, fmt.Errorf("websms: %s (code %s)", result.Message, result.Code)
	}

	return &result, nil
}
