"""Validate files step for upload workflow."""

from __future__ import annotations

from typing import Any

from synapse_sdk.plugins.actions.upload.context import UploadContext
from synapse_sdk.plugins.actions.upload.enums import LogCode
from synapse_sdk.plugins.actions.upload.strategies import (
    DefaultValidationStrategy,
    ValidationStrategy,
)
from synapse_sdk.plugins.steps import BaseStep, StepResult


class ValidateFilesStep(BaseStep[UploadContext]):
    """Validate organized files against specifications.

    This step uses a validation strategy to:
    1. Validate that required file types are present
    2. Validate file extensions match specifications
    3. Validate file integrity (if configured)

    Progress weight: 0.10 (10%)
    """

    def __init__(self, validation_strategy: ValidationStrategy | None = None):
        """Initialize with optional validation strategy.

        Args:
            validation_strategy: Strategy for file validation.
                Defaults to DefaultValidationStrategy.
        """
        self._validation_strategy = validation_strategy

    @property
    def name(self) -> str:
        """Step identifier."""
        return 'validate_files'

    @property
    def progress_weight(self) -> float:
        """Relative progress weight."""
        return 0.10

    def execute(self, context: UploadContext) -> StepResult:
        """Execute file validation step.

        Args:
            context: Upload context with organized files and specifications.

        Returns:
            StepResult with validation status in data.
        """
        strategy = self._validation_strategy or DefaultValidationStrategy()

        if not context.organized_files:
            context.log(LogCode.NO_FILES_FOUND_WARNING.value, {})
            return StepResult(
                success=False,
                error='No organized files to validate',
            )

        # Get file specifications from data_collection
        file_specifications = self._get_file_specifications(context)
        if not file_specifications:
            return StepResult(
                success=False,
                error='File specifications not available',
            )

        try:
            # Set initial progress
            context.set_progress(0, 1)

            # Validate organized files against specifications
            validation_result = strategy.validate_files(
                context.organized_files,
                file_specifications,
            )

            if not validation_result.valid:
                context.log(
                    LogCode.VALIDATION_FAILED.value,
                    {
                        'errors': validation_result.errors,
                    },
                )
                error_msg = f'File validation failed: {", ".join(validation_result.errors)}'
                return StepResult(
                    success=False,
                    error=error_msg,
                )

            # Complete progress
            context.set_progress(1, 1)

            context.log(
                LogCode.STEP_COMPLETED.value,
                {
                    'step': self.name,
                    'files_count': len(context.organized_files),
                },
            )

            return StepResult(
                success=True,
                data={'validation_passed': True},
                rollback_data={'validated_files_count': len(context.organized_files)},
            )

        except Exception as e:
            return StepResult(
                success=False,
                error=f'File validation failed: {e}',
            )

    def _get_file_specifications(self, context: UploadContext) -> list[dict[str, Any]]:
        """Get file specifications from context."""
        if context.data_collection:
            return context.data_collection.get('file_specifications', [])
        return []

    def can_skip(self, context: UploadContext) -> bool:
        """File validation cannot be skipped."""
        return False

    def rollback(self, context: UploadContext, result: StepResult) -> None:
        """Rollback file validation."""
        context.log(LogCode.ROLLBACK_FILE_VALIDATION.value, {})
