package sms

import (
	"fmt"
	"io"
	"log"
	"strings"

	"gitea.unprism.ru/KRBL/sim-modem/api/modem/at"
)

type dialer struct {
	logger *log.Logger
	port   at.Port
}

type Sms interface {
	Init() error
	Send(number, msg string) error // Send sms
	ReadNew() ([]string, error)    // Read new smses

	io.Closer
}

func New(logger *log.Logger, port at.Port) Sms {
	return &dialer{
		logger: logger,
		port:   port,
	}
}

func (d *dialer) Init() error {
	// Ensure serial port
	if !d.port.IsConnected() {
		return fmt.Errorf("serial port is not connected")
	}

	// Check SIM an PIN
	if resp, err := d.port.Send("AT+CPIN?"); err != nil || !resp.Check() {
		if err != nil {
			return fmt.Errorf("check pin: %w", err)
		}
		return fmt.Errorf("check pin: error response: %s", resp)
	}

	// Ensure text format
	d.logger.Println(d.port.Send("AT+CMGF"))
	if resp, err := d.port.Send("AT+CMGF=1"); err != nil || !resp.Check() {
		if err != nil {
			return fmt.Errorf("set to text format request: %w", err)
		}
		return fmt.Errorf("set SIM format: error response: %s", resp)
	}
	return nil
}

func (d *dialer) Send(number, msg string) error {
	d.port.Send(fmt.Sprintf(`AT+CMGS="%s"`, number))        // Because it will throw error
	resp, err := d.port.RawSend(fmt.Sprintf("%s\n\r", msg)) // Add additional \r\n because there is not supposed to be
	if err != nil {
		return fmt.Errorf("message request: %w", err)
	}
	d.logger.Println("SEND RESPONSE:", resp)
	resp, err = d.port.RawSend("\x1A")
	if err != nil {
		return fmt.Errorf("message request: %w", err)
	}
	d.logger.Println("SEND RESPONSE:", resp)
	errCode, err := GetError([]byte(resp))
	if err != nil {
		return fmt.Errorf("send sms failed and failed to get error: %w", err)
	}
	return fmt.Errorf("failed to send with SMS error: %d - %s", errCode, DecodeError(errCode))
}

// Reads all new messages
func (d *dialer) ReadNew() ([]string, error) {
	resp, err := d.port.Send("AT+CMGL=\"UNREAD\"")
	if err != nil {
		return nil, fmt.Errorf("AT+CMGL request: %w", err)
	}
	msgs := strings.Split(strings.Replace(string(resp), "\r", "", -1), "\n")

	outMsgs := make([]string, 0)
	for _, s := range msgs {
		if len(s) >= len("+CMGL:") && s[:len("+CMGL:")] == "+CMGL:" {
			params := strings.Split(s[len("+CMGL:"):], ",")
			d.logger.Println("GET MSG:", params)
		} else {
			outMsgs = append(outMsgs, s)
		}
	}

	return outMsgs, nil // TODO
}

func (d *dialer) Close() error {
	return nil
}