"""Update Service Layer.

This service provides software update operations that can be consumed by
multiple interfaces (REST API, BLE GATT, etc.).
"""
from typing import Optional, Dict, Any

from ..managers.update_manager import UpdateManager, UpdateProgress, UpdateStatus
from .pm3_service import PM3ServiceError, PM3ServiceResult


class UpdateService:
    """Update service layer for software update management.

    This service can be used by multiple interfaces:
    - REST API (FastAPI endpoints)
    - BLE GATT (Bluetooth handlers)
    - Plugin system (future)

    It encapsulates:
    - Update checking
    - Update downloading
    - Update installation
    - Progress monitoring
    """

    def __init__(self, update_manager: Optional[UpdateManager] = None):
        """Initialize update service.

        Args:
            update_manager: Update manager instance (creates new if not provided)
        """
        from ..managers.update_manager import get_update_manager
        self.update_manager = update_manager or get_update_manager()

    async def check_for_updates(self) -> PM3ServiceResult:
        """Check for available updates.

        Returns:
            PM3ServiceResult with update availability and information
        """
        try:
            result = await self.update_manager.check_for_updates()

            return PM3ServiceResult(
                success=True,
                data=result
            )

        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="update_check_error",
                    message="Failed to check for updates",
                    details=str(e)
                )
            )

    async def download_update(self) -> PM3ServiceResult:
        """Download the latest available update.

        Returns:
            PM3ServiceResult indicating download success/failure
        """
        try:
            success = await self.update_manager.download_update()

            if success:
                return PM3ServiceResult(
                    success=True,
                    data={
                        "message": "Update downloaded successfully",
                        "ready_to_install": True
                    }
                )
            else:
                return PM3ServiceResult(
                    success=False,
                    error=PM3ServiceError(
                        code="download_failed",
                        message="Update download failed"
                    )
                )

        except ValueError as e:
            # No update available
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="no_update_available",
                    message=str(e)
                )
            )
        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="update_download_error",
                    message="Error downloading update",
                    details=str(e)
                )
            )

    async def install_update(self) -> PM3ServiceResult:
        """Install the downloaded update.

        Returns:
            PM3ServiceResult indicating installation success/failure
        """
        try:
            success = await self.update_manager.install_update()

            if success:
                return PM3ServiceResult(
                    success=True,
                    data={
                        "message": "Update installed successfully",
                        "requires_restart": True
                    }
                )
            else:
                return PM3ServiceResult(
                    success=False,
                    error=PM3ServiceError(
                        code="installation_failed",
                        message="Update installation failed"
                    )
                )

        except ValueError as e:
            # No update downloaded
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="no_update_downloaded",
                    message=str(e)
                )
            )
        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="update_install_error",
                    message="Error installing update",
                    details=str(e)
                )
            )

    async def get_progress(self) -> PM3ServiceResult:
        """Get current update progress.

        Returns:
            PM3ServiceResult with progress information
        """
        try:
            progress = await self.update_manager.get_progress()

            return PM3ServiceResult(
                success=True,
                data={
                    "status": progress.status.value,
                    "current_version": progress.current_version,
                    "available_version": progress.available_version,
                    "download_progress": progress.download_progress,
                    "error_message": progress.error_message,
                    "last_check": progress.last_check
                }
            )

        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="progress_error",
                    message="Failed to get update progress",
                    details=str(e)
                )
            )

    async def get_release_notes(
        self,
        version: Optional[str] = None
    ) -> PM3ServiceResult:
        """Get release notes for a specific version or latest.

        Args:
            version: Version to get notes for (latest if None)

        Returns:
            PM3ServiceResult with release notes
        """
        try:
            notes = await self.update_manager.get_release_notes(version)

            return PM3ServiceResult(
                success=True,
                data={
                    "version": version or "latest",
                    "release_notes": notes
                }
            )

        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="release_notes_error",
                    message="Failed to get release notes",
                    details=str(e)
                )
            )

    async def check_and_download_update(self) -> PM3ServiceResult:
        """Combined operation: check for updates and download if available.

        Returns:
            PM3ServiceResult with check and download status
        """
        try:
            # First check for updates
            check_result = await self.check_for_updates()

            if not check_result.success:
                return check_result

            # If update available, download it
            if check_result.data.get("update_available"):
                download_result = await self.download_update()

                if download_result.success:
                    return PM3ServiceResult(
                        success=True,
                        data={
                            "message": "Update checked and downloaded",
                            "update_info": check_result.data,
                            "ready_to_install": True
                        }
                    )
                else:
                    return download_result
            else:
                return PM3ServiceResult(
                    success=True,
                    data={
                        "message": "System is up to date",
                        "update_available": False,
                        "current_version": check_result.data.get("current_version")
                    }
                )

        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="check_download_error",
                    message="Error checking and downloading update",
                    details=str(e)
                )
            )

    async def full_update(self) -> PM3ServiceResult:
        """Full update workflow: check, download, and install.

        Returns:
            PM3ServiceResult with complete update status
        """
        try:
            # Check for updates
            check_result = await self.check_for_updates()
            if not check_result.success:
                return check_result

            if not check_result.data.get("update_available"):
                return PM3ServiceResult(
                    success=True,
                    data={
                        "message": "System is already up to date",
                        "update_performed": False
                    }
                )

            # Download update
            download_result = await self.download_update()
            if not download_result.success:
                return download_result

            # Install update
            install_result = await self.install_update()
            if not install_result.success:
                return install_result

            return PM3ServiceResult(
                success=True,
                data={
                    "message": "Update completed successfully",
                    "update_performed": True,
                    "previous_version": check_result.data.get("current_version"),
                    "new_version": check_result.data.get("latest_version"),
                    "requires_restart": True
                }
            )

        except Exception as e:
            return PM3ServiceResult(
                success=False,
                error=PM3ServiceError(
                    code="full_update_error",
                    message="Error performing full update",
                    details=str(e)
                )
            )
