package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

func setupContainers(config Config, clientTitle string, clientInfo *ClientInfo, resources []ResourceData, resourcePortMap map[int][]PortMapping) error {
	log.Printf("Настройка контейнеров для %s", clientTitle)
	baseDir := filepath.Join("/home/install/ptaf", clientTitle)
	containerChanges := make(map[int]bool)
	composeChanges := make(map[int]bool)

	for containerNum := 1; containerNum <= clientInfo.ContainersCount; containerNum++ {
		containerName := fmt.Sprintf("%s-ptaf-agent%03d", clientTitle, containerNum)
		containerDir := filepath.Join(baseDir, containerName)
		log.Printf("  Обработка контейнера: %s", containerName)

		dirs := []string{
			containerDir,
			filepath.Join("/home/install/conf/ptaf-nginx", clientTitle, fmt.Sprintf("ptaf-agent%03d", containerNum), "conf.d"),
		}
		for _, dir := range dirs {
			existed := false
			if _, err := os.Stat(dir); err == nil {
				existed = true
			}
			if err := os.MkdirAll(dir, 0755); err != nil {
				return fmt.Errorf("ошибка создания директории %s: %w", dir, err)
			}
			if !existed {
				log.Printf("    ✓ Создана директория: %s", dir)
			}
		}

		logDir := filepath.Join("/var/log/ptaf_nginx", clientTitle, fmt.Sprintf("ptaf-agent%03d", containerNum))
		logDirExisted := false
		if _, err := os.Stat(logDir); err == nil {
			logDirExisted = true
		}
		if err := os.MkdirAll(logDir, 0777); err != nil {
			return fmt.Errorf("ошибка создания директории логов %s: %w", logDir, err)
		}
		if err := os.Chmod(logDir, 0777); err != nil {
			return fmt.Errorf("ошибка установки прав для директории логов %s: %w", logDir, err)
		}
		if !logDirExisted {
			log.Printf("    ✓ Создана директория логов: %s (права: 0777)", logDir)
		}

		nginxConfPath := filepath.Join("/home/install/conf/ptaf-nginx", clientTitle, fmt.Sprintf("ptaf-agent%03d", containerNum), "nginx.conf")
		existingPodIP := ""
		if info, err := os.Stat(nginxConfPath); err == nil {
			if info.IsDir() {
				log.Printf("    ⚠ nginx.conf является директорией, удаляем...")
				os.RemoveAll(nginxConfPath)
			} else {
				existingPodIP = extractPodIPFromConfig(nginxConfPath)
			}
		}

		ptafConfig := ""
		if clientInfo.PTAFConfig.Valid {
			ptafConfig = clientInfo.PTAFConfig.String
		}

		changed, err := generateNginxConf(nginxConfPath, config, ptafConfig, existingPodIP)
		if err != nil {
			return fmt.Errorf("ошибка генерации nginx.conf: %w", err)
		}
		if changed {
			log.Printf("    ✓ nginx.conf изменен: %s", nginxConfPath)
			containerChanges[containerNum] = true
		} else {
			log.Printf("    ○ nginx.conf не изменился: %s", nginxConfPath)
		}

		mimeTypesPath := filepath.Join("/home/install/conf/ptaf-nginx", clientTitle, fmt.Sprintf("ptaf-agent%03d", containerNum), "mime.types")
		if info, err := os.Stat(mimeTypesPath); err == nil {
			if info.IsDir() {
				log.Printf("    ⚠ mime.types является директорией, удаляем...")
				os.RemoveAll(mimeTypesPath)
			}
		}
		changed, err = generateMimeTypes(mimeTypesPath)
		if err != nil {
			return fmt.Errorf("ошибка генерации mime.types: %w", err)
		}
		if changed {
			log.Printf("    ✓ mime.types изменен: %s", mimeTypesPath)
			containerChanges[containerNum] = true
		}

		confDPath := filepath.Join("/home/install/conf/ptaf-nginx", clientTitle, fmt.Sprintf("ptaf-agent%03d", containerNum), "conf.d")
		containerPorts := []PortMapping{}
		for _, res := range resources {
			ports, ok := resourcePortMap[res.L7ResourceID]
			if !ok || containerNum-1 >= len(ports) {
				return fmt.Errorf("не найдены порты для l7ResourceID %d контейнер %d", res.L7ResourceID, containerNum)
			}
			containerPorts = append(containerPorts, ports[containerNum-1])
			confFile := filepath.Join(confDPath, fmt.Sprintf("%s_%d.conf", clientTitle, res.L7ResourceID))
			oldHash := ""
			if _, err := os.Stat(confFile); err == nil {
				oldHash, _ = getFileHash(confFile)
			}
			err := generateNginxResourceConfig(confFile, config, res, ports[containerNum-1])
			if err != nil {
				return fmt.Errorf("ошибка генерации конфига для ресурса: %w", err)
			}
			newHash, _ := getFileHash(confFile)
			if oldHash != "" && oldHash != newHash {
				log.Printf("    ✓ Конфиг ресурса изменен: %s", confFile)
				containerChanges[containerNum] = true
			} else if oldHash == "" {
				log.Printf("    ✓ Создан конфиг ресурса: %s", confFile)
				containerChanges[containerNum] = true
			} else {
				log.Printf("    ○ Конфиг ресурса не изменился: %s", confFile)
			}
		}

		composeFile := filepath.Join(containerDir, "docker-compose.yml")
		log.Printf("    → DEBUG порты контейнера %d:", containerNum)
		for idx, pm := range containerPorts {
			log.Printf("      PortMapping[%d]: HTTP=%v, HTTPS=%v", idx, pm.HTTPPorts, pm.HTTPSPorts)
		}
		changed, err = generateDockerCompose(composeFile, config, clientTitle, clientInfo, containerNum, resources, containerPorts)
		if err != nil {
			return fmt.Errorf("ошибка генерации docker-compose.yml: %w", err)
		}
		if changed {
			log.Printf("    ✓ docker-compose.yml изменен: %s", composeFile)
			composeChanges[containerNum] = true
		}
		if err := saveContainerPorts(containerDir, containerNum, resources, containerPorts); err != nil {
			log.Printf("    ⚠ Ошибка сохранения портов: %v", err)
		}
	}

	log.Printf("  Запуск и обновление контейнеров для %s", clientTitle)
	for containerNum := 1; containerNum <= clientInfo.ContainersCount; containerNum++ {
		containerName := fmt.Sprintf("%s-ptaf-agent%03d", clientTitle, containerNum)
		containerDir := filepath.Join(baseDir, containerName)
		composeFile := filepath.Join(containerDir, "docker-compose.yml")
		containerFullName := fmt.Sprintf("ptaf_%s_%03d", clientTitle, containerNum)
		containerExists, containerRunning := checkContainerStatus(containerFullName)

		if containerExists {
			if composeChanges[containerNum] {
				recreateContainer(containerFullName, composeFile, containerDir, clientTitle, resources, resourcePortMap, containerNum)
				continue
			}
			if !containerRunning {
				startContainer(containerFullName, composeFile, containerDir)
			}
			if containerChanges[containerNum] {
				log.Printf("  Конфигурация изменилась, проверяем и перезагружаем nginx в %s", containerFullName)
				if err := testNginxConfig(containerFullName); err != nil {
					log.Printf("  ⚠ Ошибка проверки конфигурации в %s: %v", containerFullName, err)
					continue
				}
				if err := reloadNginx(containerFullName); err != nil {
					log.Printf("  ⚠ Ошибка перезагрузки nginx в %s: %v", containerFullName, err)
					continue
				}
				log.Printf("  ✓ Nginx успешно перезагружен в контейнере %s", containerFullName)
			} else {
				log.Printf("  ○ Конфигурация не изменилась, проверка и перезагрузка не требуются для %s", containerFullName)
			}
		} else {
			log.Printf("  Запуск нового контейнера %s", containerName)
			cmd := exec.Command("docker-compose", "-f", composeFile, "up", "-d")
			cmd.Dir = containerDir
			output, _ := cmd.CombinedOutput()
			log.Printf("  → Вывод docker-compose: %s", string(output))
			time.Sleep(5 * time.Second)
			_, isRunning := checkContainerStatus(containerFullName)
			if !isRunning {
				log.Printf("  ⚠ Контейнер %s не запустился. Попробуйте вручную: cd %s && docker-compose up -d", containerFullName, containerDir)
				continue
			}
			log.Printf("  ✓ Контейнер %s успешно запущен", containerName)
		}
	}

	log.Printf("  Проверка лишних контейнеров для %s", clientTitle)
	processDrainingContainers(clientTitle, clientInfo.ContainersCount)
	return nil
}
