package mine

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

	"wartank/pkg/components/section"
	"wartank/pkg/types"
	"wartank/server/serv_bots/warbot/angar/base/mine/minenet"
	"wartank/server/serv_bots/warbot/tank/tankstat/static_param"
)

/*
	Объект шахты на базе
*/

// Шахта -- объект шахты на базе
type Шахта struct {
	*section.Section
	сеть       *minenet.MineNet
	бот        types.ИБот
	база       types.ИБаза
	руда       types.ИСтатПарам
	железо     types.ИСтатПарам
	сталь      types.ИСтатПарам
	свинец     types.ИСтатПарам
	numProduct types.ИСтатПарам
}

// НовШахта -- возвращает новый *Mine
func НовШахта(база types.ИБаза) (*Шахта, error) {
	section, err := section.NewSection(база.Бот(), "Шахта", `<span class="green2">Руда</span><br/>`)
	if err != nil {
		return nil, fmt.Errorf("НовШахта(): in create *Section, err=\n\t%w", err)
	}
	руда, ош := static_param.НовСтатПарам("ruda")
	if ош != nil {
		return nil, fmt.Errorf("НовШахта(): при создании статистики руды, ош=\n\t%w", ош)
	}
	железо, ош := static_param.НовСтатПарам("ferrum")
	if ош != nil {
		return nil, fmt.Errorf("НовШахта(): при создании статистики железа, ош=\n\t%w", ош)
	}
	сталь, ош := static_param.НовСтатПарам("steel")
	if ош != nil {
		return nil, fmt.Errorf("НовШахта(): при создании статистики стали, ош=\n\t%w", ош)
	}
	свинец, ош := static_param.НовСтатПарам("plumbum")
	if ош != nil {
		return nil, fmt.Errorf("НовШахта(): при создании статистики свинца, ош=\n\t%w", ош)
	}
	добычаЧисло, ош := static_param.НовСтатПарам("plumbum")
	if ош != nil {
		return nil, fmt.Errorf("НовШахта(): при создании статистики числа добычи, ош=\n\t%w", ош)
	}
	sf := &Шахта{
		Section:    section,
		бот:        база.Бот(),
		база:       база,
		руда:       руда,
		железо:     железо,
		сталь:      сталь,
		свинец:     свинец,
		numProduct: добычаЧисло,
	}
	sf.сеть, err = minenet.NewMineNet(sf)
	if err != nil {
		return nil, fmt.Errorf("NewMine(): in create NetMine, err=\n\t%w", err)
	}
	return sf, nil
}

func (sf *Шахта) Пуск() error {
	go sf.пуск()
	return nil
}

// пуск -- запускает обработку шахты
func (сам *Шахта) пуск() {
	сам.SetCountDown(1)
	for {
		select {
		case <-сам.бот.Кнт().Done():
			сам.ВремяОпрос().Стоп()
			return
		case <-сам.ВремяОпрос().КаналСиг():
		default:
			log.Printf("Шахта.пуск()\n")
			руда := сам.Руда().Получ()
			if руда == 0 {
				time.Sleep(time.Second * 5)
				сам.бот.Ангар().РесурсыОбновить()
			}
			сам.Сделать()
			time.Sleep(time.Minute * 5)
		}
	}
}

// Сделать -- вызывается с базы, если она обнаружила, что пора сделать продукцию
func (сам *Шахта) Сделать() {
	работа := сам.РежимТекущ().Режим()
	log.Printf("Шахта.Сделать(): work=%v\n", работа)
	if работа == "upgrade" {
		return
	}
	if err := сам.сеть.UpdateLst(); err != nil {
		log.Printf("ERRO Шахта.Сделать(): при обновлении lstMine, err=\n\t%v\n", err)
		return
	}
	if err := сам.выбратьМеталл(); err != nil {
		log.Printf("ERRO Шахта.Сделать(): при выборе продукции, err=\n\t%v\n", err)
		return
	}
	работа = сам.РежимТекущ().Режим()
	switch работа {
	case "руда":
		сам.рудаСделать()
	case "железо":
		сам.железоСделать()
	case "сталь":
		сам.стальСделать()
	case "свинец":
		сам.свинецСделать()
	default:
		log.Printf("ERRO Шахта.Сделать(): неизвестный режим производства, режим=%q\n", работа)
	}
}

// Свинец -- возвращает объект свинца
func (sf *Шахта) Свинец() types.ИСтатПарам {
	return sf.свинец
}

// Сталь -- возвращает объект стали
func (сам *Шахта) Сталь() types.ИСтатПарам {
	return сам.сталь
}

// Железо -- возвращает объект железа
func (сам *Шахта) Железо() types.ИСтатПарам {
	return сам.железо
}

// Руда -- возвращает объект руды
func (сам *Шахта) Руда() types.ИСтатПарам {
	return сам.руда
}

// КолвоРаботаСейчас -- возвращает количество прозводимого продукта
func (сам *Шахта) КолвоРаботаСейчас() types.ИСтатПарам {
	return сам.numProduct
}

// Выбирает продукцию по возможности произвести и её количеству
func (сам *Шахта) выбратьМеталл() error {
	var (
		mapProduct = make(map[string]bool) // Словарь известной продукции
		lstMine    = сам.СписПолучить()
	)

	фнВыбратьПродукт := func() { // вычисляет список допустимой продукции
		mapProduct["ruda"] = true // Руда есть всегда
		mapProduct["ferrum"] = false
		mapProduct["steel"] = false
		mapProduct["plumbum"] = false
		for _, strProd := range lstMine { // Проверить руду
			if strings.Contains(strProd, `<span class="green2">Руда</span><br/>`) {
				mapProduct["ruda"] = true
				break
			}
		}
		for _, strProd := range lstMine { // Проверить руду
			if strings.Contains(strProd, `<span class="green2">Железо</span><br/>`) {
				mapProduct["ferrum"] = true
				break
			}
		}
		for _, strProd := range lstMine { // Проверить сталь
			if strings.Contains(strProd, `<span class="green2">Сталь</span><br/>`) {
				mapProduct["steel"] = true
				break
			}
		}
		for _, strProd := range lstMine { // Проверить свинец
			if strings.Contains(strProd, `<span class="green2">Свинец</span><br/>`) {
				mapProduct["plumbum"] = true
				break
			}
		}
	}
	фнВыбратьПродукт()
	сам.РежимТекущ().РежимУст("руда")
	руда := сам.Руда().Получ()
	железо := сам.Железо().Получ()
	if mapProduct["ferrum"] {
		if руда > железо*2 {
			сам.РежимТекущ().РежимУст("железо")
		}
	}

	сталь := сам.Сталь().Получ()
	if mapProduct["steel"] {
		if железо > сталь*2 {
			сам.РежимТекущ().РежимУст("сталь")
		}
	}

	свинец := сам.Свинец().Получ()
	if mapProduct["plumbum"] {
		if сталь > свинец*2 {
			сам.РежимТекущ().РежимУст("свинец")
		}
	}

	return nil
}

// Создаёт руду
func (сам *Шахта) рудаСделать() {
	var (
		lstMine = сам.СписПолучить()
		ind     int
		strOut  string
		strTime string
		strLink string
		strNum  string
		isFind  bool
	)
	for ind, strOut = range lstMine {
		if strings.Contains(strOut, `<span class="green2">Руда</span><br/>`) {
			strNum = lstMine[ind+1]
			strTime = lstMine[ind+3]
			strLink = lstMine[ind+10]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strLink, `>Начать производство<`) {
		return
	}
	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
	strLink = lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "https://wartank.ru/production/" + lstLink[0]
	lstMine, err := сам.сеть.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Шахта.сделатьРуду(): при GET-команде 'начать производство руды', err=\n\t%v\n", err)
		return
	}
	isFind = false
	for _, strOut = range lstMine {
		if strings.Contains(strOut, `<title>База</title>`) {
			// log._rintf("WARN Шахта.сделатьРуду(): при обновлении lstMine обнаружено lstBase\n")
			return
		}
	}
	if err = сам.СтрОбновить(lstMine); err != nil {
		// log._rintf("ERRO Шахта.сделатьРуду(): при обновлении lstMine, err=\n\t%v\n", err)
		return
	}
	if err := сам.ParseCountDown(strTime); err != nil {
		log.Printf("ERRO Шахта.сделатьРуду(): при установке времени ожидания добычи руды(%v)\n\terr=%v\n", strTime, err)
	}
	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
	strNum = lstNum[1]
	lstNum = strings.Split(strNum, `</span><br/>`)
	strNum = lstNum[0]
	iNum, err := strconv.Atoi(strNum)
	if err != nil {
		// log._rintf("ERRO Шахта.сделатьРуду(): кол-во(%v) не число, err=\n\t%v\n", strNum, err)
		return
	}
	сам.КолвоРаботаСейчас().Уст(iNum)
}

// Создаёт железо
func (сам *Шахта) железоСделать() {
	var (
		lstMine = сам.СписПолучить()
		ind     int
		strOut  string
		strTime string
		strLink string
		strNum  string
		isFind  bool
	)
	for ind, strOut = range lstMine {
		if strings.Contains(strOut, `<span class="green2">Железо</span><br/>`) {
			strNum = lstMine[ind+1]
			strTime = lstMine[ind+3]
			strLink = lstMine[ind+10]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strLink, `>Начать производство<`) {
		return
	}
	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
	strLink = lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "https://wartank.ru/production/" + lstLink[0]
	lstMine, err := сам.сеть.Get(strLink)
	if err != nil {
		// log._rintf("ERRO MineNet.makeFerrum(): при GET-команде 'начать производство железа', err=\n\t%v\n", err)
		return
	}
	for _, strOut := range lstMine { // Проверка на базу
		if strings.Contains(strOut, `<title>База</title>`) {
			// log._rintf("ERRO MineNet.makeFerrum(): при обновлении lstMine найден lstBase")
			return
		}
	}
	if err = сам.СтрОбновить(lstMine); err != nil {
		// log._rintf("ERRO MineNet.makeFerrum(): при обновлении lstMine, err=\n\t%v\n", err)
		return
	}
	if err := сам.ParseCountDown(strTime); err != nil {
		log.Printf("ERRO Mine.makeFerrum(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err)
	}
	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
	strNum = lstNum[1]
	lstNum = strings.Split(strNum, `</span><br/>`)
	strNum = lstNum[0]
	iNum, err := strconv.Atoi(strNum)
	if err != nil {
		// log._rintf("ERRO MineNet.makeFerrum(): кол-во(%v) не число, err=\n\t%v\n", strNum, err)
		return
	}
	сам.КолвоРаботаСейчас().Уст(iNum)
}

// Создаёт сталь
func (сам *Шахта) стальСделать() {
	var (
		lstMine = сам.СписПолучить()
		ind     int
		strOut  string
		strTime string
		strLink string
		strNum  string
		isFind  bool
	)
	for ind, strOut = range lstMine {
		if strings.Contains(strOut, `<span class="green2">Сталь</span><br/>`) {
			strNum = lstMine[ind+1]
			strTime = lstMine[ind+3]
			strLink = lstMine[ind+10]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strLink, `>Начать производство<`) {
		return
	}
	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
	strLink = lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "https://wartank.ru/production/" + lstLink[0]
	lstMine, err := сам.сеть.Get(strLink)
	if err != nil {
		// log._rintf("ERRO MineNet.makeSteel(): при GET-команде 'начать производство стали', err=\n\t%v\n", err)
		return
	}
	for _, strOut := range lstMine { // Проверка на базу
		if strings.Contains(strOut, `<title>База</title>`) {
			// log._rintf("ERRO MineNet.makeSteel(): при обновлении lstMine найден lstBase")
			return
		}
	}
	if err = сам.СтрОбновить(lstMine); err != nil {
		// log._rintf("ERRO MineNet.makeSteel(): при обновлении lstMine, err=\n\t%v\n", err)
		return
	}
	if err := сам.ParseCountDown(strTime); err != nil {
		log.Printf("ERRO Mine.makeSteel(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err)
	}
	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
	strNum = lstNum[1]
	lstNum = strings.Split(strNum, `</span><br/>`)
	strNum = lstNum[0]
	iNum, err := strconv.Atoi(strNum)
	if err != nil {
		// log._rintf("ERRO MineNet.makeSteel(): кол-во(%v) не число, err=\n\t%v\n", strNum, err)
		return
	}
	сам.КолвоРаботаСейчас().Уст(iNum)
}

// Создаёт свинец
func (сам *Шахта) свинецСделать() {
	var (
		lstMine = сам.СписПолучить()
		ind     int
		strOut  string
		strTime string
		strLink string
		strNum  string
		isFind  bool
	)
	for ind, strOut = range lstMine {
		if strings.Contains(strOut, `<span class="green2">Свинец</span><br/>`) {
			strNum = lstMine[ind+1]
			strTime = lstMine[ind+3]
			strLink = lstMine[ind+10]
			isFind = true
			break
		}
	}
	if !isFind {
		return
	}
	if !strings.Contains(strLink, `>Начать производство<`) {
		return
	}
	lstLink := strings.Split(strLink, `<a class="simple-but border" href="`)
	strLink = lstLink[1]
	lstLink = strings.Split(strLink, `"><span><span>Начать производство</span></span></a>`)
	strLink = "https://wartank.ru/production/" + lstLink[0]
	lstMine, err := сам.сеть.Get(strLink)
	if err != nil {
		// log._rintf("ERRO Шахта.сделатьСвинец(): при GET-команде 'начать производство стали', err=\n\t%v\n", err)
		return
	}
	for _, strOut := range lstMine { // Проверка на базу
		if strings.Contains(strOut, `<title>База</title>`) {
			// log._rintf("ERRO Шахта.сделатьСвинец(): при обновлении lstMine найден lstBase")
			return
		}
	}
	if err = сам.СтрОбновить(lstMine); err != nil {
		// log._rintf("ERRO Шахта.сделатьСвинец(): при обновлении lstMine, err=\n\t%v\n", err)
		return
	}
	if err := сам.ParseCountDown(strTime); err != nil {
		log.Printf("ERRO Шахта.сделатьСвинец(): при установке времени производства железа(%v)\n\terr=%v\n", strTime, err)
	}
	lstNum := strings.Split(strNum, `Кол-во: <span class="green2">`)
	strNum = lstNum[1]
	lstNum = strings.Split(strNum, `</span><br/>`)
	strNum = lstNum[0]
	iNum, err := strconv.Atoi(strNum)
	if err != nil {
		// log._rintf("ERRO Шахта.сделатьСвинец(): кол-во(%v) не число, err=\n\t%v\n", strNum, err)
		return
	}
	сам.КолвоРаботаСейчас().Уст(iNum)
}
