import os
import requests
import zipfile
import sqlite3
from pathlib import Path
from typing import Optional
from rich.console import Console
from rich.progress import Progress

console = Console()

# Default config server URL for remote plugin installations
DEFAULT_CONFIG_SERVER = "https://7c347c17-595b-4b23-8b8e-961eb4eb8800-00-18rtado0909j7.janeway.replit.dev"


class PluginInstaller:
    def __init__(self, server_url=None):
        self.server_url = server_url or self._get_server_url()
        self.plugins_dir = Path.home() / '.feather' / 'plugins'
        self.plugins_dir.mkdir(parents=True, exist_ok=True)

    def _normalize_url(self, url: str) -> Optional[str]:
        """Normalize a URL to ensure it has protocol and no trailing slash"""
        if not url:
            return None

        url = url.rstrip('/')

        # Add protocol if missing
        if not url.startswith(('http://', 'https://')):
            url = f'https://{url}'

        return url

    def _get_server_url_from_api(self) -> Optional[str]:
        """Query the /api/config endpoint to get plugin server URL"""
        try:
            config_url = f"{DEFAULT_CONFIG_SERVER}/api/config"
            response = requests.get(config_url, timeout=10)
            
            if response.status_code == 200:
                data = response.json()
                plugin_server_url = data.get('plugin_server_url')
                if plugin_server_url:
                    return self._normalize_url(plugin_server_url)
        except Exception:
            pass
        
        return None

    def _get_server_url(self):
        """Get plugin server URL from admin database settings or remote API"""
        
        # Method 1: Try local database (when running from project root)
        try:
            db_path = 'admin/admin.db'
            if os.path.exists(db_path):
                conn = sqlite3.connect(db_path)
                cursor = conn.cursor()
                cursor.execute("SELECT value FROM system_settings WHERE key = 'plugin_server_url'")
                result = cursor.fetchone()
                conn.close()
                if result and result[0]:
                    return self._normalize_url(result[0])
        except Exception:
            pass
        
        # Method 2: Try importing admin.models (when package is installed in development mode)
        try:
            from admin.models import admin_db
            db_url = admin_db.get_setting('plugin_server_url')
            if db_url is not None:
                return self._normalize_url(str(db_url))
        except Exception:
            pass
        
        # Method 3: Query remote /api/config endpoint (for remote installations)
        remote_url = self._get_server_url_from_api()
        if remote_url:
            return remote_url
        
        return None

    def install(self, plugin_name: str):
        """Download and install a plugin from the server"""
        console.print(f"[cyan]Installing plugin: {plugin_name}[/cyan]")

        # Check if server URL is available
        if not self.server_url:
            console.print(f"[red]✗ Plugin server offline - contact administrator[/red]")
            console.print(f"[yellow]The plugin server URL is not configured in admin settings[/yellow]")
            return False

        # Construct the download URL
        # Check if server_url already has /api/plugins path
        if '/api/plugins' in self.server_url:
            download_url = f"{self.server_url}/{plugin_name}/download"
        else:
            download_url = f"{self.server_url}/api/plugins/{plugin_name}/download"

        try:
            response = requests.get(download_url, timeout=30)

            if response.status_code == 404:
                console.print(f"[red]✗ Plugin '{plugin_name}' not found[/red]")
                return False

            if response.status_code != 200:
                console.print(
                    f"[red]✗ Failed to download plugin (HTTP {response.status_code})[/red]"
                )
                return False

            plugin_path = self.plugins_dir / plugin_name
            plugin_path.mkdir(parents=True, exist_ok=True)

            zip_path = plugin_path / f"{plugin_name}.zip"
            with open(zip_path, 'wb') as f:
                f.write(response.content)

            with zipfile.ZipFile(zip_path, 'r') as zip_ref:
                zip_ref.extractall(plugin_path)

            zip_path.unlink()

            console.print(
                f"[green]✓ Plugin '{plugin_name}' installed successfully[/green]"
            )
            return True

        except requests.exceptions.ConnectionError:
            console.print(f"[red]✗ Could not connect to plugin server[/red]")
            console.print(
                f"[yellow]Please check your internet connection and try again[/yellow]"
            )
            return False
        except requests.exceptions.Timeout:
            console.print(f"[red]✗ Connection timed out[/red]")
            return False
        except Exception as e:
            console.print(f"[red]✗ Error installing plugin: {e}[/red]")
            return False

    def list_installed(self):
        """List all installed plugins"""
        if not self.plugins_dir.exists():
            console.print("[yellow]No plugins installed yet[/yellow]")
            return

        plugins = [d for d in self.plugins_dir.iterdir() if d.is_dir()]

        if not plugins:
            console.print("[yellow]No plugins installed yet[/yellow]")
            return

        console.print("[cyan]Installed plugins:[/cyan]")
        for plugin in sorted(plugins):
            console.print(f"  • {plugin.name}")

        console.print(f"\n[dim]Total: {len(plugins)} plugin(s)[/dim]")
