package sms

import (
	"context"
	"fmt"
	"net/http"

	"github.com/minchao/go-mitake"
)

// MitakeSettings configures 三竹 Mitake SMS (ported from app-cloudep-notification-service).
type MitakeSettings struct {
	Sort     int
	User     string
	Password string
}

// MitakeSender delivers SMS via Mitake SmExpress API.
type MitakeSender struct {
	name   string
	sort   int
	client *mitake.Client
}

// NewMitakeSender builds a Mitake provider.
func NewMitakeSender(cfg MitakeSettings, httpClient *http.Client) (*MitakeSender, error) {
	if cfg.User == "" || cfg.Password == "" {
		return nil, fmt.Errorf("sms mitake: user and password are required")
	}
	return &MitakeSender{
		name:   "mitake",
		sort:   cfg.Sort,
		client: mitake.NewClient(cfg.User, cfg.Password, httpClient),
	}, nil
}

func (m *MitakeSender) Name() string { return m.name }
func (m *MitakeSender) Sort() int    { return m.sort }

func (m *MitakeSender) Send(ctx context.Context, msg *Message) (string, error) {
	if err := ctx.Err(); err != nil {
		return "", err
	}
	if msg == nil || msg.PhoneNumber == "" {
		return "", fmt.Errorf("sms mitake: phone number is required")
	}
	if msg.Body == "" {
		return "", fmt.Errorf("sms mitake: body is required")
	}

	// SDK has no context support; check before the HTTP call.
	if err := ctx.Err(); err != nil {
		return "", err
	}

	resp, err := m.client.Send(mitake.Message{
		Dstaddr:  msg.PhoneNumber,
		Destname: msg.RecipientName,
		Smbody:   msg.Body,
	})
	if err != nil {
		return "", fmt.Errorf("sms mitake: %w", err)
	}
	if resp == nil || len(resp.Results) == 0 {
		return "", fmt.Errorf("sms mitake: empty response")
	}
	r := resp.Results[0]
	if err := mitakeStatusError(r.Statuscode); err != nil {
		return "", err
	}
	if r.Msgid == "" {
		return "", fmt.Errorf("sms mitake: empty msgid")
	}
	return r.Msgid, nil
}

func mitakeStatusError(code string) error {
	switch mitake.StatusCode(code) {
	case mitake.StatusReservationForDelivery,
		mitake.StatusCarrierAccepted,
		mitake.StatusCarrierAccepted2,
		mitake.StatusCarrierAccepted3,
		mitake.StatusDelivered:
		return nil
	default:
		return fmt.Errorf("sms mitake: status %s (%s)", code, mitake.StatusCode(code).String())
	}
}
