package convoy

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"

	"github.com/sirupsen/logrus"

	"wartank/pkg/components/section"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/convoy/convoynet"
	"wartank/server/serv_bots/warbot/tank/tankstat/static_param"
)

/*
	Объект конвоя в ангаре
*/

// Конвой -- объект конвоя в ангаре
type Конвой struct {
	*section.Section
	net   *convoynet.ConvoyNet
	бот   types.ИБот
	слава types.ИСтатПарам // Количество славы
}

// НовКонвой -- возвращает новый *Convoy
func НовКонвой(bot types.ИБот) (*Конвой, error) {
	section, err := section.NewSection(bot, "Конвой", `<title>Конвой</title>`)
	if err != nil {
		return nil, fmt.Errorf("НовКонвой(): in create ISection, err=\n\t%w", err)
	}
	слава, ош := static_param.НовСтатПарам("glory")
	if ош != nil {
		return nil, fmt.Errorf("НовКонвой(): при создании статы славы, err=\n\t%w", ош)
	}
	sf := &Конвой{
		Section: section,
		бот:     bot,
		слава:   слава,
	}
	sf.net, err = convoynet.NewConvoyNet(sf)
	if err != nil {
		return nil, fmt.Errorf("НовКонвой(): in create *SectionNet, err=\n\t%w", err)
	}
	return sf, nil
}

// Пуск -- запускает конвой в работу
func (sf *Конвой) Пуск() error {
	go sf.run()
	return nil
}

// UpdateLst -- принудительно обновляет состояние конвоя
func (sf *Конвой) UpdateLst() {
	if err := sf.net.UpdateLst(); err != nil {
		log.Printf("Convoy.UpdateLst(): err=\n\t%v\n", err)
	}
}

// Слава --возвращает счётчик славы конвоя
func (sf *Конвой) Слава() types.ИСтатПарам {
	return sf.слава
}

// обрабатывает конвой
func (сам *Конвой) run() {
	for {
		select {
		case <-сам.бот.Кнт().Done():
			return
		default:
			сам.атаковать()
			time.Sleep(time.Minute * 20)
		}
	}
}

func (сам *Конвой) атаковать() {
	сам.updateTime()
	сам.атакаНачать() // в этом месте только атаковать
	сам.проверитьМиссияКонвой()
	сам.проверитьМиссияМастерДозора()
	сам.проверитьМиссия6фрагов()
	сам.славаОбновить()
}

// Обновляет славу по требованию
func (sf *Конвой) славаОбновить() {
	// Найти строку с упоминанием оставшегося времени конвоя
	lstConvoy := sf.СписПолучить()
	var (
		strGlory string
		isFind   bool
	)
	for _, lastTime := range lstConvoy {
		if strings.Contains(lastTime, `alt="Слава" title="Слава"> `) {
			strGlory = lastTime
			isFind = true
			break
		}
	}
	if !isFind { // Не найдена строка со славой -- это атака
		return
	}
	// Ищем количество славы
	lstGlory := strings.Split(strGlory, `alt="Слава" title="Слава"> `)
	strGlory = lstGlory[1]
	iGlory, err := strconv.Atoi(strGlory)
	if err != nil {
		// log._rintf("ERRO ConvoyNet.updateGlory(): слава(%v) не число, err=\n\t%v\n", strGlory, err)
		return
	}
	sf.слава.Уст(iGlory)
}

// Обновляет оставшееся время конвоя
func (sf *Конвой) updateTime() {
	// Время подходит надо обновляться
	if err := sf.net.UpdateLst(); err != nil {
		logrus.WithError(err).Error("ConvoyNet.updateTime(): при выполнении GET-команды обновления")
		sf.SetCountDown(20)
		return
	}
	// Найти строку с упоминанием оставшегося времени конвоя
	lstConvoy := sf.СписПолучить()
	var (
		strLastTime string
		isFind      bool
		isMask      bool
	)
	for _, lastTime := range lstConvoy {
		if strings.Contains(lastTime, `До следующего конвоя: `) {
			strLastTime = lastTime
			isFind = true
			break
		}
		if strings.Contains(lastTime, `Полная маскировка через `) {
			strLastTime = lastTime
			isMask = true
			break
		}
		// <div class="bot"><a class="simple-but border red" w:id="startFight" href="convoy?7-1.ILinkListener-root-startFight"><span><span>В БОЙ!</span></span></a></div>
		if strings.Contains(lastTime, `ILinkListener-root-startFight`) {
			return
		}
		if strings.Contains(lastTime, `ILinkListener-root-findEnemy`) {
			return
		}
		// <div class="bot"><a class="simple-but border" w:id="startMasking" href="convoy?12-1.ILinkListener-root-startMasking"><span><span>В БОЙ!</span></span></a></div>
		if strings.Contains(lastTime, `ILinkListener-root-startMasking`) {
			return
		}
	}
	switch {
	case isFind: // Большая пауза между конвоями
		// Ждём окончания ожидания конвоя
		lstTime := strings.Split(strLastTime, `До следующего конвоя: `)
		strLastTime = lstTime[1]
		if err := sf.ParseCountDown(strLastTime); err != nil {
			// log._rintf("WARN Convoy.updateTime(): при установке времени ожидания конвоя(%v)\n\terr=%v\n", strLastTime, err)
			sf.SetCountDown(10)
		}
	case isMask: // Если маскировка между конвоями
		// Ждём окончания ожидания конвоя
		lstTime := strings.Split(strLastTime, `Полная маскировка через `)
		strLastTime = lstTime[1]
		if err := sf.ParseCountDown(strLastTime); err != nil {
			// log._rintf("ERRO Bank.getAllMode(): при установке времени банка для 1го режима(%v)\n\terr=%v\n", strLastTime, err)
			sf.SetCountDown(10)
		}
	}
}

// Проводит атаку на конвой
func (сам *Конвой) атакаНачать() {
	// Найти контрольную строку
	var (
		strOut    = ""
		lstConvoy = сам.СписПолучить()
		isFind    bool
	)

	for _, strLink := range lstConvoy {
		if strings.Contains(strLink, `>Начать разведку<`) {
			strOut = strLink
			lstLink := strings.Split(strOut, `<div class="bot"><a class="simple-but border" w:id="findEnemy" href="`)
			strOut = lstLink[1]
			lstLink = strings.Split(strOut, `"><span><span>Начать разведку</span></span></a></div>`)
			strOut = "https://wartank.ru/" + lstLink[0]
			isFind = true
			break
		}
		if strings.Contains(strLink, `<span>В БОЙ!</span>`) {
			strOut = strLink
			lstLink := strings.Split(strOut, `<div class="bot"><a class="simple-but border" w:id="startMasking" href="`)
			if len(lstLink) == 1 {
				lstLink = strings.Split(strOut, `<div class="bot"><a class="simple-but border red" w:id="startFight" href="`)
			}
			strOut = lstLink[1]
			lstLink = strings.Split(strOut, `"><span><span>В БОЙ!</span></span></a></div>`)
			strOut = "https://wartank.ru/" + lstLink[0]
			isFind = true
			break
		}
		if strings.Contains(strLink, `>ОБЫЧНЫЕ<`) {
			strOut = strLink
			lstLink := strings.Split(strOut, `<a href="`)
			strOut = lstLink[1]
			lstLink = strings.Split(strOut, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`)
			strOut = "https://wartank.ru/" + lstLink[0]
			isFind = true
			break
		}
	}
	if !isFind { // Время ожидания
		if err := сам.SetCountDown(1); err != nil {
			panic(fmt.Errorf("ConvoyNet.attackConvoy(): пр установке CountDown, err=\n\t%w", err))
		}
		return
	}
	strLink := strOut
	// Можно начать разведку
	lstConvoy, err := сам.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO ConvoyNet.attackConvoy(): при выполнении GET-команды 'В атаку!', err=\n\t%v\n", err)
		return
	}
	if err = сам.СтрОбновить(lstConvoy); err != nil {
		for _, strOut = range lstConvoy {
			if strings.Contains(strOut, `<title>Ошибка на сервере. Сообщение админу уже отправлено.</title>`) {
				// log._rintf("ERRO ConvoyNet.attackConvoy(): при обновлении lstConvoy, strOut=\n\t%v\n", strOut)
				return
			}
		}
		for _, strOut = range lstConvoy {
			if strings.Contains(strOut, `<title>База</title>`) {
				// log._rintf("ERRO ConvoyNet.attackConvoy(): при обновлении lstConvoy (найдено lstBase), strOut=\n\t%v\n", strOut)
				return
			}
		}
		// log._rintf("ERRO ConvoyNet.attackConvoy(): при обновлении lstConvoy, err=\n\t%v\n", err)
		return
	}
	for сам.атакаИскать() {
	}
	if err := сам.SetCountDown(1); err != nil {
		panic(fmt.Errorf("ConvoyNet.attackConvoy(): при установке CountDown, err=\n\t%w", err))
	}
}

// Выполняет атаку на конвой
func (sf *Конвой) атакаИскать() (isNext bool) {
	// Вырезать ссылку на атаку
	strOut := ""
	lstConvoy := sf.СписПолучить()
	// <a href="convoy?13-2.ILinkListener-root-fightView-attackRegular" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>
	for _, strAttack := range lstConvoy {
		if strings.Contains(strAttack, `>ОБЫЧНЫЕ<`) {
			strOut = strAttack
			break
		}
		// Полная маскировка через 39:53
		if strings.Contains(strAttack, `Полная маскировка через `) {
			return false
		}
	}
	if strOut == "" { // Нечего атаковать
		return false
	}
	// Атакуем конвой
	lstLink := strings.Split(strOut, `<a href="`)
	if len(lstLink) != 2 {
		return false
	}
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `" class="simple-but gray"><span><span>ОБЫЧНЫЕ</span></span></a>`)
	strLink = "https://wartank.ru/" + lstLink[0]
	{ // Выполнить атаку
		var err error
		lstConvoy, err = sf.net.Get(strLink)
		if err != nil {
			logrus.WithError(err).Error("ConvoyNet.attack(): in get page find attack")
			return false
		}
		if err = sf.СтрОбновить(lstConvoy); err != nil {
			logrus.WithError(err).Error("Convoy.attack(): при обновлении lstConvoy")
			return false
		}
	}
	return true
}

// Забирает награду в конвое "Активируй боевую силу"
func (sf *Конвой) проверитьМиссияКонвой() {
	var (
		strOut    string
		isFind    bool
		lstConvoy = sf.СписПолучить()
		ind       int
	)
	if len(lstConvoy) == 0 {
		if err := sf.net.UpdateLst(); err != nil {
			// log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
			return
		}
		lstConvoy = sf.СписПолучить()
	}
	for ind, strOut = range lstConvoy {
		if strings.Contains(strOut, `Активируй усиление &quot;Боевая сила&quot;<br/>`) {
			isFind = true
			ind += 23
			strOut = lstConvoy[ind]
			break
		}
	}
	if !isFind {
		return
	}
	// <a class="simple-but border" href="convoy?70-1.ILinkListener-missions-cc-0-c-awardLink"><span><span>Получить награду</span></span></a>
	if !strings.Contains(strOut, `ILinkListener-missions-cc-0-c-awardLink`) {
		return
	}
	lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Получить награду</span></span></a>`)
	// https://wartank.ru/convoy?80-1.ILinkListener-missions-cc-0-c-awardLink
	strLink = "https://wartank.ru/" + lstLink[0]
	lstConvoy, err := sf.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Convoy.checkWarForce(): при выполнени команды GET, err=\n\t%v\n", err)
		return
	}
	if err := sf.СтрОбновить(lstConvoy); err != nil {
		// log._rintf("ERRO Convoy.checkWarForce(): пр обновлении lstConvoy, err=\n\t%v\n", err)
		return
	}
	// log._rintf("INFO Convoy.checkWarForce(): награда получена\n")
}

// Забирает награду в конвое "Мастер дозора"
func (sf *Конвой) проверитьМиссияМастерДозора() {
	var (
		strOut    string
		isFind    bool
		lstConvoy = sf.СписПолучить()
		ind       int
	)
	if len(lstConvoy) == 0 {
		if err := sf.net.UpdateLst(); err != nil {
			// log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
			return
		}
		lstConvoy = sf.СписПолучить()
	}
	for ind, strOut = range lstConvoy {
		if strings.Contains(strOut, `Проведи разведку в конвое<br/>`) {
			isFind = true
			ind += 23
			strOut = lstConvoy[ind]
			break
		}
	}
	if !isFind {
		return
	}
	// <a class="simple-but border" href="convoy?61-1.ILinkListener-missions-cc-0-c-awardLink"><span><span>Получить награду</span></span></a>
	if !strings.Contains(strOut, `ILinkListener-missions-cc-0-c-awardLink`) {
		return
	}
	lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Получить награду</span></span></a>`)
	// https://wartank.ru/convoy?61-1.ILinkListener-missions-cc-0-c-awardLink
	strLink = "https://wartank.ru/" + lstLink[0]
	lstConvoy, err := sf.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Convoy.checkMaster(): при выполнени команды GET, err=\n\t%v\n", err)
		return
	}
	if err := sf.СтрОбновить(lstConvoy); err != nil {
		// log._rintf("ERRO Convoy.checkMaster(): пр обновлении lstConvoy, err=\n\t%v\n", err)
		return
	}
	// log._rintf("INFO Convoy.checkMaster(): награда получена\n")
}

// Забирает награду в конвое "Уничтожь 6 врагов в конвое"
func (sf *Конвой) проверитьМиссия6фрагов() {
	var (
		strOut    string
		isFind    bool
		lstConvoy = sf.СписПолучить()
		ind       int
	)
	if len(lstConvoy) == 0 {
		if err := sf.net.UpdateLst(); err != nil {
			// log._rintf("Convoy.check6frage(): при обновлении пустого lstConvoy, err=\n\t%v\n", err)
			return
		}
		lstConvoy = sf.СписПолучить()
	}
	for ind, strOut = range lstConvoy {
		if strings.Contains(strOut, `Уничтожь 6 врагов в конвое<br/>`) {
			isFind = true
			ind += 23
			strOut = lstConvoy[ind]
			break
		}
	}
	if !isFind {
		return
	}
	// <a class="simple-but border" href="convoy?61-1.ILinkListener-missions-cc-0-c-awardLink"><span><span>Получить награду</span></span></a>
	if !strings.Contains(strOut, `ILinkListener-missions-cc-0-c-awardLink`) {
		return
	}
	lstLink := strings.Split(strOut, `<a class="simple-but border" href="`)
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Получить награду</span></span></a>`)
	// https://wartank.ru/convoy?61-1.ILinkListener-missions-cc-0-c-awardLink
	strLink = "https://wartank.ru/" + lstLink[0]
	lstConvoy, err := sf.net.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Convoy.check6frage(): при выполнени команды GET, err=\n\t%v\n", err)
		return
	}
	if err := sf.СтрОбновить(lstConvoy); err != nil {
		// log._rintf("ERRO Convoy.check6frage(): пр обновлении lstConvoy, err=\n\t%v\n", err)
		return
	}
	// log._rintf("INFO Convoy.check6frage(): награда получена\n")
}
