import asyncio
import typer
from typing import Optional, List
from rich.console import Console
from rich.table import Table
from ..crawlers.batch_crawler import BatchCrawler
from ..database.supabase_client import SupabaseManager
from ..models.company import CompanyData

app = typer.Typer(help="NordCrawl - batch crawler för nordisk företagsdata")
console = Console()


@app.command()
def crawl(
    input_file: str = typer.Argument(..., help="CSV eller JSON fil med URLs"),
    output_file: Optional[str] = typer.Option(None, "--output", "-o", help="Output fil (JSON/CSV)"),
    format: str = typer.Option("json", "--format", "-f", help="Output format: json eller csv"),
    max_concurrent: int = typer.Option(5, "--max-concurrent", "-c", help="Max samtidiga requests"),
    rate_limit: float = typer.Option(2.0, "--rate-limit", "-r", help="Sekunder mellan requests till samma domän"),
    save_to_db: bool = typer.Option(False, "--save-db", "-s", help="Spara till Supabase databas"),
    max_retries: int = typer.Option(3, "--max-retries", help="Max antal retries")
):
    """Starta batch crawl av URLs från fil"""
    
    async def run_crawl():
        console.print(f"[bold blue]Startar NordCrawl från {input_file}[/bold blue]")
        
        # Skapa batch crawler
        crawler = BatchCrawler(
            max_concurrent=max_concurrent,
            rate_limit_delay=rate_limit,
            max_retries=max_retries
        )
        
        # Kör crawl
        results = await crawler.crawl_from_file(input_file)
        
        if not results:
            console.print("[yellow]Inga resultat att processera[/yellow]")
            return
        
        # Spara till fil
        if output_file:
            await crawler.export_results(results, output_file, format)
        
        # Spara till Supabase
        if save_to_db:
            try:
                db_manager = SupabaseManager()
                await db_manager.initialize_table()
                
                console.print(f"[blue]Sparar {len(results)} resultat till Supabase...[/blue]")
                db_results = await db_manager.batch_upsert(results)
                console.print(f"[green]Sparade {len(db_results)} poster till databasen[/green]")
                
            except Exception as e:
                console.print(f"[red]Fel vid databas-sparning: {e}[/red]")
        
        # Visa resultat
        _display_results(results)
    
    asyncio.run(run_crawl())


@app.command()
def crawl_urls(
    urls: List[str] = typer.Argument(..., help="URLs att crawla"),
    output_file: Optional[str] = typer.Option(None, "--output", "-o", help="Output fil"),
    format: str = typer.Option("json", "--format", "-f", help="Output format"),
    save_to_db: bool = typer.Option(False, "--save-db", "-s", help="Spara till Supabase")
):
    """Crawla specifika URLs direkt från kommandoraden"""
    
    async def run_crawl_urls():
        console.print(f"[bold blue]Crawlar {len(urls)} URLs med NordCrawl...[/bold blue]")
        
        crawler = BatchCrawler()
        results = await crawler.crawl_urls(urls)
        
        if output_file:
            await crawler.export_results(results, output_file, format)
        
        if save_to_db:
            try:
                db_manager = SupabaseManager()
                await db_manager.initialize_table()
                db_results = await db_manager.batch_upsert(results)
                console.print(f"[green]Sparade {len(db_results)} poster till databasen[/green]")
            except Exception as e:
                console.print(f"[red]Fel vid databas-sparning: {e}[/red]")
        
        _display_results(results)
    
    asyncio.run(run_crawl_urls())


@app.command()
def stats(
    limit: int = typer.Option(100, "--limit", "-l", help="Antal senaste resultat att visa")
):
    """Visa statistik från Supabase databasen"""
    
    async def show_stats():
        try:
            db_manager = SupabaseManager()
            await db_manager.initialize_table()
            
            # Hämta statistik
            stats_data = await db_manager.get_statistics()
            
            console.print("\n[bold green]📊 Crawl Statistik[/bold green]")
            
            stats_table = Table(title="Översikt")
            stats_table.add_column("Mätvärde", style="cyan")
            stats_table.add_column("Värde", style="green")
            
            stats_table.add_row("Totalt URLs", str(stats_data.get('total_urls', 0)))
            stats_table.add_row("Lyckade crawls", str(stats_data.get('successful_crawls', 0)))
            stats_table.add_row("Misslyckade crawls", str(stats_data.get('failed_crawls', 0)))
            stats_table.add_row("Success rate", f"{stats_data.get('success_rate', 0):.1f}%")
            stats_table.add_row("Unika domäner", str(stats_data.get('unique_domains', 0)))
            stats_table.add_row("Genomsnittlig konfidens", f"{stats_data.get('average_confidence', 0):.2f}")
            
            console.print(stats_table)
            
            # Visa senaste resultat
            recent_results = await db_manager.get_recent_crawls(limit)
            
            if recent_results:
                console.print(f"\n[bold blue]📋 Senaste {len(recent_results)} crawl-resultat[/bold blue]")
                
                results_table = Table(title="Resultat")
                results_table.add_column("Företag", style="cyan")
                results_table.add_column("Org.nummer", style="yellow")
                results_table.add_column("Status", style="green")
                results_table.add_column("Konfidens", style="blue")
                results_table.add_column("Datum", style="magenta")
                
                for result in recent_results[:10]:  # Visa max 10
                    company_name = result.get('company_name', 'N/A')
                    org_number = result.get('org_number', 'N/A')
                    status = result.get('status', 'N/A')
                    confidence = result.get('extraction_confidence', 0)
                    crawled_at = result.get('crawled_at', 'N/A')
                    
                    # Trunkera långa namn
                    if len(company_name) > 30:
                        company_name = company_name[:27] + "..."
                    
                    # Formatera datum
                    if crawled_at != 'N/A':
                        try:
                            from datetime import datetime
                            dt = datetime.fromisoformat(crawled_at.replace('Z', '+00:00'))
                            crawled_at = dt.strftime('%Y-%m-%d %H:%M')
                        except:
                            pass
                    
                    confidence_str = f"{confidence:.2f}" if confidence else "N/A"
                    
                    results_table.add_row(
                        company_name,
                        org_number,
                        status,
                        confidence_str,
                        crawled_at
                    )
                
                console.print(results_table)
        
        except Exception as e:
            console.print(f"[red]Fel vid hämtning av statistik: {e}[/red]")
    
    asyncio.run(show_stats())


@app.command()
def search(
    query: str = typer.Argument(..., help="Sökterm"),
    limit: int = typer.Option(20, "--limit", "-l", help="Max resultat")
):
    """Sök företag i databasen"""
    
    async def search_companies():
        try:
            db_manager = SupabaseManager()
            await db_manager.initialize_table()
            
            results = await db_manager.search_companies(query, limit)
            
            if not results:
                console.print(f"[yellow]Inga resultat funna för '{query}'[/yellow]")
                return
            
            console.print(f"\n[bold green]🔍 Sökresultat för '{query}'[/bold green]")
            
            search_table = Table(title="Resultat")
            search_table.add_column("Företag", style="cyan")
            search_table.add_column("Org.nummer", style="yellow")
            search_table.add_column("Email", style="green")
            search_table.add_column("Telefon", style="blue")
            search_table.add_column("Stad", style="magenta")
            
            for result in results:
                company_name = result.get('company_name', 'N/A')
                org_number = result.get('org_number', 'N/A')
                email = result.get('email', 'N/A')
                phone = result.get('phone', 'N/A')
                city = result.get('city', 'N/A')
                
                # Trunkera långa fält
                if len(company_name) > 40:
                    company_name = company_name[:37] + "..."
                if len(email) > 30:
                    email = email[:27] + "..."
                
                search_table.add_row(company_name, org_number, email, phone, city)
            
            console.print(search_table)
            console.print(f"\nHittade {len(results)} resultat")
        
        except Exception as e:
            console.print(f"[red]Fel vid sökning: {e}[/red]")
    
    asyncio.run(search_companies())


@app.command()
def export(
    output_file: str = typer.Argument(..., help="Output fil"),
    format: str = typer.Option("csv", "--format", "-f", help="Format: csv eller json")
):
    """Exportera alla data från databasen till fil"""
    
    async def export_data():
        try:
            db_manager = SupabaseManager()
            await db_manager.initialize_table()
            
            console.print("[blue]Exporterar data från databasen...[/blue]")
            
            if format.lower() == "csv":
                data = await db_manager.export_to_csv_format()
                import pandas as pd
                df = pd.DataFrame(data)
                df.to_csv(output_file, index=False, encoding='utf-8')
            
            elif format.lower() == "json":
                data = await db_manager.get_recent_crawls(10000)  # Hämta mycket data
                import json
                with open(output_file, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=2, default=str)
            
            else:
                console.print(f"[red]Format {format} stöds inte[/red]")
                return
            
            console.print(f"[green]Exporterade {len(data)} poster till {output_file}[/green]")
        
        except Exception as e:
            console.print(f"[red]Fel vid export: {e}[/red]")
    
    asyncio.run(export_data())


def _display_results(results: List[CompanyData]):
    """Visa crawl-resultat i tabell"""
    if not results:
        return
    
    console.print(f"\n[bold green]✅ Crawl Resultat ({len(results)} företag)[/bold green]")
    
    results_table = Table(title="Extraherad data")
    results_table.add_column("Företag", style="cyan")
    results_table.add_column("Org.nummer", style="yellow")
    results_table.add_column("Email", style="green")
    results_table.add_column("Telefon", style="blue")
    results_table.add_column("Konfidens", style="magenta")
    
    for result in results[:10]:  # Visa max 10 i tabellen
        company_name = result.company_name or "N/A"
        org_number = result.org_number or "N/A"
        email = result.email or "N/A"
        phone = result.phone or "N/A"
        confidence = f"{result.extraction_confidence:.2f}" if result.extraction_confidence else "N/A"
        
        # Trunkera långa fält
        if len(company_name) > 30:
            company_name = company_name[:27] + "..."
        if len(email) > 25:
            email = email[:22] + "..."
        
        results_table.add_row(company_name, org_number, email, phone, confidence)
    
    console.print(results_table)
    
    if len(results) > 10:
        console.print(f"... och {len(results) - 10} till")


if __name__ == "__main__":
    app()
