// package bot_net_login -- сетевой вход на сервер бота
package bot_net_login

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"

	"wartank/pkg/types"
)

// BotNetLogin -- объект сетевого входа на сервер
type BotNetLogin struct {
	botNet types.ИБотСеть
	conn   *http.Client
	cookie types.ИБотКуки
}

// NewBotNetLogin -- возвращает новый *NetLogin
func NewBotNetLogin(botNet types.ИБотСеть) (*BotNetLogin, error) {
	{ // Предусловия
		if botNet == nil {
			return nil, fmt.Errorf("NewBotNetLogin(): IBotNet is nil")
		}
	}

	sf := &BotNetLogin{
		botNet: botNet,
		conn:   botNet.Коннект(),
		cookie: botNet.Куки(),
	}
	if err := sf.connect(); err != nil {
		return nil, fmt.Errorf("NewBotLogin() in connect to server, err=\n\t%w", err)
	}
	return sf, nil
}

// Вызывается один раз
func (sf *BotNetLogin) connect() (err error) {
	linkBegin, err := sf.getMainPage()
	if err != nil {
		return fmt.Errorf("BotNetLogin.connect(): при получении главной страницы, err=\n\t%w", err)
	}
	switch linkBegin != "" {
	case true: // Это вход на базу
		strBodyLogin, err := sf.getPageLogin(linkBegin)
		if err != nil {
			return fmt.Errorf("BotNetLogin.connect(): при получении страницы логина, err=\n\t%w", err)
		}
		if err = sf.makePostLogin(strBodyLogin); err != nil {
			return fmt.Errorf("BotNetLogin.connect(): при выполнении логина, err=\n\t%w", err)
		}
		return nil
	default: // Логин уже был
		req, err1 := http.NewRequest("GET", "https://wartank.ru/angar", nil)
		if err1 != nil {
			return fmt.Errorf("BotNetLogin.connect(): in get page angar, err=\n\t%w", err1)

		}
		resp, err2 := sf.conn.Do(req)
		if err2 != nil {
			return fmt.Errorf("BotNetLogin.connect(): in make request, err=\n\t%w", err2)
		}
		defer resp.Body.Close()
		_, err := io.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("BotNetLogin.connect(): in read body response, err=\n\t%w", err)
		}
	}
	return nil
}

// Прочитать главную страницу для получения кукисов
func (sf *BotNetLogin) getMainPage() (linkBegin string, err error) {
	// _mt.Println("\BotNetLogin.getMainPage()")
	resp, err := sf.conn.Get("https://wartank.ru/")
	if err != nil {
		return "", fmt.Errorf("BotNetLogin.getMainPage(): err=\n\t%w", err)
	}
	defer resp.Body.Close()
	// Получить куки из ответа
	cookies := resp.Cookies()
	if len(cookies) > 0 {
		if err = sf.cookie.Уст(cookies); err != nil {
			return "", fmt.Errorf("BotNetLogin.getMainPage(): при установки куки, err=\n\t%w", err)
		}
	}
	binData, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("BotNetLogin.getMainPage(): при чтении тела ответа, err=\n\t%w", err)
	}
	// Вырезать из тела страницы ссылку на вход
	lstStr := strings.Split(string(binData), "\n")
	var strOut string
	for _, strLink := range lstStr {
		if strings.Contains(strLink, `w:id="showSigninLink"`) {
			strOut = strLink
			break
		}
	}
	if strOut == "" { // Уже был логин
		return "", nil
	}
	{ // Получить ссылку на вход
		lstLink := strings.Split(strOut, `href="`)
		lstLink = strings.Split(lstLink[1], `"><span><span>`)
		linkBegin = "https://wartank.ru/" + lstLink[0]
	}
	return linkBegin, nil
}

// Получает страницу логина
func (sf *BotNetLogin) getPageLogin(linkBegin string) (strBodyLogin string, err error) {
	// _mt.Println("\BotNetLogin.getPageLogin()")
	resp, err := sf.conn.Get(linkBegin)
	if err != nil {
		return "", fmt.Errorf("NetLogin.getPageLogin(): in mske GET-request for send login page, err=\n\t%w", err)
	}
	defer resp.Body.Close()
	// sf.cookie = resp.Cookies()
	binData, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("NetLogin.getPageLogin(): in read body response, err=\n\t%w", err)
	}
	strBodyLogin = string(binData)
	// sf.app.AddLog(fmt.Sprintf("BotNetLogin.getPageLogin(): page_login=\n%v\n\n", strBodyLogin))
	return strBodyLogin, nil
}

// Выполняет логин через POST-запрос
func (sf *BotNetLogin) makePostLogin(strBody string) (err error) {
	// _mt.Println("\BotNetLogin.makePostLogin()")
	var strBodyMain string
	{ // Получить форму логина
		lstLogin := strings.Split(strBody, "\n")
		for _, strForm := range lstLogin {
			if strings.Contains(strForm, `<form w:id="loginForm" id=`) {
				strBodyMain = strForm
				break
			}
		}
	}
	var postLink string
	{ // Получить ссылку на POST-запрос
		lstLink := strings.Split(strBodyMain, ` action="`)
		strLink := lstLink[1]
		lstLink = strings.Split(strLink, `"><div style=`)
		postLink = "https://wartank.ru/" + lstLink[0]
	}
	{ // Конструируем ПОСТ-форму логина
		form := url.Values{}
		form.Add("id1_hf_0", "")
		form.Add("login", sf.botNet.Бот().Имя())
		form.Add("password", sf.botNet.Бот().Пароль())

		resp, err := sf.conn.PostForm(postLink, form)
		if err != nil {
			return fmt.Errorf("BotNetLogin.makePostLogin(): in get POST-login response, err=\n\t%w", err)
		}
		defer resp.Body.Close()
		if _, err = io.ReadAll(resp.Body); err != nil {
			return fmt.Errorf("BotNetLogin.makePostLogin(): in read body POST-login response, err=\n\t%w", err)
		}
		urlObj, _ := url.Parse("https://wartank.ru/")
		sf.conn.Jar.SetCookies(urlObj, sf.cookie.Получ())
	}
	return nil
}
