import os
import random


def _backtracker(width, height, seed=42):
    rng = random.Random(seed)
    cw = (width - 1) // 2
    ch = (height - 1) // 2
    grid = [["#"] * width for _ in range(height)]
    visited = [[False] * cw for _ in range(ch)]
    stack = [(0, 0)]
    visited[0][0] = True
    grid[1][1] = " "
    while stack:
        cx, cy = stack[-1]
        gx, gy = cx * 2 + 1, cy * 2 + 1
        dirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]
        rng.shuffle(dirs)
        moved = False
        for dx, dy in dirs:
            nx, ny = cx + dx, cy + dy
            if 0 <= nx < cw and 0 <= ny < ch and not visited[ny][nx]:
                visited[ny][nx] = True
                grid[gy + dy][gx + dx] = " "
                grid[ny * 2 + 1][nx * 2 + 1] = " "
                stack.append((nx, ny))
                moved = True
                break
        if not moved:
            stack.pop()
    grid[1][1] = "S"
    grid[height - 2][width - 2] = "E"
    return grid


def _empty(width, height):
    grid = [["#"] * width for _ in range(height)]
    for y in range(1, height - 1):
        for x in range(1, width - 1):
            grid[y][x] = " "
    grid[1][1] = "S"
    grid[height - 2][width - 2] = "E"
    return grid


def _no_exit(width=11, height=11):
    grid = _backtracker(width, height, seed=99)
    for y in range(height):
        for x in range(width):
            if grid[y][x] == "E":
                grid[y][x] = "#"
    grid[1][width - 2] = "E"
    for dy in [-1, 0, 1]:
        for dx in [-1, 0, 1]:
            ny, nx = 1 + dy, (width - 2) + dx
            if 0 <= ny < height and 0 <= nx < width and grid[ny][nx] != "E":
                grid[ny][nx] = "#"
    return grid


def _save(grid, path):
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "w", encoding="utf-8") as f:
        for row in grid:
            f.write("".join(row) + "\n")


def generate_all(folder="mazes"):
    mazes = {
        "small.txt":   _backtracker(11, 11, seed=1),
        "medium.txt":  _backtracker(51, 51, seed=2),
        "large.txt":   _backtracker(101, 101, seed=3),
        "empty.txt":   _empty(51, 21),
        "no_exit.txt": _no_exit(11, 11),
        "sample.txt":  _backtracker(15, 15, seed=5),
    }
    for name, grid in mazes.items():
        _save(grid, os.path.join(folder, name))
    print(f"Mazes saved to {folder}/")
