"""Dropbox cloud storage provider."""

from typing import Optional, List
from pathlib import Path

from .base import CloudProvider, CloudFile, get_content_type


class DropboxProvider(CloudProvider):
    """
    Dropbox storage provider.

    Requires dropbox package: pip install dropbox
    """

    def __init__(self):
        self._dbx = None
        self._base_folder = "/Whisper Scribe"

    @property
    def name(self) -> str:
        return "dropbox"

    @property
    def display_name(self) -> str:
        return "Dropbox"

    def is_authenticated(self) -> bool:
        return self._dbx is not None

    async def authenticate(self, credentials: dict) -> bool:
        """
        Authenticate with Dropbox.

        credentials should contain:
        - access_token: Dropbox access token
        - refresh_token: (optional) Refresh token for long-lived access
        - app_key: (optional) App key for token refresh
        - app_secret: (optional) App secret for token refresh
        """
        try:
            import dropbox

            access_token = credentials.get('access_token')
            if not access_token:
                raise ValueError("access_token is required")

            # Check if we have refresh token support
            refresh_token = credentials.get('refresh_token')
            app_key = credentials.get('app_key')
            app_secret = credentials.get('app_secret')

            if refresh_token and app_key and app_secret:
                self._dbx = dropbox.Dropbox(
                    oauth2_access_token=access_token,
                    oauth2_refresh_token=refresh_token,
                    app_key=app_key,
                    app_secret=app_secret
                )
            else:
                self._dbx = dropbox.Dropbox(access_token)

            # Verify authentication works
            self._dbx.users_get_current_account()

            # Ensure base folder exists
            await self._ensure_folder()

            return True

        except ImportError:
            raise ImportError("Dropbox support requires: pip install dropbox")
        except Exception as e:
            print(f"Dropbox auth failed: {e}")
            return False

    async def _ensure_folder(self):
        """Create the Whisper Scribe folder if it doesn't exist."""
        import dropbox
        try:
            self._dbx.files_get_metadata(self._base_folder)
        except dropbox.exceptions.ApiError as e:
            if isinstance(e.error, dropbox.files.GetMetadataError) and e.error.is_path():
                # Folder doesn't exist, create it
                self._dbx.files_create_folder_v2(self._base_folder)

    async def upload_file(
        self,
        file_path: str,
        cloud_path: str = None,
        content_type: str = None
    ) -> CloudFile:
        """Upload a local file to Dropbox."""
        if not self.is_authenticated():
            raise Exception("Not authenticated with Dropbox")

        import dropbox

        path = Path(file_path)
        filename = cloud_path or path.name
        dest_path = f"{self._base_folder}/{filename}"

        with open(file_path, 'rb') as f:
            content = f.read()

        # Upload with overwrite mode
        result = self._dbx.files_upload(
            content,
            dest_path,
            mode=dropbox.files.WriteMode.overwrite
        )

        # Get shareable link
        try:
            share_result = self._dbx.sharing_create_shared_link_with_settings(dest_path)
            web_link = share_result.url
        except dropbox.exceptions.ApiError:
            # Link might already exist
            links = self._dbx.sharing_list_shared_links(path=dest_path)
            web_link = links.links[0].url if links.links else None

        return CloudFile(
            id=result.id,
            name=result.name,
            path=result.path_display,
            size=result.size,
            mime_type=content_type or get_content_type(filename),
            web_link=web_link
        )

    async def upload_content(
        self,
        content: bytes,
        filename: str,
        cloud_path: str = None,
        content_type: str = None
    ) -> CloudFile:
        """Upload content directly to Dropbox."""
        if not self.is_authenticated():
            raise Exception("Not authenticated with Dropbox")

        import dropbox

        dest_name = cloud_path or filename
        dest_path = f"{self._base_folder}/{dest_name}"

        # Upload with overwrite mode
        result = self._dbx.files_upload(
            content,
            dest_path,
            mode=dropbox.files.WriteMode.overwrite
        )

        # Get shareable link
        try:
            share_result = self._dbx.sharing_create_shared_link_with_settings(dest_path)
            web_link = share_result.url
        except dropbox.exceptions.ApiError:
            # Link might already exist
            links = self._dbx.sharing_list_shared_links(path=dest_path)
            web_link = links.links[0].url if links.links else None

        return CloudFile(
            id=result.id,
            name=result.name,
            path=result.path_display,
            size=result.size,
            mime_type=content_type or get_content_type(filename),
            web_link=web_link
        )

    async def list_files(self, folder_path: str = None) -> List[CloudFile]:
        """List files in the Whisper Scribe folder."""
        if not self.is_authenticated():
            raise Exception("Not authenticated with Dropbox")

        path = folder_path or self._base_folder

        try:
            result = self._dbx.files_list_folder(path)
        except Exception:
            return []

        files = []
        for entry in result.entries:
            if hasattr(entry, 'size'):  # It's a file, not a folder
                files.append(CloudFile(
                    id=entry.id,
                    name=entry.name,
                    path=entry.path_display,
                    size=entry.size,
                    mime_type=get_content_type(entry.name)
                ))

        return files

    async def delete_file(self, file_id: str) -> bool:
        """Delete a file from Dropbox (by path, not ID)."""
        if not self.is_authenticated():
            raise Exception("Not authenticated with Dropbox")

        try:
            # Dropbox uses paths for deletion
            # file_id here is expected to be the path
            self._dbx.files_delete_v2(file_id)
            return True
        except Exception:
            return False

    async def get_share_link(self, file_id: str) -> str:
        """Get a shareable link for a file (file_id is the path)."""
        if not self.is_authenticated():
            raise Exception("Not authenticated with Dropbox")

        import dropbox

        try:
            result = self._dbx.sharing_create_shared_link_with_settings(file_id)
            return result.url
        except dropbox.exceptions.ApiError:
            # Link might already exist
            links = self._dbx.sharing_list_shared_links(path=file_id)
            if links.links:
                return links.links[0].url
            return ""
