"""
Baseline image management functionality.

Handles storage, retrieval, and management of baseline images for
visual regression testing of OOXML templates.
"""

import structlog
import shutil
import hashlib
from typing import Optional
from pathlib import Path
import time

logger = structlog.get_logger(__name__)


def create_baseline_structure(workspace_dir: str) -> bool:
    """
    Create baseline directory structure.

    Args:
        workspace_dir: Base workspace directory.

    Returns:
        bool: True if structure created successfully, False otherwise.
    """
    try:
        logger.info("Creating baseline directory structure", workspace=workspace_dir)

        workspace_path = Path(workspace_dir)
        baselines_dir = workspace_path / "tests" / "baselines"

        # Create tier and category directories
        tiers = ["community", "professional", "enterprise"]
        categories = ["presentation", "document", "spreadsheet"]

        for tier in tiers:
            for category in categories:
                category_dir = baselines_dir / tier / category
                category_dir.mkdir(parents=True, exist_ok=True)
                logger.debug("Created baseline directory", tier=tier, category=category)

        logger.info("Baseline directory structure created successfully")
        return True

    except Exception as e:
        logger.error("Error creating baseline structure", error=str(e))
        return False


def store_baseline_image(
    image_path: str, tier: str, category: str, template_name: str
) -> bool:
    """
    Store baseline image in appropriate location.

    Args:
        image_path: Path to the image file to store.
        tier: Template tier (community, professional, enterprise).
        category: Template category (presentation, document, spreadsheet).
        template_name: Name of the template.

    Returns:
        bool: True if stored successfully, False otherwise.
    """
    try:
        logger.info(
            "Storing baseline image",
            image=image_path,
            tier=tier,
            category=category,
            template=template_name,
        )

        source_path = Path(image_path)
        if not source_path.exists():
            logger.error("Source image file does not exist", path=image_path)
            return False

        # Determine baseline storage location
        baseline_dir = Path("tests") / "baselines" / tier / category
        baseline_dir.mkdir(parents=True, exist_ok=True)

        baseline_path = baseline_dir / f"{template_name}.png"

        # Copy image to baseline location
        shutil.copy2(source_path, baseline_path)

        logger.info("Baseline image stored successfully", baseline=str(baseline_path))
        return True

    except Exception as e:
        logger.error("Error storing baseline image", error=str(e))
        return False


def retrieve_baseline_image(
    tier: str, category: str, template_name: str
) -> Optional[bytes]:
    """
    Retrieve baseline image data.

    Args:
        tier: Template tier.
        category: Template category.
        template_name: Name of the template.

    Returns:
        Image data as bytes if found, None otherwise.
    """
    try:
        logger.debug(
            "Retrieving baseline image",
            tier=tier,
            category=category,
            template=template_name,
        )

        baseline_path = (
            Path("tests") / "baselines" / tier / category / f"{template_name}.png"
        )

        if not baseline_path.exists():
            logger.warning("Baseline image not found", path=str(baseline_path))
            return None

        image_data = baseline_path.read_bytes()
        logger.debug(
            "Baseline image retrieved successfully",
            size=len(image_data),
            path=str(baseline_path),
        )
        return image_data

    except Exception as e:
        logger.error("Error retrieving baseline image", error=str(e))
        return None


def validate_baseline_hash(
    tier: str, category: str, template_name: str, expected_hash: str
) -> bool:
    """
    Validate baseline image hash.

    Args:
        tier: Template tier.
        category: Template category.
        template_name: Name of the template.
        expected_hash: Expected SHA256 hash.

    Returns:
        bool: True if hash matches, False otherwise.
    """
    try:
        logger.debug(
            "Validating baseline hash",
            tier=tier,
            category=category,
            template=template_name,
        )

        image_data = retrieve_baseline_image(tier, category, template_name)
        if image_data is None:
            logger.error("Cannot validate hash - baseline image not found")
            return False

        actual_hash = hashlib.sha256(image_data).hexdigest()
        hash_match = actual_hash == expected_hash

        logger.debug(
            "Hash validation result",
            expected=expected_hash[:16] + "...",
            actual=actual_hash[:16] + "...",
            match=hash_match,
        )

        return hash_match

    except Exception as e:
        logger.error("Error validating baseline hash", error=str(e))
        return False


def update_baseline_image(
    image_path: str, tier: str, category: str, template_name: str
) -> bool:
    """
    Update existing baseline image.

    Args:
        image_path: Path to new image file.
        tier: Template tier.
        category: Template category.
        template_name: Name of the template.

    Returns:
        bool: True if updated successfully, False otherwise.
    """
    try:
        logger.info(
            "Updating baseline image",
            new_image=image_path,
            tier=tier,
            category=category,
            template=template_name,
        )

        # Store the new image (overwrites existing)
        result = store_baseline_image(image_path, tier, category, template_name)

        if result:
            logger.info("Baseline image updated successfully")
        else:
            logger.error("Failed to update baseline image")

        return result

    except Exception as e:
        logger.error("Error updating baseline image", error=str(e))
        return False


def update_baseline_with_backup(
    image_path: str, tier: str, category: str, template_name: str
) -> bool:
    """
    Update baseline image with backup of original.

    Args:
        image_path: Path to new image file.
        tier: Template tier.
        category: Template category.
        template_name: Name of the template.

    Returns:
        bool: True if updated with backup, False otherwise.
    """
    try:
        logger.info(
            "Updating baseline with backup",
            template=template_name,
            tier=tier,
            category=category,
        )

        baseline_dir = Path("tests") / "baselines" / tier / category
        current_baseline = baseline_dir / f"{template_name}.png"

        # Create backup if baseline exists
        if current_baseline.exists():
            backup_dir = baseline_dir / "backups"
            backup_dir.mkdir(exist_ok=True)

            timestamp = int(time.time())
            backup_filename = f"{template_name}_{timestamp}.png"
            backup_path = backup_dir / backup_filename

            shutil.copy2(current_baseline, backup_path)
            logger.info("Created backup of existing baseline", backup=str(backup_path))

        # Update with new baseline
        result = update_baseline_image(image_path, tier, category, template_name)

        if result:
            logger.info("Baseline updated successfully with backup")
        else:
            logger.error("Failed to update baseline despite backup creation")

        return result

    except Exception as e:
        logger.error("Error updating baseline with backup", error=str(e))
        return False
