"""
ScreenshotManager — screenshot file validation, naming, and entity creation.

Provides utility methods for checking whether a string is an S3/HTTP URL,
normalising screenshot filenames, extracting timestamps from filenames, validating
file accessibility, and constructing
:class:`~ws_package.entities.screenshot_entity.ScreenshotEntity` instances.

Thread-safety:
    All methods are synchronous and stateless beyond ``self.last_count``; they are
    thread-safe as long as callers do not mutate ``last_count`` concurrently.
"""
# ws_package/managers/screenshot_manager.py
import datetime
import os
import re
from pathlib import Path
from typing import List

from ws_package.entities.screenshot_entity import ScreenshotEntity
from ws_package.entities.user_entity import UserEntity
from ws_package.log.writer import LogWriter
from ws_package.exceptions.custom_exceptions import ValidationError, ScreenshotError
from ws_package.utils.system import get_os_type

logger = LogWriter.file(__name__)

class ScreenshotProcessor:
    """Manages screenshot processing and validation operations."""
    
    def __init__(self, last_count: int):
        self.last_count = last_count
    
    def is_link(self, url: str) -> bool:
        """Check whether ``url`` is a valid HTTP/HTTPS URL.

        Args:
            url: String to test.

        Returns:
            ``True`` if ``url`` matches the HTTP/HTTPS pattern, ``False`` otherwise
            (including on ``None``, empty string, or regex error).
        """
        try:
            if not url:
                return False
            
            pattern = re.compile(r'^(https?://)[^\s/$.?#].[^\s]*$', re.IGNORECASE)
            return bool(pattern.match(url))
        except re.error as e:
            logger.error("Regex error in is_link: %s", e, exc_info=True)
            return False
        except Exception as e:
            logger.error("Error in detecting link in is_link: %s", e, exc_info=True)
            return False
    
    def forward_ss(self, ss: str) -> str:
        """Normalise a screenshot path to a forward-slash basename for S3 key construction.

        Args:
            ss: Local file path (may use backslashes on Windows).

        Returns:
            Basename of the path with all backslashes replaced by forward slashes.
        """
        forwardSS = ss.replace("\\", "/")
        return os.path.basename(forwardSS)
    
    def format_ss_name(self, original_name: str) -> str:
        """Format a screenshot filename as a ``YYYY-MM-DD`` date string for S3 directory keys.

        Args:
            original_name: Screenshot basename (with or without extension), expected
                in ``{utc_timestamp}_{ulid}`` or legacy ``%Y%m%d_%H%M%S.%f`` format.

        Returns:
            Formatted date string ``YYYY-MM-DD``, or the original name if parsing fails.
        """
        try:
            from ws_package.utils.screenshot_naming import parse_screenshot_datetime

            dt = parse_screenshot_datetime(original_name)
            return dt.strftime("%Y-%m-%d")
        except ValueError:
            return original_name
    
    def unix_format_ss_name(self, original_name: str) -> str:
        """Format a screenshot filename as ``YYYY-MM-DD<ext>`` for Unix S3 object keys.

        Args:
            original_name: Screenshot basename with extension, expected in
                ``{utc_timestamp}_{ulid}`` or legacy ``%Y%m%d_%H%M%S.%f`` format.

        Returns:
            Formatted string ``YYYY-MM-DD<ext>``, or the original name if parsing fails.
        """
        try:
            from ws_package.utils.screenshot_naming import parse_screenshot_datetime

            _, ex = os.path.splitext(original_name)
            dt = parse_screenshot_datetime(original_name)
            return f"{dt.strftime('%Y-%m-%d')}{ex}"
        except ValueError:
            return original_name
    
    def extract_datetime_from_filename(self, filename: str) -> datetime.datetime:
        """Extract a ``datetime`` from a screenshot filename.

        Supports ``{utc_timestamp}_{ulid}.{ext}`` and legacy ``YYYYMMDD_HHMMSS.ffffff``.

        Args:
            filename: Screenshot file path or basename.

        Returns:
            Parsed ``datetime.datetime``, or ``datetime.datetime.now()`` if no
            timestamp pattern is found or if parsing fails.
        """
        try:
            from ws_package.utils.screenshot_naming import parse_screenshot_datetime

            return parse_screenshot_datetime(filename)
        except Exception as e:
            logger.error("Error extracting datetime from filename %s: %s", filename, e, exc_info=True)
            return datetime.datetime.now()
    
    def validate_screenshot_file(self, file_path: str) -> bool:
        """Check that a screenshot file exists on disk and is readable by the current process.

        Args:
            file_path: Absolute or relative path to the screenshot file.

        Returns:
            ``True`` if the file exists and is readable, ``False`` otherwise.
        """
        try:
            if not file_path or not os.path.exists(file_path):
                return False
            
            if not os.access(file_path, os.R_OK):
                return False
            
            return True
        except Exception as e:
            logger.error("Error validating screenshot file %s: %s", file_path, e, exc_info=True)
            return False
    
    def create_screenshot_entity(self, file_path: str, s3_upload_link: str,
                                user_entity: UserEntity) -> ScreenshotEntity:
        """Build a :class:`~ws_package.entities.screenshot_entity.ScreenshotEntity` from a local file.

        Args:
            file_path: Validated local screenshot file path.
            s3_upload_link: S3 URL returned after uploading the file.
            user_entity: Authenticated user entity (used to set the ``counter``).

        Returns:
            Populated :class:`~ws_package.entities.screenshot_entity.ScreenshotEntity`.

        Raises:
            ValidationError: If ``file_path`` fails validation.
            ScreenshotError: If entity construction fails for any other reason.
        """
        try:
            if not self.validate_screenshot_file(file_path):
                raise ValidationError(f"Invalid screenshot file: {file_path}")
            
            particular_timestamp = self.extract_datetime_from_filename(file_path)
            
            return ScreenshotEntity(
                file_name=file_path,
                blur=True,
                s3_upload_link=s3_upload_link,
                file_size=str(os.stat(file_path).st_size),
                is_uploaded=False,
                file_location=file_path,
                timestamp=particular_timestamp,
                is_s3_uploaded=True,
                counter=self.last_count + 1
            )
        except Exception as e:
            logger.error("Error creating screenshot entity for %s: %s", file_path, e, exc_info=True)
            raise ScreenshotError(f"Failed to create screenshot entity: {e}")
    
    def get_os_type(self) -> str:
        """Return the OS type string used to determine platform-specific screenshot naming.

        Returns:
            OS type string from :func:`~ws_package.utils.system.get_os_type`.
        """
        return get_os_type()
