// package fuel_attack -- объект боя на топливе
package fuel_attack

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"
	"wartank/pkg/arena"
	"wartank/pkg/components/arena_net"
	"wartank/pkg/cons"
	"wartank/pkg/types"
)

// ТопливоБой -- объект боя на топливе
type ТопливоБой struct {
	types.ИАрена
	ангар     types.ИАнгар
	аренаСеть *arena_net.АренаСеть
}

// НовТопливоБой -- возвращает новый *ТопливоБойNet
func НовТопливоБой(ангар types.ИАнгар) (*ТопливоБой, error) {
	аренаСеть := arena_net.НовАренаСеть(ангар, "https://wartank.ru/battle")
	сам := &ТопливоБой{
		ангар:     ангар,
		аренаСеть: аренаСеть,
	}
	аренаКонфиг := arena.АренаКонфиг{
		Бот_:         ангар.Бот(),
		АренаИмя_:    "ТопливоБой",
		СтрКонтроль_: `<title>Бой</title>`,
		ФнПуск_:      сам.пуск,
		СтрУрл_:      "https://wartank.ru/angar",
	}
	сам.ИАрена = arena.НовАрена(аренаКонфиг)
	_ = types.ИАрена(сам)
	return сам, nil
}

func (сам *ТопливоБой) пуск() {
	for {
		time.Sleep(time.Second * 30) // Минимальный интервал ожидания прибавки топлива
		// сам.топливоПолуч()
		топливо := сам.ангар.Топливо().Получ()
		if топливо < cons.ТопливоМин { // Минимальная ёмкость бака -- 315
			continue
		}
		log.Printf("Fuel.Run: val=%v\n", топливо)
		списСтрБой, err := сам.начатьБой()
		if err != nil {
			// log._rintf("ERRO ТопливоБой.findFuel(): in get page battle, err=\n\t%v\n", err)
			continue
		}
		списВыстрел1, err := сам.выбратьБойСлабый(списСтрБой)
		if err != nil {
			// log._rintf("ERRO ТопливоБой.findFuel(): in get page shooting, err=\n\t%v\n", err)
			continue
		}
		if err := сам.сделатьВыстрелы(списВыстрел1); err != nil {
			log.Printf("ERRO ТопливоБой.findFuel(): in make shooting, err=\n\t%v\n", err)
		}
	}
}

// Получает количество топлива

// Идёт в атаку, если топлива больше cons.ТопливоМин
func (сам *ТопливоБой) начатьБой() (списСтрБой []string, err error) {
	// Получить ссылку на атаку
	// _mt.Println("\t ТопливоБой.начатьБой()")
	списАнгар := сам.ангар.СписПолучить()
	var стрАнализ string
	for _, стрАтак := range списАнгар {
		if strings.Contains(стрАтак, `<span>В бой!</span>`) {
			стрАнализ = стрАтак
			break
		}
	}
	// Вырезать ссылку на атаку
	списАнгар = strings.Split(стрАнализ, `<a class="simple-but border mb1" href="`)
	if len(списАнгар) < 2 { // Не та страница
		return nil, fmt.Errorf("ТопливоБой.начатьБой(): список строк для атаки пустой")
	}
	бойСсылка := списАнгар[1]
	списАнгар = strings.Split(бойСсылка, `"><span><span>В бой!</span></span></a>`)
	бойСсылка = "https://wartank.ru/" + списАнгар[0]
	списСтрБой, err = сам.аренаСеть.Get(бойСсылка)
	if err != nil {
		return nil, fmt.Errorf("ТопливоБой.начатьБой(): in make GET-request to battle, err=\n\t%w", err)
	}
	return списСтрБой, nil
}

// Выбирает первого более слабого противника и делает первый выстрел
func (сам *ТопливоБой) выбратьБойСлабый(списСтрБой []string) (списСтрВыстрел1 []string, err error) {
	// _mt.Println("\tAngarNet.makeSelectBattle()")
	var стрАнализ string
	defer func() {
		if паника := recover(); паника != nil {
			msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot1\n"
			msg += "\tNetClient.makeSelectBattle().fnShoot1()\n"
			msg0 := fmt.Sprintf("%v\n", паника)
			msg1 := ""
			for _, _msg := range strings.Split(msg0, "\n") {
				if _msg == "" {
					continue
				}
				msg1 += "\t" + _msg + "\n"
			}
			msg += msg1
			// _mt.Println(msg)
			err = fmt.Errorf("%v", msg)
			msg1 = "" // Сброс накопленной ошибки
			for _, _msg := range списСтрБой {
				if _msg == "" {
					continue
				}
				msg1 += "\t" + _msg + "\n"
			}
			msg += msg1
			// Выкинуть ошибку в файл
			_ = os.MkdirAll("./errors", 0700)
			err = os.WriteFile("./errors/attack_shoot1.html", []byte(msg), 0600)
		}
	}()
	// Выдернуть строку с первой ссылкой на противника
	for _, стрБой_ := range списСтрБой {
		if strings.Contains(стрБой_, `opponents-opponents-0`) {
			стрАнализ = стрБой_
			break
		}
	}
	var ссылкаБой string
	switch стрАнализ == "" {
	case true: // Такая ситуация возможна, если уже были какие-то выстрелы
		return списСтрБой, nil
	default: // Успешный выстрел
		// Вырезать ссылку из строки
		списСтрБой = strings.Split(стрАнализ, `<td class="cntr"><a href="`)
		ссылкаБой = списСтрБой[1]
		списСтрБой = strings.Split(ссылкаБой, `"><img class="tank-img" alt="tank" src="/tankimg?`)
		ссылкаБой = "https://wartank.ru/" + списСтрБой[0]
	}
	списСтрВыстрел1, err = сам.аренаСеть.Get(ссылкаБой)
	if err != nil {
		return nil, fmt.Errorf("ТопливоБой.makeSelectBattle(): in GET-response select battle tank, err=\n\t%w", err)
	}
	return списСтрВыстрел1, nil
}

// Ведёт бой в 2 выстрела (здесь только 2 и 3 выстрел -- первый сделан при слабом противнике)
func (сам *ТопливоБой) сделатьВыстрелы(lstShoot2 []string) error {
	// _mt.Println("\tAngarNet.makeShooting()")
	var списВыстрел3 []string          // Тело страницы для третьего выстрела
	фнВыстрел2 := func() (err error) { // Второй выстрел
		// _mt.Println("\tAngarNet.makeShooting().fnShoot2()")
		defer func() {
			if _panic := recover(); _panic != nil {
				msg := time.Now().Local().Format("2006-01-02 15:04:05.000 ") + "fnShoot2\n"
				msg += "\tNetClient.makeShooting().fnShoot2()\n"
				msg0 := fmt.Sprintf("%v\n", _panic)
				msg1 := ""
				for _, _msg := range strings.Split(msg0, "\n") {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// _mt.Println(msg)
				err = fmt.Errorf("%v", msg)
				msg1 = "" // Сброс накопленной ошибки
				for _, _msg := range lstShoot2 {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// Выкинуть ошибку в файл
				_ = os.MkdirAll("./errors", 0700)
				err = os.WriteFile("./errors/attack_shoot2.html", []byte(msg), 0600)
			}
		}()
		// Получить ссылку на второй выстрел
		var strOut string
		for _, strShoot := range lstShoot2 {
			if strings.Contains(strShoot, `<span>Добить</span>`) {
				strOut = strShoot
				break
			}
		}
		var linkShoot2 string
		switch strOut == "" {
		case true: // Первый выстрел был неудачным
			for _, strShoot := range lstShoot2 {
				if strings.Contains(strShoot, `<span>Взять реванш</span>`) {
					strOut = strShoot
					break
				}
			}
			if strOut == "" { // Это ситуация для третьего выстрела
				списВыстрел3 = lstShoot2
				return nil
			}
			// Вырезать ссылку из строки
			lstShoot2 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot2 = lstShoot2[1]
			lstShoot2 = strings.Split(linkShoot2, `"><span><span>Взять реванш</span></span></a>`)
			linkShoot2 = "https://wartank.ru/" + lstShoot2[0]
		default: // Первый выстрел был удачным
			// Вырезать ссылку из строки
			lstShoot2 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot2 = lstShoot2[1]
			lstShoot2 = strings.Split(linkShoot2, `"><span><span>Добить</span></span></a>`)
			linkShoot2 = "https://wartank.ru/" + lstShoot2[0]
		}
		списВыстрел3, err = сам.аренаСеть.Get(linkShoot2)
		if err != nil {
			return fmt.Errorf("ТопливоБой.makeShooting(): in Get-response shoot2, err=\n\t%w", err)
		}
		fuel := сам.ангар.Топливо().Получ()
		fuel -= 30
		сам.ангар.Топливо().Уст(fuel)
		return nil
	}
	if err := фнВыстрел2(); err != nil {
		return err
	}
	фнВыстрел3 := func() (err error) { // Третий выстрел
		// _mt.Println("\tAngarNet.makeShooting().fnShoot3()")
		defer func() {
			if _panic := recover(); _panic != nil {
				msg := time.Now().Local().Format("2006-01-02 15:04:05.000 fnShoot3\n")
				msg += "\tNetClient.makeShooting().fnShoot3()\n"
				msg0 := fmt.Sprintf("%v\n", _panic)
				msg1 := ""
				for _, _msg := range strings.Split(msg0, "\n") {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// _mt.Println(msg)
				err = fmt.Errorf("%v", msg)
				msg1 = "" // Сброс накопленной ошибки
				for _, _msg := range списВыстрел3 {
					if _msg == "" {
						continue
					}
					msg1 += "\t" + _msg + "\n"
				}
				msg += msg1
				// Выкинуть ошибку в файл
				_ = os.MkdirAll("./errors", 0700)
				err = os.WriteFile("./errors/attack_shoot3.html", []byte(msg), 0600)
			}
		}()
		// Получить ссылку на третий выстрел
		var strOut string
		for _, strShoot3 := range списВыстрел3 {
			if strings.Contains(strShoot3, `<span>Уничтожить</span>`) {
				strOut = strShoot3
				break
			}
		}
		linkShoot3 := ""
		switch strOut == "" {
		case true: // Если не найдена ссылка -- значит было поражение в выстреле
			if strOut == "" {
				for _, strShoot3 := range списВыстрел3 {
					if strings.Contains(strShoot3, `<span>Взять реванш</span>`) {
						strOut = strShoot3
						break
					}
				}
			}
			// Вырезать ссылку из строки
			списВыстрел3 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot3 = списВыстрел3[1]
			списВыстрел3 = strings.Split(linkShoot3, `"><span><span>Взять реванш</span></span></a>`)
			linkShoot3 = "https://wartank.ru/" + списВыстрел3[0]
		default: // Успешный выстрел
			// Вырезать ссылку из строки
			списВыстрел3 = strings.Split(strOut, `<a class="simple-but border" href="`)
			linkShoot3 = списВыстрел3[1]
			списВыстрел3 = strings.Split(linkShoot3, `"><span><span>Уничтожить</span></span></a>`)
			linkShoot3 = "https://wartank.ru/" + списВыстрел3[0]
		}

		if _, err = сам.аренаСеть.Get(linkShoot3); err != nil {
			return fmt.Errorf("ТопливоБой.makeShooting(): in Get-response shoot3, err=\n\t%w", err)
		}
		fuel := сам.ангар.Топливо().Получ()
		fuel -= 30
		сам.ангар.Топливо().Уст(fuel)
		return nil
	}
	if err := фнВыстрел3(); err != nil {
		return err
	}
	сам.ангар.РесурсыОбновить()
	return nil
}
