package gomodules

import (
	"fmt"
	"rubric/utils"
)

var BasicsModule = Module{
	Key:         "basics",
	Aliases:     []string{"b", "base", "install"},
	Title:       "Установка и основные команды",
	Description: "Установка Go, go build, go test, go doc и базовые инструменты",
	Run:         showBasics,
}

func showBasics() {
	utils.Header("Go — Установка и основные команды")

	// ─── Установка ───────────────────────────────────────────────
	utils.Section("Установка Go")

	utils.Println("Официальный сайт: https://go.dev/dl/")
	fmt.Println()
	utils.Info("Linux / macOS", "скачать архив и распаковать в /usr/local/go")
	utils.Code(`# Linux (пример для версии 1.22)
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz

# Добавить в ~/.bashrc или ~/.zshrc:
export PATH=$PATH:/usr/local/go/bin`)

	utils.Info("macOS (Homebrew)", "brew install go")
	utils.Info("Windows", "скачать .msi установщик с go.dev/dl")
	utils.Code(`# Проверить установку:
go version
# go version go1.22.0 linux/amd64`)

	utils.Note("Переменная GOPATH по умолчанию — ~/go. Код проектов хранится в ~/go/src/")

	// ─── Структура проекта ───────────────────────────────────────
	utils.Section("Структура проекта и модули")

	utils.Code(`# Создать новый модуль
go mod init github.com/user/myproject

# Структура типичного проекта:
myproject/
├── go.mod          # описание модуля и зависимостей
├── go.sum          # контрольные суммы зависимостей
├── main.go         # точка входа
├── internal/       # внутренние пакеты (недоступны снаружи)
└── pkg/            # переиспользуемые пакеты`)

	// ─── go build ────────────────────────────────────────────────
	utils.Section("Команды: сборка")

	utils.Command("go build", "скомпилировать текущий пакет")
	utils.Command("go build ./...", "скомпилировать все пакеты проекта")
	utils.Command("go build -o myapp", "указать имя выходного файла")
	utils.Command("go build -v", "показать компилируемые пакеты")
	utils.Command("go build -race", "включить детектор гонок данных")
	fmt.Println()
	utils.Code(`# Кросс-компиляция (собрать под Windows на Linux):
GOOS=windows GOARCH=amd64 go build -o app.exe

# Основные пары GOOS/GOARCH:
# linux/amd64  linux/arm64
# windows/amd64
# darwin/amd64  darwin/arm64  (macOS Intel / Apple Silicon)`)

	// ─── go run ──────────────────────────────────────────────────
	utils.Section("Команды: запуск")

	utils.Command("go run main.go", "скомпилировать и сразу запустить файл")
	utils.Command("go run .", "запустить пакет в текущей директории")
	utils.Command("go run ./cmd/app", "запустить конкретный пакет")

	// ─── go test ─────────────────────────────────────────────────
	utils.Section("Команды: тестирование")

	utils.Command("go test ./...", "запустить все тесты проекта")
	utils.Command("go test -v", "подробный вывод (имена тестов)")
	utils.Command("go test -run TestName", "запустить конкретный тест")
	utils.Command("go test -run TestName/SubTest", "запустить под-тест")
	utils.Command("go test -count=3", "запустить каждый тест 3 раза")
	utils.Command("go test -timeout 30s", "таймаут на все тесты")
	utils.Command("go test -race", "тесты с детектором гонок")
	utils.Command("go test -cover", "показать покрытие кода")
	utils.Command("go test -coverprofile=c.out", "сохранить отчёт о покрытии")
	utils.Command("go tool cover -html=c.out", "открыть покрытие в браузере")
	utils.Command("go test -bench=.", "запустить бенчмарки")
	utils.Command("go test -bench=. -benchmem", "бенчмарки + аллокации памяти")
	fmt.Println()
	utils.Code(`// Пример тестового файла (math_test.go):
package mypackage

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf("Add(2,3) = %d, хотели 5", result)
    }
}

// Под-тесты (subtests):
func TestOperations(t *testing.T) {
    t.Run("сложение", func(t *testing.T) { ... })
    t.Run("вычитание", func(t *testing.T) { ... })
}

// Бенчмарк:
func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(2, 3)
    }
}`)

	// ─── go fmt / vet / lint ─────────────────────────────────────
	utils.Section("Команды: форматирование и анализ")

	utils.Command("go fmt ./...", "автоформатирование всех файлов")
	utils.Command("go vet ./...", "статический анализ на типичные ошибки")
	utils.Command("go vet -shadow ./...", "поиск затенения переменных")
	utils.Command("gofmt -d main.go", "показать diff без записи")
	utils.Command("gofmt -w main.go", "записать форматирование в файл")
	fmt.Println()
	utils.Note("golangci-lint — популярный агрегатор линтеров: golangci-lint.run")
	utils.Code(`# Установка golangci-lint:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint run ./...`)

	// ─── go doc ──────────────────────────────────────────────────
	utils.Section("Документация: go doc")

	utils.Command("go doc fmt", "документация пакета fmt")
	utils.Command("go doc fmt.Println", "документация конкретной функции")
	utils.Command("go doc -all fmt", "вся документация пакета")
	utils.Command("go doc -src fmt.Println", "исходный код функции")
	utils.Command("go doc builtin", "встроенные функции и типы")
	fmt.Println()
	utils.Code(`// Комментарий к функции становится документацией:
// Add складывает два целых числа и возвращает результат.
// Оба аргумента должны быть неотрицательными.
func Add(a, b int) int {
    return a + b
}

// Запустить веб-сервер документации:
// godoc -http=:6060`)

	// ─── go get / mod ────────────────────────────────────────────
	utils.Section("Управление зависимостями")

	utils.Command("go get github.com/pkg/errors", "добавить зависимость")
	utils.Command("go get github.com/pkg/errors@v0.9.1", "конкретная версия")
	utils.Command("go get github.com/pkg/errors@latest", "последняя версия")
	utils.Command("go mod tidy", "удалить лишние / добавить нужные зависимости")
	utils.Command("go mod vendor", "скопировать зависимости в ./vendor")
	utils.Command("go mod graph", "граф зависимостей")
	utils.Command("go mod why pkg", "почему пакет является зависимостью")
	utils.Command("go list -m all", "список всех зависимостей")

	// ─── go install / env ─────────────────────────────────────────
	utils.Section("Прочие полезные команды")

	utils.Command("go install tool@latest", "установить CLI-инструмент глобально")
	utils.Command("go env", "показать все переменные окружения Go")
	utils.Command("go env GOPATH", "показать конкретную переменную")
	utils.Command("go env -w GONOSUMCHECK=*", "установить переменную глобально")
	utils.Command("go clean -cache", "очистить кэш сборки")
	utils.Command("go clean -modcache", "очистить кэш модулей")
	utils.Command("go generate ./...", "запустить //go:generate директивы")
	utils.Command("go work init ./mod1 ./mod2", "workspace для нескольких модулей")
	fmt.Println()
	utils.Code(`# Ключевые переменные окружения:
GOROOT   — где установлен Go (/usr/local/go)
GOPATH   — рабочая директория (~/go)
GOBIN    — куда устанавливаются бинарники (~/go/bin)
GOPROXY  — прокси для модулей (https://proxy.golang.org)
GONOSUMCHECK — пакеты без проверки checksumdb
CGO_ENABLED  — включить/отключить cgo (0 или 1)`)

	utils.Footer()
}
