import os
from typing import List, Optional, Dict, Any
from datetime import datetime
from supabase import create_client, Client
from dotenv import load_dotenv
from ..models.company import CompanyData, CrawlStatus

load_dotenv()


class SupabaseManager:
    """Hanterar Supabase-databasoperationer för crawl-resultat"""
    
    def __init__(self):
        self.supabase_url: str = os.getenv("SUPABASE_URL", "")
        self.supabase_key: str = os.getenv("SUPABASE_KEY", "")
        
        if not self.supabase_url or not self.supabase_key:
            raise ValueError("SUPABASE_URL och SUPABASE_KEY måste vara satta i .env filen")
        
        self.client: Client = create_client(self.supabase_url, self.supabase_key)
        self.table_name = "company_data"
    
    async def initialize_table(self) -> bool:
        """Skapa tabell om den inte finns"""
        try:
            # Kontrollera om tabellen finns
            response = self.client.table(self.table_name).select("id").limit(1).execute()
            
            if response.data:
                return True
            
            # Skapa tabell med SQL (om behövs)
            create_table_sql = f"""
            CREATE TABLE IF NOT EXISTS {self.table_name} (
                id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
                url TEXT NOT NULL,
                company_name TEXT,
                org_number TEXT,
                email TEXT,
                phone TEXT,
                address TEXT,
                postal_code TEXT,
                city TEXT,
                website TEXT,
                crawled_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
                status TEXT DEFAULT 'completed',
                raw_html_hash TEXT,
                extraction_confidence REAL,
                created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
                updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
                UNIQUE(url)
            );
            
            CREATE INDEX IF NOT EXISTS idx_{self.table_name}_url ON {self.table_name}(url);
            CREATE INDEX IF NOT EXISTS idx_{self.table_name}_org_number ON {self.table_name}(org_number);
            CREATE INDEX IF NOT EXISTS idx_{self.table_name}_crawled_at ON {self.table_name}(crawled_at);
            """
            
            # Not: Denna SQL behöver köras manuellt i Supabase Dashboard
            # eller via RPC. Här för dokumentation.
            
            return True
            
        except Exception as e:
            print(f"Error initializing table: {e}")
            return False
    
    async def upsert_company_data(self, data: CompanyData) -> Optional[Dict[str, Any]]:
        """Spara eller uppdatera företagsdata (upsert baserat på URL)"""
        try:
            # Ta bort fält som inte ska sparas i databasen
            db_data = {
                'url': str(data.url),
                'company_name': data.company_name,
                'org_number': data.org_number,
                'email': data.email,
                'phone': data.phone,
                'address': data.address,
                'postal_code': data.postal_code,
                'city': data.city,
                'website': str(data.website) if data.website else None,
                'crawled_at': data.crawled_at.isoformat(),
                'status': data.status.value,
                'raw_html_hash': data.raw_html_hash,
                'extraction_confidence': data.extraction_confidence,
                'updated_at': datetime.now().isoformat()
            }
            
            # Försök upsert (uppdatera om URL finns, annars insert)
            response = (
                self.client
                .table(self.table_name)
                .upsert(db_data, on_conflict='url')
                .execute()
            )
            
            if response.data:
                return response.data[0]
            else:
                print(f"No data returned from upsert: {response}")
                return None
                
        except Exception as e:
            print(f"Error upserting company data: {e}")
            return None
    
    async def batch_upsert(self, company_data_list: List[CompanyData]) -> List[Dict[str, Any]]:
        """Batch upsert för flera företag"""
        results = []
        
        for data in company_data_list:
            result = await self.upsert_company_data(data)
            if result:
                results.append(result)
        
        return results
    
    async def get_company_by_url(self, url: str) -> Optional[Dict[str, Any]]:
        """Hämta företag baserat på URL"""
        try:
            response = self.client.table(self.table_name).select("*").eq("url", url).execute()
            
            if response.data:
                return response.data[0]
            return None
            
        except Exception as e:
            print(f"Error getting company by URL: {e}")
            return None
    
    async def get_companies_by_org_number(self, org_number: str) -> List[Dict[str, Any]]:
        """Hämta företag baserat på organisationsnummer"""
        try:
            response = self.client.table(self.table_name).select("*").eq("org_number", org_number).execute()
            
            return response.data or []
            
        except Exception as e:
            print(f"Error getting companies by org number: {e}")
            return []
    
    async def get_recent_crawls(self, limit: int = 100) -> List[Dict[str, Any]]:
        """Hämta senaste crawl-resultat"""
        try:
            response = (self.client.table(self.table_name)
                       .select("*")
                       .order("crawled_at", desc=True)
                       .limit(limit)
                       .execute())
            
            return response.data or []
            
        except Exception as e:
            print(f"Error getting recent crawls: {e}")
            return []
    
    async def get_statistics(self) -> Dict[str, Any]:
        """Hämta statistik över crawl-resultat"""
        try:
            # Total antal
            total_response = self.client.table(self.table_name).select("id", count="exact").execute()
            total_count = total_response.count or 0
            
            # Lyckade crawls
            successful_response = (self.client.table(self.table_name)
                                  .select("id", count="exact")
                                  .eq("status", "completed")
                                  .execute())
            successful_count = successful_response.count or 0
            
            # Misslyckade crawls
            failed_response = (self.client.table(self.table_name)
                              .select("id", count="exact")
                              .eq("status", "failed")
                              .execute())
            failed_count = failed_response.count or 0
            
            # Medel extraktionskonfidens
            confidence_response = (self.client.table(self.table_name)
                                  .select("extraction_confidence")
                                  .not_("extraction_confidence", "is", "null")
                                  .execute())
            
            confidences = [row["extraction_confidence"] for row in confidence_response.data or []]
            avg_confidence = sum(confidences) / len(confidences) if confidences else 0.0
            
            # Unika domäner
            urls_response = self.client.table(self.table_name).select("url").execute()
            domains = set()
            for row in urls_response.data or []:
                try:
                    from urllib.parse import urlparse
                    domain = urlparse(row["url"]).netloc
                    domains.add(domain)
                except:
                    pass
            
            return {
                'total_urls': total_count,
                'successful_crawls': successful_count,
                'failed_crawls': failed_count,
                'success_rate': (successful_count / total_count * 100) if total_count > 0 else 0,
                'average_confidence': avg_confidence,
                'unique_domains': len(domains),
                'last_updated': datetime.now().isoformat()
            }
            
        except Exception as e:
            print(f"Error getting statistics: {e}")
            return {}
    
    async def delete_by_url(self, url: str) -> bool:
        """Radera företag baserat på URL"""
        try:
            response = self.client.table(self.table_name).delete().eq("url", url).execute()
            return len(response.data or []) > 0
            
        except Exception as e:
            print(f"Error deleting by URL: {e}")
            return False
    
    async def search_companies(self, query: str, limit: int = 50) -> List[Dict[str, Any]]:
        """Sök företag baserat på namn eller annan data"""
        try:
            # Använd text search på company_name och andra fält
            response = (self.client.table(self.table_name)
                       .select("*")
                       .or_(f"company_name.ilike.%{query}%,email.ilike.%{query}%,org_number.ilike.%{query}%")
                       .limit(limit)
                       .execute())
            
            return response.data or []
            
        except Exception as e:
            print(f"Error searching companies: {e}")
            return []
    
    async def export_to_csv_format(self) -> List[Dict[str, Any]]:
        """Exportera data i CSV-format"""
        try:
            response = self.client.table(self.table_name).select("*").order("crawled_at", desc=True).execute()
            
            # Konvertera till platt format för CSV
            csv_data = []
            for row in response.data or []:
                csv_row = {
                    'url': row.get('url'),
                    'company_name': row.get('company_name'),
                    'org_number': row.get('org_number'),
                    'email': row.get('email'),
                    'phone': row.get('phone'),
                    'address': row.get('address'),
                    'postal_code': row.get('postal_code'),
                    'city': row.get('city'),
                    'website': row.get('website'),
                    'crawled_at': row.get('crawled_at'),
                    'status': row.get('status'),
                    'extraction_confidence': row.get('extraction_confidence')
                }
                csv_data.append(csv_row)
            
            return csv_data
            
        except Exception as e:
            print(f"Error exporting to CSV format: {e}")
            return []
