#!/usr/bin/env python3
"""
Website Color and Font Analyzer

This script analyzes websites to extract primary and secondary colors, fonts,
and color palettes. It provides detailed analysis of typography and design
elements for web design research and inspiration.

Author: AI Assistant
Version: 1.0.0
"""

import os
import sys
import argparse
import json
import logging
import requests
from pathlib import Path
from typing import List, Dict, Any, Optional, Tuple, Set
from urllib.parse import urljoin, urlparse
import re
from datetime import datetime
import hashlib
import time
from collections import Counter, defaultdict
import colorsys

# Web scraping libraries
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from bs4 import BeautifulSoup
import css_parser
from PIL import Image, ImageDraw
import io
import base64

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class ColorAnalyzer:
    """Color analysis utilities"""
    
    @staticmethod
    def hex_to_rgb(hex_color: str) -> Tuple[int, int, int]:
        """Convert hex color to RGB tuple"""
        hex_color = hex_color.lstrip('#')
        if len(hex_color) == 3:
            hex_color = ''.join([c*2 for c in hex_color])
        try:
            return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
        except ValueError:
            return (0, 0, 0)
    
    @staticmethod
    def rgb_to_hex(rgb: Tuple[int, int, int]) -> str:
        """Convert RGB tuple to hex color"""
        return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"
    
    @staticmethod
    def rgb_to_hsl(rgb: Tuple[int, int, int]) -> Tuple[float, float, float]:
        """Convert RGB to HSL"""
        r, g, b = [x/255.0 for x in rgb]
        h, l, s = colorsys.rgb_to_hls(r, g, b)
        return (h*360, s*100, l*100)
    
    @staticmethod
    def get_color_luminance(rgb: Tuple[int, int, int]) -> float:
        """Calculate color luminance for contrast analysis"""
        r, g, b = [x/255.0 for x in rgb]
        # Apply gamma correction
        def gamma_correct(c):
            return c/12.92 if c <= 0.03928 else ((c + 0.055)/1.055) ** 2.4
        
        r, g, b = map(gamma_correct, [r, g, b])
        return 0.2126 * r + 0.7152 * g + 0.0722 * b
    
    @staticmethod
    def calculate_contrast_ratio(color1: Tuple[int, int, int], color2: Tuple[int, int, int]) -> float:
        """Calculate WCAG contrast ratio between two colors"""
        l1 = ColorAnalyzer.get_color_luminance(color1)
        l2 = ColorAnalyzer.get_color_luminance(color2)
        lighter = max(l1, l2)
        darker = min(l1, l2)
        return (lighter + 0.05) / (darker + 0.05)
    
    @staticmethod
    def is_color_dark(rgb: Tuple[int, int, int]) -> bool:
        """Determine if color is dark or light"""
        return ColorAnalyzer.get_color_luminance(rgb) < 0.5
    
    @staticmethod
    def group_similar_colors(colors: List[str], threshold: float = 30.0) -> Dict[str, List[str]]:
        """Group similar colors together"""
        groups = {}
        processed = set()
        
        for color in colors:
            if color in processed:
                continue
                
            rgb1 = ColorAnalyzer.hex_to_rgb(color)
            hsl1 = ColorAnalyzer.rgb_to_hsl(rgb1)
            
            group_key = color
            groups[group_key] = [color]
            processed.add(color)
            
            # Find similar colors
            for other_color in colors:
                if other_color in processed:
                    continue
                    
                rgb2 = ColorAnalyzer.hex_to_rgb(other_color)
                hsl2 = ColorAnalyzer.rgb_to_hsl(rgb2)
                
                # Calculate color distance in HSL space
                h_diff = min(abs(hsl1[0] - hsl2[0]), 360 - abs(hsl1[0] - hsl2[0]))
                s_diff = abs(hsl1[1] - hsl2[1])
                l_diff = abs(hsl1[2] - hsl2[2])
                
                distance = (h_diff * 2 + s_diff + l_diff) / 4
                
                if distance < threshold:
                    groups[group_key].append(other_color)
                    processed.add(other_color)
        
        return groups

class WebsiteAnalyzer:
    """Main class for website color and font analysis"""
    
    def __init__(self, output_dir: str = "website_analysis", headless: bool = True):
        self.output_dir = Path(output_dir)
        self.headless = headless
        self.driver = None
        self.session = requests.Session()
        
        # Setup user agent
        self.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        self.session.headers.update({'User-Agent': self.user_agent})
        
        # Setup directories
        self.setup_directories()
        
        # Color and font collections
        self.colors = []
        self.fonts = []
        self.css_properties = {}
        
    def setup_directories(self):
        """Create necessary output directories"""
        self.output_dir.mkdir(exist_ok=True)
        
        # Create subdirectories
        subdirs = ['colors', 'fonts', 'palettes', 'screenshots', 'css', 'reports']
        for subdir in subdirs:
            (self.output_dir / subdir).mkdir(exist_ok=True)
            
    def setup_selenium_driver(self):
        """Setup Selenium WebDriver"""
        if self.driver:
            return
            
        try:
            chrome_options = Options()
            if self.headless:
                chrome_options.add_argument("--headless")
            chrome_options.add_argument("--no-sandbox")
            chrome_options.add_argument("--disable-dev-shm-usage")
            chrome_options.add_argument("--disable-gpu")
            chrome_options.add_argument("--window-size=1920,1080")
            chrome_options.add_argument(f"--user-agent={self.user_agent}")
            
            self.driver = webdriver.Chrome(options=chrome_options)
            logger.info("Selenium WebDriver initialized successfully")
        except Exception as e:
            logger.error(f"Failed to setup WebDriver: {e}")
            self.driver = None
            
    def close_driver(self):
        """Close Selenium WebDriver"""
        if self.driver:
            self.driver.quit()
            self.driver = None
            
    def extract_colors_from_css(self, css_text: str) -> List[str]:
        """Extract colors from CSS text"""
        colors = []
        
        # Regex patterns for different color formats
        patterns = [
            r'#([0-9a-fA-F]{3,6})',  # Hex colors
            r'rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)',  # RGB
            r'rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([0-9.]+)\s*\)',  # RGBA
            r'hsl\s*\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)',  # HSL
            r'hsla\s*\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([0-9.]+)\s*\)'  # HSLA
        ]
        
        # Named colors mapping (common ones)
        named_colors = {
            'red': '#ff0000', 'green': '#008000', 'blue': '#0000ff',
            'white': '#ffffff', 'black': '#000000', 'gray': '#808080',
            'grey': '#808080', 'yellow': '#ffff00', 'cyan': '#00ffff',
            'magenta': '#ff00ff', 'orange': '#ffa500', 'pink': '#ffc0cb',
            'purple': '#800080', 'brown': '#a52a2a', 'navy': '#000080',
            'lime': '#00ff00', 'olive': '#808000', 'maroon': '#800000',
            'aqua': '#00ffff', 'teal': '#008080', 'silver': '#c0c0c0',
            'fuchsia': '#ff00ff', 'transparent': 'transparent'
        }
        
        # Find hex colors
        hex_matches = re.findall(patterns[0], css_text, re.IGNORECASE)
        for match in hex_matches:
            color = f"#{match.lower()}"
            if len(match) == 3:
                color = f"#{match[0]*2}{match[1]*2}{match[2]*2}"
            colors.append(color)
            
        # Find RGB colors
        rgb_matches = re.findall(patterns[1], css_text, re.IGNORECASE)
        for r, g, b in rgb_matches:
            try:
                rgb = (int(r), int(g), int(b))
                colors.append(ColorAnalyzer.rgb_to_hex(rgb))
            except ValueError:
                continue
                
        # Find RGBA colors
        rgba_matches = re.findall(patterns[2], css_text, re.IGNORECASE)
        for r, g, b, a in rgba_matches:
            try:
                rgb = (int(r), int(g), int(b))
                colors.append(ColorAnalyzer.rgb_to_hex(rgb))
            except ValueError:
                continue
                
        # Find HSL colors
        hsl_matches = re.findall(patterns[3], css_text, re.IGNORECASE)
        for h, s, l in hsl_matches:
            try:
                # Convert HSL to RGB
                h_norm = int(h) / 360.0
                s_norm = int(s) / 100.0
                l_norm = int(l) / 100.0
                r, g, b = colorsys.hls_to_rgb(h_norm, l_norm, s_norm)
                rgb = (int(r*255), int(g*255), int(b*255))
                colors.append(ColorAnalyzer.rgb_to_hex(rgb))
            except ValueError:
                continue
                
        # Find named colors
        for name, hex_color in named_colors.items():
            if re.search(r'\b' + name + r'\b', css_text, re.IGNORECASE):
                if hex_color != 'transparent':
                    colors.append(hex_color)
                    
        return list(set(colors))  # Remove duplicates
        
    def extract_fonts_from_css(self, css_text: str) -> List[str]:
        """Extract font families from CSS text"""
        fonts = []
        
        # Find font-family declarations
        font_pattern = r'font-family\s*:\s*([^;}]+)'
        font_matches = re.findall(font_pattern, css_text, re.IGNORECASE)
        
        for match in font_matches:
            # Clean up and split font families
            font_list = [f.strip().strip('\'"') for f in match.split(',')]
            fonts.extend(font_list)
            
        # Find @import font declarations
        import_pattern = r'@import\s+[\'"]([^\'";]+)[\'"]'
        import_matches = re.findall(import_pattern, css_text, re.IGNORECASE)
        
        for match in import_matches:
            if 'fonts.googleapis.com' in match or 'font' in match.lower():
                # Extract font name from Google Fonts URL
                font_name_pattern = r'family=([^&:]+)'
                font_name = re.search(font_name_pattern, match)
                if font_name:
                    fonts.append(font_name.group(1).replace('+', ' '))
                    
        return list(set(fonts))  # Remove duplicates
        
    def analyze_computed_styles(self) -> Dict[str, Any]:
        """Analyze computed styles of elements using Selenium"""
        if not self.driver:
            return {}
            
        style_analysis = {
            'background_colors': [],
            'text_colors': [],
            'border_colors': [],
            'fonts': [],
            'font_sizes': [],
            'element_styles': []
        }
        
        try:
            # Get all visible elements
            elements = self.driver.find_elements(By.CSS_SELECTOR, "*")
            
            for element in elements[:100]:  # Limit to first 100 elements
                try:
                    # Get computed styles
                    bg_color = element.value_of_css_property("background-color")
                    text_color = element.value_of_css_property("color")
                    border_color = element.value_of_css_property("border-color")
                    font_family = element.value_of_css_property("font-family")
                    font_size = element.value_of_css_property("font-size")
                    
                    # Convert colors to hex if they're in rgb format
                    def convert_color(color_str):
                        if color_str.startswith('rgb'):
                            # Extract RGB values
                            rgb_match = re.search(r'(\d+),\s*(\d+),\s*(\d+)', color_str)
                            if rgb_match:
                                r, g, b = map(int, rgb_match.groups())
                                return ColorAnalyzer.rgb_to_hex((r, g, b))
                        return color_str
                    
                    # Process colors
                    if bg_color and bg_color != 'rgba(0, 0, 0, 0)':
                        converted = convert_color(bg_color)
                        if converted.startswith('#'):
                            style_analysis['background_colors'].append(converted)
                            
                    if text_color:
                        converted = convert_color(text_color)
                        if converted.startswith('#'):
                            style_analysis['text_colors'].append(converted)
                            
                    if border_color:
                        converted = convert_color(border_color)
                        if converted.startswith('#'):
                            style_analysis['border_colors'].append(converted)
                            
                    # Process fonts
                    if font_family:
                        # Clean font family string
                        fonts = [f.strip().strip('\'"') for f in font_family.split(',')]
                        style_analysis['fonts'].extend(fonts)
                        
                    if font_size:
                        style_analysis['font_sizes'].append(font_size)
                        
                    # Store element style info
                    element_info = {
                        'tag': element.tag_name,
                        'class': element.get_attribute('class'),
                        'background_color': bg_color,
                        'text_color': text_color,
                        'font_family': font_family,
                        'font_size': font_size
                    }
                    style_analysis['element_styles'].append(element_info)
                    
                except Exception:
                    continue
                    
        except Exception as e:
            logger.warning(f"Error analyzing computed styles: {e}")
            
        return style_analysis
        
    def fetch_external_css(self, base_url: str, css_links: List[str]) -> str:
        """Fetch external CSS files"""
        combined_css = ""
        
        for css_url in css_links:
            try:
                # Make URL absolute
                full_url = urljoin(base_url, css_url)
                
                response = self.session.get(full_url, timeout=10)
                response.raise_for_status()
                
                combined_css += f"\n/* CSS from {full_url} */\n"
                combined_css += response.text
                
            except Exception as e:
                logger.warning(f"Failed to fetch CSS from {css_url}: {e}")
                continue
                
        return combined_css
        
    def take_screenshot(self, url: str, filename: str) -> bool:
        """Take a screenshot of the website"""
        if not self.driver:
            return False
            
        try:
            screenshot_path = self.output_dir / "screenshots" / f"{filename}.png"
            self.driver.save_screenshot(str(screenshot_path))
            logger.info(f"Screenshot saved: {screenshot_path}")
            return True
        except Exception as e:
            logger.error(f"Failed to take screenshot: {e}")
            return False
            
    def generate_color_palette(self, colors: List[str], max_colors: int = 10) -> Dict[str, Any]:
        """Generate a color palette from extracted colors"""
        if not colors:
            return {}
            
        # Count color frequency
        color_counts = Counter(colors)
        
        # Group similar colors
        color_groups = ColorAnalyzer.group_similar_colors(list(color_counts.keys()))
        
        # Calculate group scores (frequency + diversity)
        group_scores = {}
        for representative, group_colors in color_groups.items():
            frequency_score = sum(color_counts[color] for color in group_colors)
            diversity_score = len(group_colors)
            group_scores[representative] = frequency_score + diversity_score
            
        # Select top colors
        top_colors = sorted(group_scores.keys(), key=lambda x: group_scores[x], reverse=True)[:max_colors]
        
        # Analyze color relationships
        palette_analysis = {
            'primary_colors': top_colors[:3],
            'secondary_colors': top_colors[3:6],
            'accent_colors': top_colors[6:],
            'color_harmony': self.analyze_color_harmony(top_colors),
            'accessibility': self.analyze_color_accessibility(top_colors),
            'color_temperature': self.analyze_color_temperature(top_colors)
        }
        
        return palette_analysis
        
    def analyze_color_harmony(self, colors: List[str]) -> Dict[str, Any]:
        """Analyze color harmony and relationships"""
        if len(colors) < 2:
            return {}
            
        harmony_analysis = {
            'complementary_pairs': [],
            'analogous_groups': [],
            'triadic_groups': [],
            'dominant_hue': None
        }
        
        # Convert to HSL for harmony analysis
        hsl_colors = []
        for color in colors:
            rgb = ColorAnalyzer.hex_to_rgb(color)
            hsl = ColorAnalyzer.rgb_to_hsl(rgb)
            hsl_colors.append((color, hsl))
            
        # Find complementary colors (opposite on color wheel)
        for i, (color1, hsl1) in enumerate(hsl_colors):
            for color2, hsl2 in hsl_colors[i+1:]:
                hue_diff = abs(hsl1[0] - hsl2[0])
                if 150 <= hue_diff <= 210:  # Approximately opposite
                    harmony_analysis['complementary_pairs'].append([color1, color2])
                    
        # Find dominant hue
        hues = [hsl[1][0] for hsl in hsl_colors if hsl[1][1] > 10]  # Exclude near-grays
        if hues:
            hue_ranges = [(h//30) * 30 for h in hues]  # Group into 30-degree ranges
            dominant_hue_range = Counter(hue_ranges).most_common(1)[0][0]
            harmony_analysis['dominant_hue'] = f"{dominant_hue_range}-{dominant_hue_range+30} degrees"
            
        return harmony_analysis
        
    def analyze_color_accessibility(self, colors: List[str]) -> Dict[str, Any]:
        """Analyze color accessibility and contrast"""
        accessibility_analysis = {
            'high_contrast_pairs': [],
            'low_contrast_pairs': [],
            'wcag_aa_compliant': [],
            'wcag_aaa_compliant': []
        }
        
        # Check all color combinations
        for i, color1 in enumerate(colors):
            rgb1 = ColorAnalyzer.hex_to_rgb(color1)
            for color2 in colors[i+1:]:
                rgb2 = ColorAnalyzer.hex_to_rgb(color2)
                
                contrast_ratio = ColorAnalyzer.calculate_contrast_ratio(rgb1, rgb2)
                
                pair_info = {
                    'color1': color1,
                    'color2': color2,
                    'contrast_ratio': round(contrast_ratio, 2)
                }
                
                if contrast_ratio >= 7.0:
                    accessibility_analysis['wcag_aaa_compliant'].append(pair_info)
                elif contrast_ratio >= 4.5:
                    accessibility_analysis['wcag_aa_compliant'].append(pair_info)
                    
                if contrast_ratio >= 3.0:
                    accessibility_analysis['high_contrast_pairs'].append(pair_info)
                else:
                    accessibility_analysis['low_contrast_pairs'].append(pair_info)
                    
        return accessibility_analysis
        
    def analyze_color_temperature(self, colors: List[str]) -> Dict[str, Any]:
        """Analyze color temperature (warm/cool)"""
        temperature_analysis = {
            'warm_colors': [],
            'cool_colors': [],
            'neutral_colors': [],
            'overall_temperature': 'neutral'
        }
        
        warm_count = 0
        cool_count = 0
        
        for color in colors:
            rgb = ColorAnalyzer.hex_to_rgb(color)
            hsl = ColorAnalyzer.rgb_to_hsl(rgb)
            
            # Classify based on hue
            hue = hsl[0]
            saturation = hsl[1]
            
            if saturation < 10:  # Near-gray colors
                temperature_analysis['neutral_colors'].append(color)
            elif 0 <= hue <= 60 or 300 <= hue <= 360:  # Red to yellow range
                temperature_analysis['warm_colors'].append(color)
                warm_count += 1
            elif 120 <= hue <= 240:  # Green to blue range
                temperature_analysis['cool_colors'].append(color)
                cool_count += 1
            else:  # Transition areas
                temperature_analysis['neutral_colors'].append(color)
                
        # Determine overall temperature
        if warm_count > cool_count * 1.5:
            temperature_analysis['overall_temperature'] = 'warm'
        elif cool_count > warm_count * 1.5:
            temperature_analysis['overall_temperature'] = 'cool'
        else:
            temperature_analysis['overall_temperature'] = 'neutral'
            
        return temperature_analysis
        
    def analyze_typography(self, fonts: List[str]) -> Dict[str, Any]:
        """Analyze typography and font usage"""
        font_analysis = {
            'font_families': [],
            'font_categories': {},
            'web_safe_fonts': [],
            'custom_fonts': [],
            'font_stacks': []
        }
        
        # Common web-safe fonts
        web_safe = [
            'Arial', 'Helvetica', 'Times New Roman', 'Georgia', 'Verdana',
            'Courier New', 'Times', 'serif', 'sans-serif', 'monospace',
            'Trebuchet MS', 'Tahoma', 'Impact', 'Comic Sans MS'
        ]
        
        # Font categories
        serif_fonts = ['Times New Roman', 'Georgia', 'Times', 'serif', 'Book Antiqua', 'Palatino']
        sans_serif_fonts = ['Arial', 'Helvetica', 'Verdana', 'sans-serif', 'Trebuchet MS', 'Tahoma']
        monospace_fonts = ['Courier New', 'monospace', 'Monaco', 'Consolas']
        
        # Process fonts
        processed_fonts = []
        for font in fonts:
            font_clean = font.strip().strip('\'"')
            if font_clean and font_clean not in processed_fonts:
                processed_fonts.append(font_clean)
                
        font_analysis['font_families'] = processed_fonts
        
        # Categorize fonts
        categories = {'serif': 0, 'sans-serif': 0, 'monospace': 0, 'display': 0}
        
        for font in processed_fonts:
            font_lower = font.lower()
            if any(sf.lower() in font_lower for sf in serif_fonts):
                categories['serif'] += 1
                font_analysis.setdefault('serif_fonts', []).append(font)
            elif any(ssf.lower() in font_lower for ssf in sans_serif_fonts):
                categories['sans-serif'] += 1
                font_analysis.setdefault('sans_serif_fonts', []).append(font)
            elif any(mf.lower() in font_lower for mf in monospace_fonts):
                categories['monospace'] += 1
                font_analysis.setdefault('monospace_fonts', []).append(font)
            else:
                categories['display'] += 1
                font_analysis.setdefault('display_fonts', []).append(font)
                
            # Check if web-safe
            if any(ws.lower() in font_lower for ws in web_safe):
                font_analysis['web_safe_fonts'].append(font)
            else:
                font_analysis['custom_fonts'].append(font)
                
        font_analysis['font_categories'] = categories
        
        return font_analysis
        
    def create_color_swatch(self, colors: List[str], filename: str) -> bool:
        """Create a visual color swatch"""
        if not colors:
            return False
            
        try:
            # Create image
            swatch_width = min(len(colors) * 100, 1000)
            swatch_height = 200
            
            img = Image.new('RGB', (swatch_width, swatch_height), 'white')
            draw = ImageDraw.Draw(img)
            
            # Draw color swatches
            for i, color in enumerate(colors[:10]):  # Limit to 10 colors
                x = i * 100
                try:
                    draw.rectangle([x, 0, x + 100, 150], fill=color)
                    # Add color text
                    draw.text((x + 10, 160), color, fill='black')
                except Exception:
                    continue
                    
            # Save image
            swatch_path = self.output_dir / "palettes" / f"{filename}_swatch.png"
            img.save(swatch_path)
            logger.info(f"Color swatch saved: {swatch_path}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to create color swatch: {e}")
            return False
            
    def analyze_website(self, url: str) -> Dict[str, Any]:
        """Main method to analyze a website"""
        logger.info(f"Analyzing website: {url}")
        
        # Setup Selenium driver
        self.setup_selenium_driver()
        if not self.driver:
            return {'success': False, 'error': 'WebDriver not available'}
            
        try:
            # Navigate to website
            self.driver.get(url)
            time.sleep(3)  # Wait for page load
            
            # Get page source
            page_source = self.driver.page_source
            soup = BeautifulSoup(page_source, 'html.parser')
            
            # Extract CSS
            inline_css = ""
            external_css_links = []
            
            # Get inline styles and style tags
            for style_tag in soup.find_all('style'):
                if style_tag.string:
                    inline_css += style_tag.string + "\n"
                    
            # Get external CSS links
            for link in soup.find_all('link', rel='stylesheet'):
                href = link.get('href')
                if href:
                    external_css_links.append(href)
                    
            # Fetch external CSS
            external_css = self.fetch_external_css(url, external_css_links)
            combined_css = inline_css + external_css
            
            # Analyze computed styles
            computed_styles = self.analyze_computed_styles()
            
            # Extract colors and fonts
            css_colors = self.extract_colors_from_css(combined_css)
            css_fonts = self.extract_fonts_from_css(combined_css)
            
            # Combine with computed styles
            all_colors = list(set(css_colors + 
                                computed_styles.get('background_colors', []) +
                                computed_styles.get('text_colors', []) +
                                computed_styles.get('border_colors', [])))
            
            all_fonts = list(set(css_fonts + computed_styles.get('fonts', [])))
            
            # Generate analysis
            color_palette = self.generate_color_palette(all_colors)
            typography_analysis = self.analyze_typography(all_fonts)
            
            # Create visual assets
            domain = urlparse(url).netloc.replace('.', '_')
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            base_filename = f"{domain}_{timestamp}"
            
            # Take screenshot
            screenshot_taken = self.take_screenshot(url, base_filename)
            
            # Create color swatch
            swatch_created = self.create_color_swatch(all_colors[:10], base_filename)
            
            # Save CSS
            css_file = self.output_dir / "css" / f"{base_filename}.css"
            with open(css_file, 'w', encoding='utf-8') as f:
                f.write(combined_css)
                
            # Compile results
            analysis_result = {
                'success': True,
                'url': url,
                'domain': domain,
                'analysis_date': datetime.now().isoformat(),
                'colors': {
                    'total_found': len(all_colors),
                    'unique_colors': all_colors,
                    'palette_analysis': color_palette
                },
                'typography': {
                    'total_fonts': len(all_fonts),
                    'font_families': all_fonts,
                    'analysis': typography_analysis
                },
                'technical_info': {
                    'css_sources': {
                        'inline_styles': len(soup.find_all('style')),
                        'external_stylesheets': len(external_css_links),
                        'total_css_size': len(combined_css)
                    },
                    'computed_styles': computed_styles
                },
                'files_created': {
                    'screenshot': screenshot_taken,
                    'color_swatch': swatch_created,
                    'css_file': str(css_file)
                }
            }
            
            # Save analysis report
            report_file = self.output_dir / "reports" / f"{base_filename}_analysis.json"
            with open(report_file, 'w', encoding='utf-8') as f:
                json.dump(analysis_result, f, indent=2, ensure_ascii=False)
                
            logger.info(f"Analysis completed successfully")
            return analysis_result
            
        except Exception as e:
            logger.error(f"Error analyzing website: {e}")
            return {'success': False, 'error': str(e)}
            
    def get_analysis_stats(self) -> Dict[str, Any]:
        """Get statistics about previous analyses"""
        stats = {
            'total_analyses': 0,
            'websites_analyzed': [],
            'color_statistics': {},
            'font_statistics': {},
            'file_counts': {}
        }
        
        try:
            reports_dir = self.output_dir / "reports"
            if reports_dir.exists():
                report_files = list(reports_dir.glob("*_analysis.json"))
                stats['total_analyses'] = len(report_files)
                
                all_colors = []
                all_fonts = []
                
                for report_file in report_files:
                    try:
                        with open(report_file, 'r', encoding='utf-8') as f:
                            data = json.load(f)
                            
                        stats['websites_analyzed'].append({
                            'url': data.get('url'),
                            'domain': data.get('domain'),
                            'date': data.get('analysis_date')
                        })
                        
                        # Collect colors and fonts
                        colors = data.get('colors', {}).get('unique_colors', [])
                        fonts = data.get('typography', {}).get('font_families', [])
                        
                        all_colors.extend(colors)
                        all_fonts.extend(fonts)
                        
                    except Exception:
                        continue
                        
                # Calculate statistics
                stats['color_statistics'] = {
                    'total_colors_found': len(all_colors),
                    'unique_colors': len(set(all_colors)),
                    'most_common_colors': dict(Counter(all_colors).most_common(10))
                }
                
                stats['font_statistics'] = {
                    'total_fonts_found': len(all_fonts),
                    'unique_fonts': len(set(all_fonts)),
                    'most_common_fonts': dict(Counter(all_fonts).most_common(10))
                }
                
            # Count files
            for subdir in ['screenshots', 'palettes', 'css', 'reports']:
                subdir_path = self.output_dir / subdir
                if subdir_path.exists():
                    stats['file_counts'][subdir] = len(list(subdir_path.glob("*")))
                    
        except Exception as e:
            logger.error(f"Error calculating stats: {e}")
            
        return stats

def main():
    """Command-line interface"""
    parser = argparse.ArgumentParser(description="Website Color and Font Analyzer")
    parser.add_argument("action", choices=["analyze", "stats", "palette"], 
                       help="Action to perform")
    parser.add_argument("url", nargs="?", help="Website URL to analyze")
    parser.add_argument("-o", "--output", default="website_analysis", 
                       help="Output directory")
    parser.add_argument("--headless", action="store_true", 
                       help="Run browser in headless mode")
    parser.add_argument("--max-colors", type=int, default=20,
                       help="Maximum colors to analyze")
    parser.add_argument("-v", "--verbose", action="store_true", 
                       help="Verbose logging")
    
    args = parser.parse_args()
    
    if args.verbose:
        logging.getLogger().setLevel(logging.DEBUG)
        
    if args.action in ["analyze", "palette"] and not args.url:
        print("❌ URL is required for this action")
        print("Usage examples:")
        print(f"  python {sys.argv[0]} analyze https://example.com")
        print(f"  python {sys.argv[0]} palette https://example.com")
        return 1
        
    # Initialize analyzer
    analyzer = WebsiteAnalyzer(output_dir=args.output, headless=args.headless)
    
    try:
        if args.action == "analyze":
            result = analyzer.analyze_website(args.url)
            
            if result['success']:
                print(f"✅ Successfully analyzed {args.url}")
                print(f"🎨 Found {result['colors']['total_found']} colors")
                print(f"🔤 Found {result['typography']['total_fonts']} fonts")
                print(f"📁 Output directory: {args.output}")
                
                # Display key findings
                colors = result['colors']['unique_colors'][:10]
                fonts = result['typography']['font_families'][:5]
                
                print(f"\n🎨 Top Colors:")
                for color in colors:
                    print(f"  {color}")
                    
                print(f"\n🔤 Top Fonts:")
                for font in fonts:
                    print(f"  {font}")
                    
            else:
                print(f"❌ Failed to analyze: {result.get('error', 'Unknown error')}")
                return 1
                
        elif args.action == "palette":
            result = analyzer.analyze_website(args.url)
            
            if result['success']:
                palette = result['colors']['palette_analysis']
                print(f"🎨 Color Palette for {args.url}")
                print("=" * 50)
                
                print("Primary Colors:")
                for color in palette.get('primary_colors', []):
                    print(f"  {color}")
                    
                print("\nSecondary Colors:")
                for color in palette.get('secondary_colors', []):
                    print(f"  {color}")
                    
                print("\nAccent Colors:")
                for color in palette.get('accent_colors', []):
                    print(f"  {color}")
                    
                # Color harmony info
                harmony = palette.get('color_harmony', {})
                if harmony.get('dominant_hue'):
                    print(f"\nDominant Hue: {harmony['dominant_hue']}")
                    
                # Temperature analysis
                temp = palette.get('color_temperature', {})
                print(f"Color Temperature: {temp.get('overall_temperature', 'unknown')}")
                
            else:
                print(f"❌ Failed to analyze: {result.get('error', 'Unknown error')}")
                return 1
                
        elif args.action == "stats":
            stats = analyzer.get_analysis_stats()
            print("\n📊 Website Analysis Statistics:")
            print("=" * 40)
            print(f"Total Analyses: {stats['total_analyses']}")
            
            if stats['websites_analyzed']:
                print(f"\nRecent Websites:")
                for site in stats['websites_analyzed'][-5:]:
                    print(f"  {site['domain']} - {site['date'][:10]}")
                    
            if stats['color_statistics']:
                print(f"\nColor Statistics:")
                print(f"  Total Colors Found: {stats['color_statistics']['total_colors_found']}")
                print(f"  Unique Colors: {stats['color_statistics']['unique_colors']}")
                
            if stats['font_statistics']:
                print(f"\nFont Statistics:")
                print(f"  Total Fonts Found: {stats['font_statistics']['total_fonts_found']}")
                print(f"  Unique Fonts: {stats['font_statistics']['unique_fonts']}")
                
            return 0
            
    except KeyboardInterrupt:
        print("\n⚠️ Analysis interrupted by user")
        return 1
    except Exception as e:
        print(f"❌ Error: {e}")
        return 1
    finally:
        # Cleanup
        analyzer.close_driver()
        
    return 0

if __name__ == "__main__":
    exit(main()) 