// package market -- объект рынка
package market

import (
	"log"
	"strconv"
	"strings"
	"time"
	"wartank/pkg/alias"
	"wartank/pkg/arena"
	"wartank/pkg/components/arena_net"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/stat_tank/static_param"
)

// Рынок -- объект рынка
type Рынок struct {
	types.ИАрена
	бот     types.ИБот
	сеть    types.ИАренаСеть
	уровень types.ИСтатПарам
}

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

// Пуск -- запускает всю работу рынка в отдельном потоке
func (сам *Рынок) Пуск() error {
	go сам.пуск()
	return nil
}

// выполняет опрос рынка базы, должен работать как горутина
func (сам *Рынок) пуск() {
	time.Sleep(time.Second * 7)
	фнРабота := func() {
		defer time.Sleep(time.Minute * 30)
		for !сам.уровеньОбновить() {
		}
		сам.ускорениеПровер()
		сам.проверОжидание()
		for сам.купитьЗолото() {
		}
	}
	for {
		select {
		case <-сам.бот.Контекст().Done():
			return
		default:
			фнРабота()
		}
	}
}

// Проверяет ускорение строительства
func (сам *Рынок) ускорениеПровер() {
	списСтр := сам.сеть.ВебВоркер().Получ("http://wartank.ru/buildings")
	// <span class="green2">Склад топлива -
	var (
		еслиНайти = false
		стр       string
	)
	for _, стр = range списСтр {
		if strings.Contains(стр, `<span class="green2">Склад топлива - `) {
			еслиНайти = true
			break
		}
	}
	if !еслиНайти {
		return
	}
}

// Обновляет текущий уровень рынка (может быть не построен)
func (сам *Рынок) уровеньОбновить() bool {
	списСтр := сам.сеть.ВебВоркер().Получ("http://wartank.ru/buildings")
	// <span class="green2">Рынок -
	var (
		еслиНайти = false
		стр       = ""
	)
	for _, стр = range списСтр {
		if strings.Contains(стр, `<span class="green2">Рынок -`) {
			еслиНайти = true
			break
		}
	}
	if !еслиНайти {
		return false
	}
	// <span class="green2">Рынок - 0</span><br/>
	_стр := strings.TrimPrefix(стр, `<span class="green2">Рынок - `)
	_стр = strings.TrimSuffix(_стр, `</span><br/>`)
	иУровень, ош := strconv.Atoi(_стр)
	if ош != nil {
		log.Printf("Рынок.уровеньОбновить(): строка уровня сбойная, стр=%q, ош=\n\t%v\n", стр, ош)
		return false
	}
	сам.уровень.Уст(иУровень)
	switch иУровень {
	case 0: // рынок надо построить
		for !сам.построить() {
		}
	default: // Может можно проапгрейдить
		счёт := 5
		for !сам.проапгрейдить() {
			счёт--
			if счёт >= 0 {
				break
			}
		}
	}

	return true
}

// Строит шахту при нулевом уровне
func (сам *Рынок) построить() bool {
	time.Sleep(time.Millisecond * 1000)
	// <td style="width:50%;padding-left:1px;"><a class="simple-but border mb5" href="building-upgrade/Market"><span><span>Построить</span></span></a></td>
	var (
		еслиНайти = false
		списСтр   []string
		стр       = ""
	)
	фнКупить := func() bool {
		defer time.Sleep(time.Millisecond * 1000)
		списСтр = сам.сеть.ВебВоркер().Получ("https://wartank.ru/building-upgrade/Market")
		for _, стр = range списСтр {
			// <a class="simple-but border mb5" href="Market?19-1.ILinkListener-upgradeLink-link">
			if strings.Contains(стр, `ILinkListener-upgradeLink-link`) {
				еслиНайти = true
				break
			}
		}
		if !еслиНайти {
			return true
		}
		// Пробуем построить шахту
		_стр := strings.TrimPrefix(стр, "<a class=\"simple-but border mb5\" href=\"")
		_стр = strings.TrimSuffix(_стр, "\">")
		// https://wartank.ru/building-upgrade/Market?18-1.ILinkListener-upgradeLink-link
		// <a class="simple-but border mb5" href="Market?19-1.ILinkListener-upgradeLink-link">
		ссылка := "https://wartank.ru/building-upgrade/" + _стр
		списСтр = сам.сеть.ВебВоркер().Получ(ссылка)
		// Проверить, что постройка состоялась
		for _, стр := range списСтр {
			if strings.Contains(стр, "ILinkListener-upgradeLink-link") {
				log.Printf("Рынок.построить().фнКупить(): покупка склада топлива не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
				return false // Покупка не оплачена
			}
		}
		log.Printf("+++++Рынок.построить().фнКупить(): покупка склада топлива прошла\n")
		return true
	}

	фнПодтверждение := func() bool {
		for _, стр = range списСтр {
			// <a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="../wicket/page?21-1.ILinkListener-confirmLink"><span><span>да, подтверждаю</span></span></a>
			if strings.Contains(стр, `ILinkListener-confirmLink`) {
				еслиНайти = true
				break
			}
		}
		if !еслиНайти {
			return true
		}
		// Пробуем построить шахту
		_стр := strings.TrimPrefix(стр, `<a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="..`)
		_стр = strings.TrimSuffix(_стр, `"><span><span>да, подтверждаю</span></span></a>`)
		// https://wartank.ru/wicket/page?20-1.ILinkListener-confirmLink
		ссылка := "https://wartank.ru" + _стр
		списСтр = сам.сеть.ВебВоркер().Получ(ссылка)
		// Проверить, что постройка состоялась
		for _, стр := range списСтр {
			if strings.Contains(стр, "<title>Вы сделали слишком большую паузу</title>") {
				log.Printf("Рынок.построить().фнПодтверждение(): подтверждение покупка склада топлива не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
				return false // Покупка не оплачена
			}
		}
		log.Printf("+++++Рынок.построить().фнПодтверждение(): подтверждение покупка склада топлива прошла\n")
		return true
	}

	фнКомплекс := func() {
		for {
			if фнКупить() {
				if фнПодтверждение() {
					break
				}
			}
		}
	}
	фнКомплекс()
	return true
}

// Пытается проапгрейдить топливный склад
func (сам *Рынок) проапгрейдить() bool {
	time.Sleep(time.Millisecond * 1000)
	var (
		еслиНайти = false
		списСтр   []string
		стр       = ""
	)
	фнКупить := func() bool {
		defer time.Sleep(time.Millisecond * 1000)
		списСтр = сам.сеть.ВебВоркер().Получ("https://wartank.ru/building-upgrade/Market")
		for _, стр = range списСтр {
			// <a class="simple-but border mb5" href="Market?5-1.ILinkListener-upgradeLink-link">
			if strings.Contains(стр, `ILinkListener-upgradeLink-link`) {
				еслиНайти = true
				break
			}
		}
		if !еслиНайти {
			return true
		}
		// Пробуем улучшить шахту
		_стр := strings.TrimPrefix(стр, "<a class=\"simple-but border mb5\" href=\"")
		_стр = strings.TrimSuffix(_стр, "\">")
		// https://wartank.ru/building-upgrade/Market?4-1.ILinkListener-upgradeLink-link
		// <a class="simple-but border mb5" href="Market?50-1.ILinkListener-upgradeLink-link">
		ссылка := "https://wartank.ru/building-upgrade/" + _стр
		списСтр = сам.сеть.ВебВоркер().Получ(ссылка)
		// Проверить, что постройка состоялась
		for _, стр := range списСтр {
			if strings.Contains(стр, "ILinkListener-upgradeLink-link") {
				log.Printf("Рынок.проапгрейдить().фнКупить(): покупка рынка не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
				return false // Покупка не оплачена
			}
		}
		log.Printf("+++++Рынок.проапгрейдить().фнКупить(): покупка рынка прошла\n")
		return true
	}

	фнПодтверждение := func() bool {
		for _, стр = range списСтр {
			// <a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="../wicket/page?7-1.ILinkListener-confirmLink"><span><span>да, подтверждаю</span></span></a>
			if strings.Contains(стр, `ILinkListener-confirmLink`) {
				еслиНайти = true
				break
			}
		}
		if !еслиНайти {
			return true
		}
		// Пробуем построить шахту
		_стр := strings.TrimPrefix(стр, `<a class="simple-but border w50 mXa mb10" w:id="confirmLink" href="..`)
		_стр = strings.TrimSuffix(_стр, `"><span><span>да, подтверждаю</span></span></a>`)
		// https://wartank.ru/wicket/page?6-1.ILinkListener-confirmLink
		ссылка := "https://wartank.ru" + _стр
		списСтр = сам.сеть.ВебВоркер().Получ(ссылка)
		// Проверить, что постройка состоялась
		for _, стр := range списСтр {
			if strings.Contains(стр, "<title>Вы сделали слишком большую паузу</title>") {
				log.Printf("Рынок.проапгрейдить().фнПодтверждение(): подтверждение покупка рынка не прошла\n\tlink=%v\n\tстр=\n\t%v\n", ссылка, стр)
				return false // Покупка не оплачена
			}
		}
		log.Printf("+++++Рынок.проапгрейдить().фнПодтверждение(): подтверждение покупка склада топлива прошла\n")
		return true
	}

	фнКомплекс := func() {
		count := 5
		for count > 0 {
			if фнКупить() {
				if фнПодтверждение() {
					break
				}
			}
			count--
		}
	}
	фнКомплекс()
	return true
}

// Проверяет  время ожидания рынка
func (сам *Рынок) проверОжидание() {
	var (
		strOut      string
		еслиНайдено bool
	)
	// countDown := сам.CountDown().Get()
	фнЕслиСеребро := func() bool { // Найти счётчик цены серебра
		сам.сеть.Обновить()
		еслиНайдено := false
		lstMarket := сам.СписПолучить()
		for _, strOut = range lstMarket {
			if strings.Contains(strOut, `alt="Серебро" title="Серебро"> `) {
				еслиНайдено = true
				break
			}
		}
		if еслиНайдено {
			lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
			strSilver := lstSilver[1]
			switch strSilver {
			case "10", "50", "100", "500":
				return true
			default:
				серебро := сам.бот.Ангар().СереброВсего()
				if серебро.Получ() > 1_000_000 {
					return true
				}
				return false
			}
		}
		return false
	}

	fnGetCountDown := func() { // Искать счётчик времени
		lstMarket := сам.СписПолучить()
		// Найти счётчик времени
		for _, strOut = range lstMarket {
			if strings.Contains(strOut, `Минимальная цена через `) {
				еслиНайдено = true
				break
			}
		}
		if !еслиНайдено {
			return // Минимальная цена
		}
		lstTime := strings.Split(strOut, `Минимальная цена через `)
		strTime := lstTime[1]
		if err := сам.ОбратВремяУст(alias.Время(strTime)); err != nil {
			// log._rintf("ERRO Market.checkTime(): при установке времени ожидания рынка(%v)\n\terr=%v\n", strTime, err)
			return // Возможно минимальная цена
		}
	}
	if фнЕслиСеребро() {
		return
	}
	fnGetCountDown()
}

// Проверяет рынок на режим покупки
func (сам *Рынок) купитьЗолото() bool {
	var (
		ind         int
		еслиНайдено bool
		strOut      string
		lstMarket   = сам.СписПолучить()
		strSilver   string
	)
	for ind, strOut = range lstMarket {
		if strings.Contains(strOut, `alt="Серебро" title="Серебро"> `) {
			еслиНайдено = true
			break
		}
	}
	if !еслиНайдено { // Не найдена продажа золота за серебро
		return false
	}
	lstSilver := strings.Split(strOut, `<img class="ico vm" src="/images/icons/silver.png?2" alt="Серебро" title="Серебро"> `)
	strSilver = lstSilver[1]
	серебро := сам.бот.Ангар().СереброВсего().Получ()
	еслиКупить := false
	switch strSilver {
	case "10", "50", "100", "500": // Допустимые суммы трат
		еслиКупить = true
	case "1000": // Если стоит тысяча серебра
		if серебро > 500_000 { // Если серебра больше полумиллиона -- покупаем
			еслиКупить = true
		}
	case "5000", "10000": // Если большая сумма -- можно купить и больше
		if серебро > 1_000_000 {
			еслиКупить = true
		}
	}
	if !еслиКупить {
		return false
	}
	ind -= 15
	strOut = lstMarket[ind]
	lstLink := strings.Split(strOut, `<a class="simple-but border mb5" href="`)
	if len(lstLink) < 2 {
		return false
	}
	strLink := lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Получить `)
	strLink = "https://wartank.ru/" + lstLink[0]
	lstMarket, err := сам.сеть.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Market.buyGold(): при выполнении GET-команды на покупку золота, err=\n\t%v\n", err)
		return true
	}
	for _, strOut = range lstMarket {
		if strings.Contains(strOut, `Ошибка на сервере. Сообщение админу уже отправлено.`) {
			// log._rintf("ERRO Market.buyGold(): при получении lstMarket, strHTML=%v, err=\nt%v\n", strOut, err)
			return false
		}
	}
	if err = сам.СтрОбновить(lstMarket); err != nil {
		// log._rintf("Market.buyGold(): при обновлении lstMarket, err=\n\t%v\n", err)
		return true
	}
	return true
}
