import pytest
import os
import json
import shutil
import time
import tempfile
from app import create_app


def init_test_environment(storage_path):
    """Initialize the test environment with required directories."""
    if os.path.exists(storage_path):
        try:
            shutil.rmtree(storage_path)
        except PermissionError:
            # Try to handle Windows file locking issues
            print(f"Warning: Could not remove {storage_path} directory, retrying...")
            time.sleep(1)
            try:
                shutil.rmtree(storage_path)
            except Exception as e:
                print(f"Failed to remove directory: {e}")

    # Create main storage directory
    os.makedirs(storage_path, exist_ok=True)

    # Create required subdirectories
    for dir_name in ["users", "schemas", "filetypes", "projects", "logs"]:
        os.makedirs(os.path.join(storage_path, dir_name), exist_ok=True)

    # Initialize test data
    initialize_test_data(storage_path)


@pytest.fixture
def app():
    # Use a unique temporary directory for each test session
    storage_path = tempfile.mkdtemp(prefix="arch_test_")

    # Set up the test environment
    init_test_environment(storage_path)

    # Create app with test configuration
    app = create_app("testing")

    # Update the app's config with our test settings
    app.config.update(
        {
            "TESTING": True,
            "STORAGE_PATH": storage_path,
            "WTF_CSRF_ENABLED": False,  # Disable CSRF protection for testing
            "SERVER_NAME": "localhost.localdomain",  # Set server name to ensure correct URLs
        }
    )

    # Create app context
    with app.app_context():
        yield app

    # Clean up after tests - with retry mechanism for Windows
    max_retries = 3
    retry_delay = 1

    for attempt in range(max_retries):
        try:
            if os.path.exists(storage_path):
                shutil.rmtree(storage_path)
            break
        except PermissionError:
            if attempt < max_retries - 1:
                print(
                    f"Cleanup attempt {attempt+1} failed, retrying in {retry_delay}s..."
                )
                time.sleep(retry_delay)
            else:
                print(f"Warning: Could not clean up {storage_path}")


@pytest.fixture
def client(app):
    """Create a test client for the application."""
    with app.test_client() as client:
        # Enable cookies and sessions for the test client
        client.testing = True
        yield client


@pytest.fixture
def auth(client):
    """Helper for authentication tests."""

    class AuthActions:
        def login(self, username="admin", password="admin123"):
            # Use session for better cookie handling
            with client.session_transaction() as session:
                # Pre-clear any existing session data
                session.clear()

            response = client.post(
                "/auth/login",
                data={"username": username, "password": password},
                follow_redirects=True,
            )
            return response

        def logout(self):
            return client.get("/auth/logout", follow_redirects=True)

    return AuthActions()


@pytest.fixture
def logged_in_client(client, auth):
    """Client that's already logged in as admin."""
    response = auth.login()

    # Verify login was successful
    assert response.status_code == 200

    # Check for expected content in response to confirm logged in state
    assert (
        b"Cerrar" in response.data
        or b"Logout" in response.data
        or b"Panel" in response.data
    )

    return client


def initialize_test_data(storage_path):
    """Initialize test data files."""
    # Create test users
    users_data = {
        "admin": {
            "nombre": "Administrador",
            "username": "admin",
            "email": "admin@ejemplo.com",
            "password_hash": "$2b$12$Q5Nz3QSF0FP.mKAxPmWXmurKn1oor4Cl1KbYZAKsFbGcEWWyPHou6",  # admin123
            "nivel": 9999,
            "idioma": "es",
            "fecha_caducidad": None,
            "empresa": "ARCH",
            "estado": "activo",
        },
        "user1": {
            "nombre": "Usuario Normal",
            "username": "user1",
            "email": "user1@ejemplo.com",
            "password_hash": "$2b$12$Q5Nz3QSF0FP.mKAxPmWXmurKn1oor4Cl1KbYZAKsFbGcEWWyPHou6",  # admin123
            "nivel": 1000,
            "idioma": "es",
            "fecha_caducidad": None,
            "empresa": "ARCH",
            "estado": "activo",
        },
    }

    with open(f"{storage_path}/users/users.json", "w", encoding="utf-8") as f:
        json.dump(users_data, f, ensure_ascii=False, indent=2)

    # Create test file types
    filetypes_data = {
        "pdf": {
            "extension": "pdf",
            "descripcion": "Documento PDF",
            "mime_type": "application/pdf",
            "tamano_maximo": 20971520,
        },
        "txt": {
            "extension": "txt",
            "descripcion": "Documento de texto",
            "mime_type": "text/plain",
            "tamano_maximo": 5242880,
        },
    }

    with open(f"{storage_path}/filetypes/filetypes.json", "w", encoding="utf-8") as f:
        json.dump(filetypes_data, f, ensure_ascii=False, indent=2)

    # Create test schemas
    schemas_data = {
        "TEST001": {
            "codigo": "TEST001",
            "descripcion": "Esquema de prueba",
            "fecha_creacion": "2023-10-01T10:00:00Z",
            "creado_por": "admin",
            "documentos": [
                {
                    "tipo": "pdf",
                    "nombre": "Documento de Prueba",
                    "nivel_ver": 0,
                    "nivel_editar": 1000,
                }
            ],
        }
    }

    with open(f"{storage_path}/schemas/schema.json", "w", encoding="utf-8") as f:
        json.dump(schemas_data, f, ensure_ascii=False, indent=2)

    # Create indices file
    indices_data = {"max_project_id": 0, "max_document_id": 0}

    with open(f"{storage_path}/indices.json", "w", encoding="utf-8") as f:
        json.dump(indices_data, f, ensure_ascii=False, indent=2)
