#!/usr/bin/env python3
"""
Frontend Link Crawler for LittleShop Admin Panel
Tests all navigation links in both mobile and desktop views
"""

import requests
import re
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
import json
import time
from collections import defaultdict

class FrontendLinkCrawler:
    def __init__(self, base_url="http://localhost:5000", username="admin", password="admin"):
        self.base_url = base_url
        self.session = requests.Session()
        self.visited_urls = set()
        self.broken_links = []
        self.redirect_links = []
        self.navigation_links = {}
        self.test_results = {
            "mobile": {"working": [], "broken": [], "redirects": []},
            "desktop": {"working": [], "broken": [], "redirects": []}
        }
        
        # Login credentials
        self.username = username
        self.password = password
        
    def login(self):
        """Login to the admin panel"""
        print("🔐 Logging into admin panel...")
        
        # Get login page to get anti-forgery token
        login_url = f"{self.base_url}/Admin/Account/Login"
        response = self.session.get(login_url)
        
        if response.status_code != 200:
            print(f"❌ Failed to access login page: {response.status_code}")
            return False
            
        soup = BeautifulSoup(response.content, 'html.parser')
        token_input = soup.find('input', {'name': '__RequestVerificationToken'})
        
        if not token_input:
            print("❌ Could not find anti-forgery token")
            return False
            
        token = token_input.get('value')
        
        # Submit login form
        login_data = {
            'Username': self.username,
            'Password': self.password,
            '__RequestVerificationToken': token
        }
        
        response = self.session.post(login_url, data=login_data, allow_redirects=True)
        
        # Check if login was successful (should redirect to dashboard)
        if '/Admin/Dashboard' in response.url or response.url.endswith('/Admin'):
            print("✅ Successfully logged in")
            return True
        else:
            print(f"❌ Login failed - redirected to: {response.url}")
            return False
    
    def get_page_links(self, url, view_type="desktop"):
        """Extract all links from a page"""
        headers = {
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15' if view_type == "mobile" else 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
        
        try:
            response = self.session.get(url, headers=headers, timeout=10)
            response.raise_for_status()
            
            soup = BeautifulSoup(response.content, 'html.parser')
            links = []
            
            # Extract all anchor tags
            for a_tag in soup.find_all('a', href=True):
                href = a_tag.get('href')
                if href:
                    full_url = urljoin(url, href)
                    link_text = a_tag.get_text(strip=True)
                    link_classes = a_tag.get('class', [])
                    
                    # Only include admin panel links
                    if '/Admin' in full_url:
                        links.append({
                            'url': full_url,
                            'text': link_text,
                            'classes': link_classes,
                            'source_page': url
                        })
                        
            return links, response.status_code
            
        except requests.RequestException as e:
            print(f"❌ Error accessing {url}: {str(e)}")
            return [], 0
    
    def test_link(self, link_info, view_type="desktop"):
        """Test if a link is working"""
        url = link_info['url']
        
        headers = {
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15' if view_type == "mobile" else 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
        
        try:
            response = self.session.get(url, headers=headers, timeout=10, allow_redirects=False)
            
            result = {
                'url': url,
                'text': link_info['text'],
                'source_page': link_info['source_page'],
                'status_code': response.status_code,
                'view_type': view_type
            }
            
            if response.status_code == 200:
                self.test_results[view_type]["working"].append(result)
                return "working"
            elif response.status_code in [301, 302, 303, 307, 308]:
                result['redirect_url'] = response.headers.get('Location', 'Unknown')
                self.test_results[view_type]["redirects"].append(result)
                return "redirect"
            else:
                self.test_results[view_type]["broken"].append(result)
                return "broken"
                
        except requests.RequestException as e:
            result = {
                'url': url,
                'text': link_info['text'],
                'source_page': link_info['source_page'],
                'error': str(e),
                'view_type': view_type
            }
            self.test_results[view_type]["broken"].append(result)
            return "error"
    
    def crawl_admin_panel(self):
        """Main crawling function"""
        if not self.login():
            return False
            
        print("🕷️  Starting frontend link crawler...")
        
        # Key admin pages to test
        admin_pages = [
            f"{self.base_url}/Admin/Dashboard",
            f"{self.base_url}/Admin/Categories",
            f"{self.base_url}/Admin/Products", 
            f"{self.base_url}/Admin/Orders",
            f"{self.base_url}/Admin/Users",
            f"{self.base_url}/Admin/Bots",
            f"{self.base_url}/Admin/Messages",
            f"{self.base_url}/Admin/ShippingRates"
        ]
        
        all_links = set()
        
        # Collect all links from each page
        for page_url in admin_pages:
            print(f"📄 Scanning page: {page_url}")
            
            # Get links for both mobile and desktop views
            for view_type in ["desktop", "mobile"]:
                links, status_code = self.get_page_links(page_url, view_type)
                
                if status_code == 200:
                    print(f"  ✅ Found {len(links)} links in {view_type} view")
                    for link in links:
                        link['view_type'] = view_type
                        all_links.add((link['url'], link['text'], link['source_page'], view_type))
                else:
                    print(f"  ❌ Failed to access {page_url} in {view_type} view: {status_code}")
        
        print(f"\n🔍 Testing {len(all_links)} unique links...")
        
        # Test each unique link
        for url, text, source_page, view_type in all_links:
            link_info = {
                'url': url,
                'text': text,
                'source_page': source_page
            }
            
            result = self.test_link(link_info, view_type)
            status_emoji = "✅" if result == "working" else "🔄" if result == "redirect" else "❌"
            print(f"  {status_emoji} [{view_type}] {text}: {url} -> {result}")
            
            # Small delay to avoid overwhelming the server
            time.sleep(0.1)
    
    def generate_report(self):
        """Generate a comprehensive test report"""
        report = {
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
            "summary": {
                "mobile": {
                    "working": len(self.test_results["mobile"]["working"]),
                    "broken": len(self.test_results["mobile"]["broken"]),
                    "redirects": len(self.test_results["mobile"]["redirects"])
                },
                "desktop": {
                    "working": len(self.test_results["desktop"]["working"]),
                    "broken": len(self.test_results["desktop"]["broken"]),
                    "redirects": len(self.test_results["desktop"]["redirects"])
                }
            },
            "details": self.test_results
        }
        
        # Save detailed report
        with open('/mnt/c/Production/Source/LittleShop/frontend_test_report.json', 'w') as f:
            json.dump(report, f, indent=2)
        
        # Generate readable summary
        print("\n" + "="*80)
        print("🔍 FRONTEND LINK CRAWLER REPORT")
        print("="*80)
        
        for view_type in ["mobile", "desktop"]:
            print(f"\n📱 {view_type.upper()} VIEW RESULTS:")
            summary = report["summary"][view_type]
            print(f"  ✅ Working Links: {summary['working']}")
            print(f"  🔄 Redirects: {summary['redirects']}")
            print(f"  ❌ Broken Links: {summary['broken']}")
            
            # Show broken links in detail
            if self.test_results[view_type]["broken"]:
                print(f"\n❌ BROKEN LINKS ({view_type.upper()}):")
                for broken in self.test_results[view_type]["broken"]:
                    print(f"  • {broken['text']}: {broken['url']}")
                    print(f"    Source: {broken['source_page']}")
                    if 'error' in broken:
                        print(f"    Error: {broken['error']}")
                    else:
                        print(f"    Status: {broken['status_code']}")
                    print()
            
            # Show suspicious redirects
            if self.test_results[view_type]["redirects"]:
                print(f"\n🔄 REDIRECTS ({view_type.upper()}):")
                for redirect in self.test_results[view_type]["redirects"]:
                    print(f"  • {redirect['text']}: {redirect['url']}")
                    print(f"    Redirects to: {redirect.get('redirect_url', 'Unknown')}")
                    print(f"    Source: {redirect['source_page']}")
                    print()
        
        print("="*80)
        print(f"📊 Report saved to: frontend_test_report.json")
        
        return report

def main():
    crawler = FrontendLinkCrawler()
    crawler.crawl_admin_panel()
    report = crawler.generate_report()
    
    # Quick summary
    total_broken = sum(len(report["details"][view]["broken"]) for view in ["mobile", "desktop"])
    if total_broken > 0:
        print(f"\n⚠️  Found {total_broken} broken links that need attention!")
        return 1
    else:
        print(f"\n🎉 All links are working correctly!")
        return 0

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