# 4_code_generator.py

import os
import json
import argparse
from pathlib import Path
from typing import Dict, List
import re
import time
from datetime import datetime

from dotenv import load_dotenv
import vertexai
from vertexai.generative_models import GenerativeModel, GenerationResponse, GenerationConfig

# --- Model & Pricing Configuration ---
MODELS_CONFIG = [
    {
        "name": "Gemini 2.5 Pro (GA)",
        "model_id": "gemini-2.5-pro",
        "location": "us-east1",
        "pricing": { "input": 1.25 / 1_000_000, "output": 10.00 / 1_000_000 }
    },
    {
        "name": "Gemini 2.5 Flash (GA)",
        "model_id": "gemini-2.5-flash",
        "location": "us-east1",
        "pricing": { "input": 0.30 / 1_000_000, "output": 2.50 / 1_000_000 }
    },
    {
        "name": "Gemini 2.5 Flash Lite (Preview)",
        "model_id": "gemini-2.5-flash-lite",
        "location": "global",
        "pricing": { "input": 0.10 / 1_000_000, "output": 0.40 / 1_000_000 }
    }
]

DEFAULT_MODEL_INDEX = 0  # Gemini 2.5 Pro for code generation

def print_timestamp():
    """Get current time formatted for progress reporting."""
    return datetime.now().strftime("%H:%M:%S")

def setup_gcp_credentials():
    """Auto-setup GCP credentials from default location or environment."""
    import os
    import json
    from pathlib import Path
    
    # Default paths to check for credentials
    # Default paths to check for credentials (multiple structures)
    credential_paths = [
        Path("../data/credentials/gcp_key.json"),           # Development: from dashboard/scripts
        Path("./data/credentials/gcp_key.json"),            # Alternative: from project root
        Path("../dashboard/data/credentials/gcp_key.json"), # Production with dashboard: from /test/scripts
        Path("dashboard/data/credentials/gcp_key.json"),    # Alternative production with dashboard
        Path("data/credentials/gcp_key.json")               # Fallback
    ]
    
    # Check if GOOGLE_APPLICATION_CREDENTIALS is already set
    if not os.getenv("GOOGLE_APPLICATION_CREDENTIALS"):
        # Try to find credentials file in order of preference
        key_path = None
        for path in credential_paths:
            if path.exists():
                key_path = path
                break
        
        if key_path:
            os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = str(key_path.absolute())
            print(f"🔑 Auto-detected GCP key: {key_path}")
    
    # Check if GCLOUD_PROJECT is already set
    if not os.getenv("GCLOUD_PROJECT"):
        # Try to read project ID from the key file
        creds_path = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
        if creds_path and Path(creds_path).exists():
            try:
                with open(creds_path, 'r') as f:
                    key_data = json.load(f)
                    project_id = key_data.get("project_id")
                    if project_id:
                        os.environ["GCLOUD_PROJECT"] = project_id
                        print(f"🌐 Auto-detected GCP project: {project_id}")
            except Exception as e:
                print(f"⚠️ Could not read project ID from key file: {e}")

def get_gemini_model(model_index: int):
    """Initialize and return Gemini model."""
    # Auto-setup credentials if not already configured
    setup_gcp_credentials()
    
    active_model_config = MODELS_CONFIG[model_index]
    gcloud_project = os.getenv("GCLOUD_PROJECT")
    if not gcloud_project:
        raise ValueError("GCLOUD_PROJECT not found. Please check your GCP setup.")
    
    print(f"   🔗 Connecting to project: {gcloud_project}")
    vertexai.init(project=gcloud_project, location=active_model_config["location"])
    
    model = GenerativeModel(
        active_model_config["model_id"],
        generation_config=GenerationConfig(temperature=0.8)
    )
    return model

def print_usage_and_cost(response: GenerationResponse, model_index: int, stage_name: str) -> dict:
    """Calculate and print API usage costs."""
    usage_data = {"cost": 0, "tokens": 0}
    try:
        active_model_config = MODELS_CONFIG[model_index]
        usage = response.usage_metadata
        pricing = active_model_config["pricing"]
        input_tokens = usage.prompt_token_count
        output_tokens = usage.candidates_token_count
        usage_data["cost"] = (input_tokens * pricing["input"]) + (output_tokens * pricing["output"])
        usage_data["tokens"] = input_tokens + output_tokens
        print(f"   💰 Usage for {stage_name}: {(usage_data['tokens']):,} tokens, cost: ${usage_data['cost']:.6f}")
        print(f"   📊 Breakdown: {input_tokens:,} input + {output_tokens:,} output tokens")
    except Exception: 
        pass
    return usage_data

def load_project_data(site_dir: Path) -> tuple[Dict, Dict]:
    """Load designs and site brief from previous scripts."""
    print(f"   [{print_timestamp()}] Loading project data files...")
    
    designs_path = site_dir / "designs.json"
    brief_path = site_dir / "site_brief.json"
    
    print(f"   📁 Checking for: {designs_path.name}")
    if not designs_path.exists():
        raise FileNotFoundError(f"Designs file not found at {designs_path}")
    
    print(f"   📁 Checking for: {brief_path.name}")
    if not brief_path.exists():
        raise FileNotFoundError(f"Site brief not found at {brief_path}")
    
    print(f"   📖 Reading designs specification...")
    with open(designs_path, 'r', encoding='utf-8') as f:
        designs_data = json.load(f)
    
    print(f"   📖 Reading site content...")
    with open(brief_path, 'r', encoding='utf-8') as f:
        site_brief = json.load(f)
    
    print(f"   ✅ Project data loaded successfully!")
    return designs_data, site_brief

def prepare_content_for_generation(site_brief: Dict) -> str:
    """Prepare comprehensive content summary for code generation including images."""
    print(f"   [{print_timestamp()}] Preparing content for AI generation...")
    
    content_parts = []
    
    # Brand and navigation
    brand_profile = site_brief.get('brand_profile', {})
    navigation_links = site_brief.get('navigation_links', [])
    
    print(f"   🏷️  Processing brand profile...")
    content_parts.append("=== BRAND PROFILE ===")
    content_parts.append(json.dumps(brand_profile, indent=2))
    
    print(f"   🧭 Processing navigation structure ({len(navigation_links)} links)...")
    content_parts.append("\n=== NAVIGATION STRUCTURE ===")
    content_parts.append(json.dumps(navigation_links, indent=2))
    
    # Site pages with content (preserving image placeholders)
    site_pages = site_brief.get('site_pages', [])
    print(f"   📄 Processing {len(site_pages)} pages of content...")
    
    # Filter out legal/privacy content
    excluded_keywords = [
        'privacy policy', 'terms of service', 'cookie policy', 'legal notice',
        'disclaimer', 'terms and conditions', 'privacy notice', 'gdpr',
        'data protection', 'cookie notice', 'legal disclaimer', 'terms of use'
    ]
    
    filtered_pages = []
    excluded_count = 0
    
    for page in site_pages:
        page_title = page.get('title', '').lower()
        page_url = page.get('url', '').lower()
        page_key = page.get('page_key', '').lower()
        
        # Check if this page should be excluded
        is_excluded = any(keyword in page_title or keyword in page_url or keyword in page_key 
                         for keyword in excluded_keywords)
        
        if is_excluded:
            excluded_count += 1
            print(f"   🚫 Excluding legal/privacy page: {page.get('title', 'Untitled')}")
        else:
            filtered_pages.append(page)
    
    if excluded_count > 0:
        print(f"   ✅ Filtered out {excluded_count} legal/privacy pages")
    
    content_parts.append(f"\n=== WEBSITE CONTENT ({len(filtered_pages)} pages) ===")
    content_parts.append("NOTE: [image: filename.ext] placeholders show where images should be placed in the content.")
    content_parts.append("IMPORTANT: Legal pages (privacy policy, terms) have been excluded - focus on main business content only.")
    
    # Track all images for reference
    all_images = set()
    
    for i, page in enumerate(filtered_pages, 1):
        print(f"   📝 Processing page {i}/{len(filtered_pages)}: {page.get('title', 'Untitled')}")
        
        page_key = page.get('page_key', 'unknown')
        title = page.get('title', 'Untitled')
        content_sections = page.get('content_sections', {})
        url = page.get('url', '')
        
        content_parts.append(f"\n--- PAGE: {page_key.upper()} ({title}) ---")
        content_parts.append(f"Original URL: {url}")
        
        for section_title, section_content in content_sections.items():
            if isinstance(section_content, str) and section_content.strip():
                # Additional filtering of legal content within sections
                section_lower = section_content.lower()
                has_legal_content = any(keyword in section_lower for keyword in excluded_keywords)
                
                if not has_legal_content:
                    content_parts.append(f"\n{section_title}:")
                    content_parts.append(section_content)
                    
                    # Extract images for tracking
                    import re
                    images_in_section = re.findall(r'\[image: ([^\]]+)\]', section_content)
                    all_images.update(images_in_section)
                else:
                    print(f"   🚫 Skipping legal content in section: {section_title}")
    
    # Add image inventory
    if all_images:
        print(f"   🖼️  Found {len(all_images)} images to integrate...")
        content_parts.append(f"\n=== IMAGE INVENTORY ===")
        content_parts.append(f"Total images available: {len(all_images)}")
        content_parts.append("Available image files:")
        for img in sorted(all_images):
            content_parts.append(f"  - {img}")
        content_parts.append("\nUse these images with: <img src='assets/images/filename.ext' alt='description' />")
        content_parts.append("For missing images, use Unsplash URLs with relevant search terms.")
    
    # Add extraction notes for context
    extraction_summary = site_brief.get('extraction_summary', {})
    if extraction_summary:
        print(f"   📊 Adding extraction summary...")
        content_parts.append(f"\n=== EXTRACTION NOTES ===")
        content_parts.append(f"Success rate: {extraction_summary.get('overall_success_rate', 'Unknown')}")
        
        pages_needing_manual = site_brief.get('pages_requiring_manual_processing', [])
        if pages_needing_manual:
            content_parts.append(f"Pages that may need attention: {[p.get('page_key') for p in pages_needing_manual]}")
            content_parts.append("Consider adding stock photos for these sections if content is sparse.")
    
    print(f"   ✅ Content preparation complete!")
    return '\n'.join(content_parts)

def generate_html_for_design(design_data: Dict, website_content: str, site_brief: Dict, design_number: int, model_index: int, max_retries: int = 2) -> tuple[str, Dict]:
    """Generate complete HTML for a single design as a standalone website with retry logic."""
    print(f"   [{print_timestamp()}] Starting HTML generation for design {design_number}...")
    
    model = get_gemini_model(model_index)
    if not model:
        raise ValueError("Could not initialize code generation model.")
    
    design_name = design_data.get('design_name', f'Design {design_number}')
    print(f"   🎨 Design: {design_name}")
    print(f"   🎯 Target emotion: {design_data.get('target_emotion', 'Not specified')}")
    print(f"   🔨 Creating standalone HTML with full functionality...")
    
    # Extract key context from site brief
    print(f"   📋 Extracting design context...")
    brand_profile = site_brief.get('brand_profile', {})
    navigation_links = site_brief.get('navigation_links', [])
    site_metadata = site_brief.get('site_metadata', {})
    business_keywords = brand_profile.get('keywords', [])
    brand_identity = brand_profile.get('brand_identity', '')
    
    # Extract all images mentioned in the content for reference
    print(f"   🖼️  Cataloging available images...")
    all_images = set()
    site_pages = site_brief.get('site_pages', [])
    for page in site_pages:
        content_sections = page.get('content_sections', {})
        for section_content in content_sections.values():
            if isinstance(section_content, str):
                import re
                images_in_section = re.findall(r'\[image: ([^\]]+)\]', section_content)
                all_images.update(images_in_section)
    
    print(f"   📊 Context summary:")
    print(f"      • Brand: {brand_identity[:50]}..." if brand_identity else "      • Brand: Not specified")
    print(f"      • Business type: {', '.join(business_keywords[:3])}")
    print(f"      • Navigation items: {len(navigation_links)}")
    print(f"      • Available images: {len(all_images)}")
    
    retry_instructions = ""  # Initialize retry instructions
    
    for attempt in range(max_retries + 1):
        try:
            if attempt > 0:
                print(f"   🔄 Retry attempt {attempt}/{max_retries} for Design {design_number}...")
                time.sleep(5 + (attempt * 5))  # Increasing delay
            
            print(f"   📝 Building optimized AI prompt (attempt {attempt + 1})...")
            
            # Optimize content to reduce prompt size
            optimized_content = website_content[:15000] + "..." if len(website_content) > 15000 else website_content
            
            # Simplify brand profile to essential info only
            simplified_brand = {
                "brand_identity": brand_identity[:500] + "..." if len(brand_identity) > 500 else brand_identity,
                "keywords": business_keywords[:5],  # Limit to top 5 keywords
                "colors": brand_profile.get('colors', [])[:4],  # Limit to 4 colors
                "design_style": brand_profile.get('design_style', '')[:300]  # Limit design style description
            }
            
            # Simplify design data to essential components only
            essential_design = {
                "design_name": design_data.get('design_name', ''),
                "design_philosophy": design_data.get('design_philosophy', '')[:200],
                "color_scheme": design_data.get('color_scheme', {}),
                "typography": design_data.get('typography', {}),
                "components": {
                    "header": design_data.get('components', {}).get('header', {}),
                    "navigation": design_data.get('components', {}).get('navigation', {}),
                    "hero": design_data.get('components', {}).get('hero', {}),
                    "buttons": design_data.get('components', {}).get('buttons', {}),
                    "cards": design_data.get('components', {}).get('cards', {})
                }
            }
            
            prompt = f"""You are an expert full-stack developer creating a complete, standalone website for a LIVE DEMO. This must be POLISHED and PRODUCTION-READY.

🚨 **CRITICAL DEMO REQUIREMENTS:**

**1. RESPONSIVE DESIGN (MANDATORY):**
- Mobile-first responsive design (320px+, 768px+, 1024px+)
- All text readable on mobile (min 16px font size)
- Touch-friendly buttons (min 44px targets)
- Navigation works on mobile

**2. TEXT CONTRAST (MANDATORY):**
- Minimum 4.5:1 contrast ratio
- Dark text (#333 or darker) on light backgrounds
- Light text (#fff or #f0f0f0+) on dark backgrounds  
- NO light text on light backgrounds
- NO white or light gray text on white/light backgrounds
- Test all text combinations for readability
- Use high contrast color combinations only

**3. CONTENT FILTERING (MANDATORY):**
- EXCLUDE privacy policy, terms of service, legal text
- EXCLUDE cookie notices, disclaimers, fine print
- FOCUS on main business content only
- Use actual business information provided
- NO generic placeholder content

**4. CLEAN LAYOUT (MANDATORY):**
- Header separate from content below
- NO overlapping elements
- NO duplicate information
- Consistent spacing system

**5. DEMO-SAFE LINKS (MANDATORY):**
- ALL links use href="#" onclick="return false"
- NO external navigation
- Hover effects for interactivity

**6. IMAGE STRATEGY (MANDATORY):**
- People/founders: https://via.placeholder.com/300x300/4a90e2/ffffff?text=Founder
- Stock content: Relevant Unsplash images
- Add proper alt text

**7. PROFESSIONAL POLISH (MANDATORY):**
- Modern styling with subtle shadows
- Smooth transitions (0.3s ease)
- Perfect spacing and typography
- When uncertain, be CONSERVATIVE

BUSINESS: {', '.join(business_keywords[:3])} - {brand_identity[:200]}

NAVIGATION: {json.dumps(navigation_links)}

DESIGN TO IMPLEMENT: {json.dumps(essential_design)}

CONTENT: {optimized_content}{retry_instructions}

**TECHNICAL REQUIREMENTS:**

1. **MUST START WITH:** <!DOCTYPE html>
2. **CSS SCOPING:** Wrap in <div id="design-{design_number}"> and scope ALL CSS with #design-{design_number}
3. **NO PLACEHOLDERS:** Use EXACT content provided above
4. **MINIMUM 15+ scoped CSS rules required**

**HTML TEMPLATE:**
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Business Website</title>
    <style>
        #design-{design_number} {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            line-height: 1.6;
            margin: 0;
            padding: 0;
            color: #333333; /* DARK text for light backgrounds */
        }}
        
        #design-{design_number} .header {{
            padding: 24px;
            margin-bottom: 32px;
            background: #ffffff; /* Light background */
            color: #333333; /* Dark text */
        }}
        
        #design-{design_number} .dark-section {{
            background: #333333; /* Dark background */
            color: #ffffff; /* Light text */
        }}
        
        #design-{design_number} .btn {{
            padding: 12px 24px;
            border-radius: 6px;
            transition: all 0.3s ease;
            min-height: 44px;
            cursor: pointer;
            /* ENSURE button text is readable */
            background: #007bff;
            color: #ffffff; /* White text on blue background */
        }}
        
        #design-{design_number} .btn:hover {{
            background: #0056b3; /* Darker blue on hover */
            color: #ffffff; /* Keep white text */
        }}
        
        /* CONTRAST EXAMPLES - USE THESE PATTERNS:
           Light backgrounds: use #333, #222, #000 for text
           Dark backgrounds: use #fff, #f8f9fa for text
           Blue backgrounds: use #fff for text
           Never use: light text on light bg, dark text on dark bg */
        
        /* 15+ more scoped CSS rules required */
        
        @media (min-width: 768px) {{
            #design-{design_number} .header {{
                padding: 32px;
            }}
        }}
    </style>
</head>
<body>
    <div id="design-{design_number}">
        <header class="header">
            <!-- Navigation with proper contrast -->
        </header>
        <main>
            <!-- Content sections with readable text -->
        </main>
        <footer class="dark-section">
            <!-- Footer with light text on dark background -->
        </footer>
    </div>
</body>
</html>
```

**CRITICAL VALIDATION CHECKLIST:**
1. ✅ All text must be readable (no white on white, no light gray on light backgrounds)
2. ✅ Dark text (#333+) on light backgrounds (#fff, #f8f9fa, etc.)
3. ✅ Light text (#fff, #f0f0f0+) on dark backgrounds (#333, #222, etc.)
4. ✅ No privacy policy or legal content included
5. ✅ All links use href="#" onclick="return false"
6. ✅ Mobile responsive design
7. ✅ Minimum 15+ scoped CSS rules

Return ONLY the complete HTML code implementing the design with all requirements."""

            print(f"   🚀 Sending to Gemini AI for implementation...", flush=True)
            print(f"   ⏱️  Estimated time: 45-90 seconds for complete website generation", flush=True)
            print(f"   🤖 AI is generating complete website for {design_name}...", flush=True)
            
            start_time = time.time()
            response = model.generate_content(prompt)
            end_time = time.time()
            
            print(f"   ✅ AI response received! (took {end_time - start_time:.1f} seconds)", flush=True)
            
            usage_data = print_usage_and_cost(response, model_index, f"HTML Generation - {design_name} (attempt {attempt + 1})")
            
            print(f"   🔍 Processing and validating generated HTML...")
            
            # Clean the response to get just the HTML
            html_content = response.text.strip()
            
            # Remove any markdown code blocks if present
            if html_content.startswith('```'):
                print(f"   🧹 Removing markdown formatting...")
                html_content = html_content.split('```')[1]
                if html_content.startswith('html'):
                    html_content = html_content[4:]
            if html_content.endswith('```'):
                html_content = html_content.rsplit('```', 1)[0]
            
            # Comprehensive validation
            print(f"   ✅ Running HTML validation checks...")
            validation_issues = []
            
            if not html_content.strip().startswith('<!DOCTYPE html'):
                validation_issues.append("Missing DOCTYPE declaration")
            
            if f'id="design-{design_number}"' not in html_content:
                validation_issues.append(f"Missing required design container ID: design-{design_number}")
            else:
                print(f"   ✅ Design container ID found: design-{design_number}")
            
            # Check for CSS scoping
            scoped_css_count = html_content.count(f'#design-{design_number}')
            if scoped_css_count < 15:  # Should have many scoped CSS rules per updated prompt
                validation_issues.append(f"Insufficient CSS scoping (found {scoped_css_count} rules, need 15+)")
            
            # Check for basic HTML structure
            if not ('<html' in html_content and '</html>' in html_content):
                validation_issues.append("Invalid HTML structure")
            
            # Check for placeholders and actual content
            placeholder_indicators = [
                'placeholder', 'lorem ipsum', '[insert', '[add', 'your content here',
                'content goes here', 'replace with', 'customize this', 'example content',
                'sample text', 'dummy text', 'brief description', 'add description'
            ]
            
            placeholder_count = sum(html_content.lower().count(indicator) for indicator in placeholder_indicators)
            
            # Check if actual website content is present (dynamic based on site)
            business_name = site_brief.get('brand_analysis', {}).get('business_name', '').lower()
            business_type = site_brief.get('brand_analysis', {}).get('business_type', '').lower()
            
            # Extract key terms from the actual content
            content_indicators = []
            if business_name:
                content_indicators.extend(business_name.split())
            if business_type:
                content_indicators.extend(business_type.split())
            
            # Add some generic content indicators
            content_indicators.extend(['contact', 'about', 'home', 'welcome', 'hours', 'phone'])
            
            # Remove common words and short words
            content_indicators = [term for term in content_indicators if len(term) > 3 and term not in ['the', 'and', 'for', 'with', 'your', 'our', 'all']]
            
            content_present = sum(html_content.lower().count(indicator) for indicator in content_indicators)
            
            # Only flag if there are many placeholder words AND little actual content
            if placeholder_count > 12 and content_present < 2:
                validation_issues.append("Contains too many placeholders instead of actual content")
            
            # Check file size
            html_size = len(html_content.encode('utf-8'))
            print(f"   📊 Generated HTML size: {html_size:,} bytes ({html_size/1024:.1f} KB)")
            
            if html_size < 10000:  # Less than 10KB is suspicious for a full website
                validation_issues.append(f"File too small ({html_size:,} bytes) - likely incomplete")
            
            # Check for image handling
            existing_image_count = len([img for img in all_images if img in html_content])
            unsplash_image_count = html_content.count('images.unsplash.com')
            local_image_count = html_content.count('assets/images/')
            
            print(f"   🖼️  Image integration analysis:")
            print(f"      • Local images: {local_image_count}")
            print(f"      • Stock photos: {unsplash_image_count}")
            print(f"      • Original images used: {existing_image_count}/{len(all_images)}")
            
            if existing_image_count > 0:
                print(f"   ✅ Successfully integrated {existing_image_count} original images")
            
            # Report validation results
            if validation_issues:
                print(f"   ⚠️  Validation issues found:")
                for issue in validation_issues:
                    print(f"      • {issue}")
                
                if attempt < max_retries:
                    print(f"   🔄 Will retry with corrected instructions...")
                    # Add specific error feedback for next attempt
                    error_feedback = f"\n\nPREVIOUS ATTEMPT ERRORS - DO NOT REPEAT:\n"
                    for issue in validation_issues:
                        if "DOCTYPE" in issue:
                            error_feedback += "- You forgot to start with <!DOCTYPE html> - MUST be the very first line\n"
                        elif "placeholder" in issue.lower():
                            error_feedback += "- You used placeholders instead of real content - use the EXACT content provided\n"
                        elif "scoping" in issue.lower():
                            error_feedback += f"- You didn't scope CSS properly - ALL CSS rules must start with #design-{design_number}\n"
                        elif "container ID" in issue:
                            error_feedback += f"- You forgot the main container - wrap everything in <div id=\"design-{design_number}\">\n"
                        else:
                            error_feedback += f"- {issue}\n"
                    
                    # Store error feedback for next iteration
                    retry_instructions = error_feedback
                    continue
                else:
                    print(f"   ⚠️  Max retries reached. Using current result with warnings...")
                    print(f"   💡 Manual review may be needed")
            else:
                print(f"   ✅ HTML validation complete - all checks passed!")
            
            print(f"   [{print_timestamp()}] Design {design_number} generation complete!")
            
            return html_content.strip(), usage_data
            
        except Exception as e:
            print(f"   ❌ Error generating HTML for {design_name} (attempt {attempt + 1}): {e}")
            
            if attempt < max_retries:
                retry_delay = 10 + (attempt * 10)
                print(f"   🔄 Retrying in {retry_delay} seconds...")
                time.sleep(retry_delay)
                continue
            else:
                print(f"   ❌ All retry attempts failed for Design {design_number}")
                raise

def create_manual_combination_html(design_htmls: List[str], designs_data: Dict) -> str:
    """Create a manual combination HTML using iframe approach for perfect isolation."""
    print(f"   [{print_timestamp()}] Creating manual combination with iframe approach...")
    
    designs = designs_data.get('designs', [])
    design_names = [design.get('design_name', f'Design {i+1}') for i, design in enumerate(designs)]
    
    # Count successful designs
    successful_designs = []
    for i, html in enumerate(design_htmls):
        if not html.startswith('<!--'):
            successful_designs.append({
                'number': i + 1,
                'name': design_names[i] if i < len(design_names) else f'Design {i+1}',
                'description': designs[i].get('design_philosophy', 'Modern website design') if i < len(designs) else 'Modern website design'
            })
    
    print(f"   📊 Combining {len(successful_designs)} successful designs")
    
    # Create manual combination HTML
    manual_html = f'''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Website Design Showcase</title>
    <style>
        * {{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }}

        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            overflow: hidden;
        }}

        .design-switcher {{
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 10000;
            background: rgba(0, 0, 0, 0.8);
            backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px);
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 16px;
            padding: 16px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            min-width: 180px;
        }}

        .design-switcher:hover {{
            background: rgba(0, 0, 0, 0.9);
            transform: translateY(-2px);
            box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
        }}

        .switcher-title {{
            color: white;
            font-size: 12px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 1.2px;
            margin-bottom: 12px;
            text-align: center;
            opacity: 0.9;
        }}

        .design-buttons {{
            display: flex;
            flex-direction: column;
            gap: 8px;
        }}

        .design-btn {{
            background: rgba(255, 255, 255, 0.15);
            border: 1px solid rgba(255, 255, 255, 0.3);
            color: rgba(255, 255, 255, 0.95);
            padding: 12px 16px;
            border-radius: 10px;
            font-family: inherit;
            font-size: 13px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            text-align: left;
            position: relative;
            overflow: hidden;
        }}

        .design-btn::before {{
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
            transition: left 0.5s;
        }}

        .design-btn:hover::before {{
            left: 100%;
        }}

        .design-btn:hover {{
            background: rgba(255, 255, 255, 0.25);
            color: white;
            transform: translateX(2px);
            border-color: rgba(255, 255, 255, 0.4);
        }}

        .design-btn.active {{
            background: rgba(255, 255, 255, 0.9);
            color: #333;
            border-color: rgba(255, 255, 255, 0.9);
            box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
            transform: translateX(0);
        }}

        .design-btn.active:hover {{
            transform: translateX(0);
            background: white;
        }}

        .design-frame {{
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border: none;
            opacity: 0;
            visibility: hidden;
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            transform: scale(0.95);
        }}

        .design-frame.active {{
            opacity: 1;
            visibility: visible;
            transform: scale(1);
        }}

        .keyboard-hint {{
            position: fixed;
            bottom: 20px;
            left: 20px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 8px 12px;
            border-radius: 8px;
            font-size: 11px;
            font-weight: 500;
            opacity: 0.8;
            z-index: 9999;
        }}

        /* Mobile responsiveness */
        @media (max-width: 768px) {{
            .design-switcher {{
                top: 10px;
                right: 10px;
                padding: 12px;
                min-width: 160px;
            }}
            
            .design-btn {{
                padding: 10px 12px;
                font-size: 12px;
            }}
            
            .keyboard-hint {{
                display: none;
            }}
        }}

        /* Loading animation */
        .loading {{
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: white;
            font-size: 16px;
            z-index: 9998;
        }}

        .loading::after {{
            content: '';
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 2px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top-color: white;
            animation: spin 1s ease-in-out infinite;
            margin-left: 10px;
        }}

        @keyframes spin {{
            to {{ transform: rotate(360deg); }}
        }}
    </style>
</head>
<body>
    <div class="design-switcher">
        <div class="switcher-title">Design Style</div>
        <div class="design-buttons">'''

    # Add buttons for each successful design
    for i, design in enumerate(successful_designs):
        active_class = 'active' if i == 0 else ''
        manual_html += f'''
            <button class="design-btn {active_class}" data-design="{design['number']}">{design['name']}</button>'''

    manual_html += '''
        </div>
    </div>

    <div class="loading" id="loading">Loading design...</div>

'''

    # Add iframes for each successful design
    for i, design in enumerate(successful_designs):
        active_class = 'active' if i == 0 else ''
        manual_html += f'''
    <iframe id="frame-{design['number']}" class="design-frame {active_class}" 
            src="design_{design['number']}.html" 
            title="{design['name']}">
    </iframe>'''

    manual_html += '''

    <script>
        // Design switching functionality
        let currentDesign = 1;
        const buttons = document.querySelectorAll('.design-btn');
        const frames = document.querySelectorAll('.design-frame');
        const loading = document.getElementById('loading');

        function showDesign(designNumber) {
            if (designNumber === currentDesign) return;
            
            // Show loading
            loading.style.display = 'block';
            
            // Update buttons
            buttons.forEach(btn => {
                btn.classList.toggle('active', btn.dataset.design == designNumber);
            });
            
            // Update frames with smooth transition
            frames.forEach(frame => {
                frame.classList.toggle('active', frame.id === `frame-${designNumber}`);
            });
            
            currentDesign = designNumber;
            
            // Save preference
            localStorage.setItem('selectedDesign', designNumber);
            
            // Hide loading after transition
            setTimeout(() => {
                loading.style.display = 'none';
            }, 400);
        }

        // Button click handlers
        buttons.forEach(button => {
            button.addEventListener('click', () => {
                const designNumber = parseInt(button.dataset.design);
                showDesign(designNumber);
            });
        });

        // Keyboard shortcuts
        document.addEventListener('keydown', (e) => {
            if (e.altKey && e.key >= '1' && e.key <= '3') {
                e.preventDefault();
                const designNumber = parseInt(e.key);
                const targetButton = document.querySelector(`[data-design="${designNumber}"]`);
                if (targetButton) {
                    showDesign(designNumber);
                }
            }
        });

        // Load saved preference
        document.addEventListener('DOMContentLoaded', () => {
            const saved = localStorage.getItem('selectedDesign');
            if (saved) {
                const savedNumber = parseInt(saved);
                const targetButton = document.querySelector(`[data-design="${savedNumber}"]`);
                if (targetButton) {
                    showDesign(savedNumber);
                }
            }
            
            // Hide loading once everything is ready
            setTimeout(() => {
                loading.style.display = 'none';
            }, 1000);
        });

        // Handle iframe load events
        frames.forEach(frame => {
            frame.addEventListener('load', () => {
                // Iframe loaded successfully
                console.log(`Design ${frame.id} loaded`);
                // Hide loading if this is the current design
                if (frame.classList.contains('active')) {
                    setTimeout(() => {
                        loading.style.display = 'none';
                    }, 100);
                }
            });
            
            frame.addEventListener('error', () => {
                console.error(`Failed to load ${frame.id}`);
                // Hide loading even on error to prevent infinite loading
                if (frame.classList.contains('active')) {
                    setTimeout(() => {
                        loading.style.display = 'none';
                    }, 100);
                }
            });
        });

        // Fallback timeout to hide loading if iframe doesn't fire load event
        setTimeout(() => {
            loading.style.display = 'none';
        }, 5000); // 5 second fallback timeout
    </script>
</body>
</html>'''

    print(f"   ✅ Manual combination HTML created successfully")
    print(f"   🎛️  Features: Smooth transitions, keyboard shortcuts, localStorage")
    print(f"   📱 Responsive design with glassmorphism UI")
    
    return manual_html

def create_readme(output_dir: Path, designs_data: Dict) -> None:
    """Create a README with instructions."""
    designs = designs_data.get('designs', [])
    design_brief = designs_data.get('design_brief', {})
    
    readme_content = f"""# Website Redesign - Generated Implementations

This directory contains the generated website implementations based on AI-designed concepts.

## Generated Files

- `index.html` - Complete website with all 3 design variations and switcher
- `design_1.html` - Individual implementation of {designs[0].get('design_name', 'Design 1') if len(designs) > 0 else 'Design 1'}
- `design_2.html` - Individual implementation of {designs[1].get('design_name', 'Design 2') if len(designs) > 1 else 'Design 2'}
- `design_3.html` - Individual implementation of {designs[2].get('design_name', 'Design 3') if len(designs) > 2 else 'Design 3'}

- `README.md` - This file

## Design Concepts

### Design 1: {designs[0].get('design_name', 'Design 1') if len(designs) > 0 else 'Design 1'}
{designs[0].get('design_philosophy', 'No description available') if len(designs) > 0 else 'No description available'}

### Design 2: {designs[1].get('design_name', 'Design 2') if len(designs) > 1 else 'Design 2'}
{designs[1].get('design_philosophy', 'No description available') if len(designs) > 1 else 'No description available'}

### Design 3: {designs[2].get('design_name', 'Design 3') if len(designs) > 2 else 'Design 3'}
{designs[2].get('design_philosophy', 'No description available') if len(designs) > 2 else 'No description available'}

## How to View

### Direct File Opening
Open `index.html` in your web browser. All features work without a server!

## Design Strategy

**Overall Strategy:** {design_brief.get('overall_strategy', 'Not provided')}

**Target Audience:** {design_brief.get('target_audience_analysis', 'Not provided')}

**Competitive Differentiation:** {design_brief.get('competitive_differentiation', 'Not provided')}

**Recommended Approach:** {design_brief.get('recommended_design', 'Not provided')}

## Features

- ✨ Three distinct design variations in one file
- 🎨 Smooth design switching with floating switcher
- 📱 Fully responsive design (mobile-first)
- ♿ Accessibility features and semantic HTML
- 🚀 Modern CSS and JavaScript (no external dependencies)
- 💾 Design preference saved to browser
- 🔄 Smooth animations and transitions
- 🎯 SEO-optimized markup

## Technical Notes

- All designs are contained in a single HTML file
- CSS is inlined for portability
- JavaScript handles design switching and interactions
- Images should be placed in `../assets/images/` relative to this file
- No external dependencies required

## Deployment

To deploy this website:

1. Upload `index.html` to your web server
2. Ensure image assets are available at the referenced paths
3. Configure your domain to point to this file
4. Test all three designs work correctly

---

Generated by AI Website Redesign Pipeline
"""

    readme_path = output_dir / "README.md"
    with open(readme_path, 'w', encoding='utf-8') as f:
        f.write(readme_content)
    
    print(f"   📖 README created: {readme_path.name}")

def main():
    """Main function to generate final HTML implementations."""
    print(f"\n🚀 STARTING ADVANCED CODE GENERATION")
    print(f"⏰ Started at: {print_timestamp()}")
    
    load_dotenv()
    
    model_options_text = ', '.join([f"{i}='{config['name']}'" for i, config in enumerate(MODELS_CONFIG)])
    
    parser = argparse.ArgumentParser(description="Generates complete HTML implementations from design specifications.")
    parser.add_argument("site_dir", type=str, help="Path to website data directory (output from design generator).")
    parser.add_argument("--model-index", type=int, default=DEFAULT_MODEL_INDEX, 
                       choices=range(len(MODELS_CONFIG)),
                       help=f"Model to use for code generation ({model_options_text})")
    parser.add_argument("--force-regenerate", choices=["all", "designs", "combination"], 
                       help="Force regeneration: 'all' (everything), 'designs' (individual designs only), 'combination' (final index.html only)")
    parser.add_argument("--skip-combination", action="store_true", 
                       help="Generate only individual designs, skip the combination step")
    
    args = parser.parse_args()
    
    site_data_path = Path(args.site_dir)
    if not site_data_path.is_dir():
        print(f"❌ Error: Directory not found at '{site_data_path}'")
        return
    
    print(f"\n--- Advanced Code Generation for {site_data_path.name} ---")
    print(f"🎯 Target: {site_data_path}")
    print(f"🤖 AI Model: {MODELS_CONFIG[args.model_index]['name']}")
    
    # Show processing mode based on arguments
    if args.force_regenerate:
        if args.force_regenerate == "all":
            print(f"🔄 Mode: FORCE REGENERATE ALL (designs + combination)")
        elif args.force_regenerate == "designs":
            print(f"🔄 Mode: FORCE REGENERATE DESIGNS ONLY")
        elif args.force_regenerate == "combination":
            print(f"🔄 Mode: FORCE REGENERATE COMBINATION ONLY")
    elif args.skip_combination:
        print(f"⏭️  Mode: DESIGNS ONLY (skip combination)")
    else:
        print(f"🚀 Mode: SMART RESUME (skip existing files)")
    
    print(f"📋 Process: 3 individual websites → 1 combined website with switcher")
    
    try:
        # Load project data
        print(f"\n📖 STEP 1: Loading Project Data")
        print(f"   [{print_timestamp()}] Reading design specifications and website content...")
        
        designs_data, site_brief = load_project_data(site_data_path)
        
        designs = designs_data.get('designs', [])
        if len(designs) == 0:
            print("❌ Error: No designs found in designs.json")
            return
        
        design_names = [d.get('design_name', f'Design {i+1}') for i, d in enumerate(designs)]
        
        print(f"✅ Successfully loaded project data:")
        print(f"   🎨 Found {len(designs)} design variations:")
        for i, name in enumerate(design_names, 1):
            emotion = designs[i-1].get('target_emotion', 'Not specified')
            print(f"      {i}. {name} (Target: {emotion})")
        
        pages_count = len(site_brief.get('site_pages', []))
        brand_name = site_brief.get('brand_profile', {}).get('brand_identity', 'Unknown')
        print(f"   📄 Website content: {pages_count} pages for {brand_name}")
        
        # Prepare content for generation
        print(f"\n📝 STEP 2: Content Preparation")
        website_content = prepare_content_for_generation(site_brief)
        
        # Extract total image count for reference
        all_images = set()
        for page in site_brief.get('site_pages', []):
            content_sections = page.get('content_sections', {})
            for section_content in content_sections.values():
                if isinstance(section_content, str):
                    import re
                    images_in_section = re.findall(r'\[image: ([^\]]+)\]', section_content)
                    all_images.update(images_in_section)
        
        print(f"   ✅ Content prepared and formatted for AI processing")
        print(f"   🖼️  Found {len(all_images)} images to integrate from original site")
        
        # Create output directory
        output_dir = site_data_path / "final_output"
        output_dir.mkdir(exist_ok=True)
        print(f"📁 Output directory ready: {output_dir}")
        
        # Check for existing individual design files
        print(f"\n🔨 STEP 3: Individual Website Generation", flush=True)
        print(f"   🔍 Checking for existing individual design files...")
        
        existing_designs = {}
        design_htmls = []
        total_usage_data = {"cost": 0, "tokens": 0}
        
        # Check which designs already exist (unless forcing regeneration)
        for i, design in enumerate(designs, 1):
            design_file = output_dir / f"design_{i}.html"
            
            # Skip existing file check if forcing regeneration of designs or all
            if args.force_regenerate in ["all", "designs"]:
                design_htmls.append(None)  # Force regeneration
                print(f"   🔄 Will regenerate Design {i}: {design.get('design_name', f'Design {i}')} (forced)")
                continue
            
            if design_file.exists():
                try:
                    with open(design_file, 'r', encoding='utf-8') as f:
                        existing_content = f.read()
                    
                    file_size = design_file.stat().st_size
                    if file_size > 5000 and not existing_content.startswith('<!--'):  # Valid existing file
                        existing_designs[i] = existing_content
                        design_htmls.append(existing_content)
                        print(f"   ✅ Found existing Design {i}: {design.get('design_name', f'Design {i}')} ({file_size:,} bytes)")
                    else:
                        design_htmls.append(None)  # Placeholder for regeneration
                        print(f"   ⚠️  Design {i} file exists but seems invalid - will regenerate")
                except Exception as e:
                    design_htmls.append(None)  # Placeholder for regeneration
                    print(f"   ⚠️  Could not read Design {i} file: {e} - will regenerate")
            else:
                design_htmls.append(None)  # Placeholder for new generation
                print(f"   🆕 Design {i} needs to be generated: {design.get('design_name', f'Design {i}')}")
        
        existing_count = len(existing_designs)
        total_designs = len(designs)
        
        if existing_count > 0:
            print(f"   📊 Resume status: {existing_count}/{total_designs} designs already exist")
            print(f"   💰 Estimated cost savings: ~${existing_count * 0.05:.3f}")
            print(f"   ⚡ Will only generate {total_designs - existing_count} missing designs")
        else:
            print(f"   📋 Creating {total_designs} complete standalone websites from scratch")
        
        print(f"   🎯 Each design will be a fully functional website")
        
        # Generate only missing designs
        for i, design in enumerate(designs, 1):
            if i in existing_designs:
                print(f"\n--- DESIGN {i}/{len(designs)}: {design.get('design_name', f'Design {i}')} ---")
                print(f"✅ SKIPPING: Design already exists and is valid")
                continue
                
            try:
                print(f"\n--- DESIGN {i}/{len(designs)}: {design.get('design_name', f'Design {i}')} ---", flush=True)
                print(f"⏰ Started at: {print_timestamp()}", flush=True)
                
                html_content, usage_data = generate_html_for_design(
                    design, website_content, site_brief, i, args.model_index
                )
                
                # Immediately save individual design as it's generated
                design_file = output_dir / f"design_{i}.html"
                print(f"   💾 Saving individual design immediately: {design_file.name}")
                with open(design_file, 'w', encoding='utf-8') as f:
                    f.write(html_content)
                
                file_size = design_file.stat().st_size
                print(f"   ✅ Individual design saved: {design_file.name} ({file_size:,} bytes)")
                print(f"   🔗 Available for testing: {design_file}")
                
                # Update the design_htmls list with new content
                design_htmls[i-1] = html_content
                total_usage_data["cost"] += usage_data.get("cost", 0)
                total_usage_data["tokens"] += usage_data.get("tokens", 0)
                
                print(f"   ✅ Design {i} complete and ready for testing")
                print(f"   ⏰ Completed at: {print_timestamp()}")
                
                # Small delay to avoid rate limiting
                remaining_designs = sum(1 for j in range(i+1, len(designs)+1) if j not in existing_designs)
                if remaining_designs > 0:  # Don't delay after the last one
                    print(f"   ⏸️  Brief pause before next design (3 seconds)...")
                    time.sleep(3)
                
            except Exception as e:
                print(f"   ❌ Failed to generate Design {i}: {e}")
                print(f"   ⏰ Failed at: {print_timestamp()}")
                design_htmls[i-1] = f"<!-- Design {i} generation failed: {e} -->"
        
        successful_designs = len([html for html in design_htmls if not html.startswith('<!--')])
        print(f"\n📊 Individual Design Generation Summary:")
        print(f"   ✅ Successfully generated: {successful_designs}/{len(designs)} designs")
        print(f"   💾 Each saved as standalone HTML file for testing")
        print(f"   💰 Cost so far: ${total_usage_data.get('cost', 0):.6f}")
        
        # Combine designs into final HTML
        if successful_designs > 0 and not args.skip_combination:
            print(f"\n🔗 STEP 4: Design Combination")
            print(f"   ⏰ Started at: {print_timestamp()}")
            
            # Check if combination already exists (unless forcing regeneration)
            final_file = output_dir / "index.html"
            if final_file.exists() and args.force_regenerate not in ["all", "combination"]:
                try:
                    final_size = final_file.stat().st_size
                    if final_size > 10000:  # At least 10KB for a valid combination
                        print(f"   ✅ Combined website already exists: {final_file.name} ({final_size:,} bytes)")
                        print(f"   🎯 Skipping combination step - file appears valid")
                        print(f"   💡 Use --force-regenerate=combination to regenerate the combination")
                        
                        # Still create supporting files if they don't exist
                        print(f"\n📝 STEP 5: Creating Supporting Files")
                        print(f"   ⏰ Started at: {print_timestamp()}")
                        create_readme(output_dir, designs_data)
                        print(f"   ✅ Supporting files updated")
                        
                        # Show final summary
                        print(f"\n🎉 CODE GENERATION COMPLETE (RESUMED)!")
                        print(f"⏰ Finished at: {print_timestamp()}")
                        print(f"   📊 Resume Results:")
                        print(f"      ✅ Individual websites: {successful_designs}/{len(designs)} successful")
                        print(f"      🔗 Combined website: ✅ index.html (existing)")
                        print(f"      📁 Supporting files: ✅ README.md")
                        
                        print(f"\n🌐 How to View Your Website:")
                        print(f"   📂 Navigate to: {output_dir}")
                        print(f"   🌍 Open index.html directly in your browser")
                        print(f"   💡 All designs work without a server!")
                        
                        print(f"\n💰 Cost for this run: ${total_usage_data.get('cost', 0):.6f}")
                        print(f"🔢 Tokens used this run: {total_usage_data.get('tokens', 0):,}")
                        print(json.dumps(total_usage_data))
                        return
                    else:
                        print(f"   ⚠️  Existing index.html seems too small ({final_size:,} bytes) - will regenerate")
                except Exception as e:
                    print(f"   ⚠️  Could not validate existing index.html: {e} - will regenerate")
            
            print(f"   🎛️  Creating manual combination HTML")
            print(f"   🔄 Implementing manual combination with iframe approach")
            print(f"   💾 Will save as index.html for final deployment")
            print(f"   📊 Creating manual combination HTML")
            
            manual_html = create_manual_combination_html(design_htmls, designs_data)
            
            # Save manual combination HTML
            final_file = output_dir / "index.html"
            print(f"   💾 Saving manual combination HTML to: {final_file.name}")
            with open(final_file, 'w', encoding='utf-8') as f:
                f.write(manual_html)
            
            final_size = final_file.stat().st_size
            print(f"   ✅ Manual combination HTML created successfully!")
            print(f"   💾 Final website saved: {final_file.name} ({final_size:,} bytes)")
            print(f"   🎯 Ready for deployment with manual combination")
            print(f"   ⏰ Completed at: {print_timestamp()}")
            
            # Quick validation of saved file
            if final_size > 5000:  # At least 5KB
                print(f"   ✅ Saved file size looks good")
            else:
                print(f"   ⚠️  WARNING: Saved file seems small - check content")
            
        elif args.skip_combination:
            print(f"\n⏭️  STEP 4: Design Combination SKIPPED")
            print(f"   💡 Combination step skipped as requested")
            print(f"   📄 Individual designs are available: design_1.html, design_2.html, design_3.html")
        else:
            print(f"   ⚠️  No successful designs to combine")
            print(f"   💡 Check individual design generation logs above")
        
        # Create supporting files
        print(f"\n📝 STEP 5: Creating Supporting Files")
        print(f"   ⏰ Started at: {print_timestamp()}")
        create_readme(output_dir, designs_data)
        print(f"   ✅ README created")
        print(f"   ⏰ Completed at: {print_timestamp()}")
        
        # Final summary
        successful_designs = len([html for html in design_htmls if not html.startswith('<!--')])
        final_html_exists = (output_dir / "index.html").exists()
        design_names = [d.get('design_name', f'Design {i+1}') for i, d in enumerate(designs_data.get('designs', []))]
        
        print(f"\n🎉 CODE GENERATION COMPLETE!")
        print(f"⏰ Finished at: {print_timestamp()}")
        print(f"   📊 Generation Results:")
        print(f"      ✅ Individual websites: {successful_designs}/{len(designs)} successful")
        for i, name in enumerate(design_names[:successful_designs], 1):
            print(f"         {i}. {name} → design_{i}.html")
        print(f"      🔗 Combined website: {'✅ index.html' if final_html_exists else '❌ Failed'}")
        print(f"      📁 Supporting files: ✅ README.md")
        
        print(f"\n🌐 How to View Your Website:")
        print(f"   📂 Navigate to: {output_dir}")
        print(f"   🌍 Open index.html directly in your browser")
        print(f"   💡 All designs work without a server!")
        
        if final_html_exists:
            print(f"\n🎛️  Design Switcher Features:")
            print(f"   • Manual combination with iframe approach")
            print(f"   • Saves your design preference")
            print(f"   • Fully responsive across all devices")
        
        print(f"\n💰 Total Generation Cost: ${total_usage_data.get('cost', 0):.6f}")
        print(f"🔢 Total Tokens Used: {total_usage_data.get('tokens', 0):,}")
        print(f"⏰ Total Time: Started at beginning → Finished at {print_timestamp()}")
        
        # Print usage data for orchestrator
        print(json.dumps(total_usage_data))
        
    except FileNotFoundError as e:
        print(f"❌ Required file not found: {e}")
        print(f"💡 Make sure you've run the design generator (script 3) first")
        print(f"⏰ Failed at: {print_timestamp()}")
    except Exception as e:
        print(f"❌ Code generation failed: {e}")
        print(f"🔍 Error details saved for debugging")
        print(f"⏰ Failed at: {print_timestamp()}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    main()