#!/usr/bin/env python3
"""
Script melhorado para comparar HTML focando no body
"""

import re
from html.parser import HTMLParser
from collections import defaultdict
from dataclasses import dataclass
from typing import Dict, List, Set, Tuple, Optional

@dataclass
class NodeDiff:
    path: str
    type: str
    vue_value: Optional[str]
    blade_value: Optional[str]
    severity: int

def extract_body(html: str) -> str:
    """Extrai apenas o conteúdo do body"""
    match = re.search(r'<body[^>]*>(.*?)</body>', html, re.DOTALL | re.IGNORECASE)
    if match:
        return match.group(1)
    return html

def normalize_html(html: str) -> str:
    """Normaliza HTML removendo whitespace redundante"""
    # Remove comentários
    html = re.sub(r'<!--.*?-->', '', html, flags=re.DOTALL)
    # Remove whitespace entre tags
    html = re.sub(r'>\s+<', '><', html)
    # Normaliza espaços
    html = re.sub(r'\s+', ' ', html)
    return html.strip()

def extract_classes_from_html(html: str) -> Dict[str, Set[str]]:
    """Extrai todas as classes CSS do HTML"""
    classes_map = {}
    
    # Encontra todas as tags com class
    pattern = r'<(\w+)[^>]*\sclass=["\']([^"\']+)["\'][^>]*>'
    
    idx = 0
    for match in re.finditer(pattern, html):
        tag = match.group(1)
        classes_str = match.group(2)
        classes = set(classes_str.split())
        
        # Cria um identificador único baseado na posição
        path = f"{tag}[{idx}]"
        classes_map[path] = {
            'tag': tag,
            'classes': classes,
            'full_match': match.group(0)[:200]  # Primeiros 200 chars
        }
        idx += 1
    
    return classes_map

def extract_structure(html: str) -> List[Dict]:
    """Extrai estrutura básica de tags"""
    structure = []
    tag_pattern = r'<(\w+)[^>]*>'
    
    idx = 0
    for match in re.finditer(tag_pattern, html):
        tag = match.group(1)
        if tag.lower() not in ['script', 'style', 'link', 'meta']:  # Ignora tags do head
            full_tag = match.group(0)
            structure.append({
                'tag': tag,
                'full_tag': full_tag[:150],
                'index': idx
            })
            idx += 1
    
    return structure

def find_unique_classes(vue_html: str, blade_html: str) -> Tuple[Set[str], Set[str]]:
    """Encontra classes únicas em cada HTML"""
    vue_classes = set()
    blade_classes = set()
    
    # Extrai todas as classes
    vue_matches = re.findall(r'\sclass=["\']([^"\']+)["\']', vue_html)
    blade_matches = re.findall(r'\sclass=["\']([^"\']+)["\']', blade_html)
    
    for match in vue_matches:
        vue_classes.update(match.split())
    
    for match in blade_matches:
        blade_classes.update(match.split())
    
    return vue_classes, blade_classes

def find_critical_class_diffs(vue_html: str, blade_html: str) -> List[NodeDiff]:
    """Encontra diferenças críticas de classes"""
    diffs = []
    
    # Classes críticas visualmente
    critical_prefixes = {
        'container', 'row', 'col', 'flex', 'grid', 'block', 'inline',
        'w-', 'h-', 'p-', 'm-', 'px-', 'py-', 'mx-', 'my-', 'pt-', 'pb-', 'pl-', 'pr-',
        'mt-', 'mb-', 'ml-', 'mr-', 'space-', 'gap-',
        'text-', 'font-', 'leading-', 'tracking-',
        'bg-', 'border-', 'rounded-'
    }
    
    vue_classes, blade_classes = find_unique_classes(vue_html, blade_html)
    
    missing_in_blade = vue_classes - blade_classes
    extra_in_blade = blade_classes - vue_classes
    
    # Filtra apenas classes críticas
    critical_missing = {c for c in missing_in_blade if any(c.startswith(prefix) for prefix in critical_prefixes) or any(prefix in c for prefix in critical_prefixes)}
    critical_extra = {c for c in extra_in_blade if any(c.startswith(prefix) for prefix in critical_prefixes) or any(prefix in c for prefix in critical_prefixes)}
    
    if critical_missing:
        diffs.append(NodeDiff(
            path="classes",
            type="classes",
            vue_value=", ".join(sorted(critical_missing)),
            blade_value=None,
            severity=9
        ))
    
    if critical_extra:
        diffs.append(NodeDiff(
            path="classes",
            type="classes",
            vue_value=None,
            blade_value=", ".join(sorted(critical_extra)),
            severity=9
        ))
    
    return diffs

def compare_structural_elements(vue_body: str, blade_body: str) -> List[NodeDiff]:
    """Compara elementos estruturais principais"""
    diffs = []
    
    # Encontra containers principais
    vue_containers = re.findall(r'<div[^>]*class=["\']([^"\']*container[^"\']*)["\'][^>]*>', vue_body)
    blade_containers = re.findall(r'<div[^>]*class=["\']([^"\']*container[^"\']*)["\'][^>]*>', blade_body)
    
    vue_main_content = re.search(r'<div[^>]*class=["\'][^"\']*main[^"\']*content[^"\']*["\'][^>]*>', vue_body)
    blade_main_content = re.search(r'<div[^>]*class=["\'][^"\']*main[^"\']*content[^"\']*["\'][^>]*>', blade_body)
    
    if vue_main_content and not blade_main_content:
        diffs.append(NodeDiff(
            path="main_content",
            type="structure",
            vue_value="Present",
            blade_value=None,
            severity=10
        ))
    
    if not vue_main_content and blade_main_content:
        diffs.append(NodeDiff(
            path="main_content",
            type="structure",
            vue_value=None,
            blade_value="Present",
            severity=10
        ))
    
    return diffs

def main():
    import sys
    
    vue_file = sys.argv[1]
    blade_file = sys.argv[2]
    
    with open(vue_file, 'r', encoding='utf-8') as f:
        vue_html = f.read()
    
    with open(blade_file, 'r', encoding='utf-8') as f:
        blade_html = f.read()
    
    # Extrai body
    vue_body = extract_body(vue_html)
    blade_body = extract_body(blade_html)
    
    # Normaliza
    vue_body_norm = normalize_html(vue_body)
    blade_body_norm = normalize_html(blade_body)
    
    print("="*80)
    print("COMPARAÇÃO HTML - FOCO EM BODY")
    print("="*80)
    print(f"\nVue body:   {len(vue_body_norm)} caracteres")
    print(f"Blade body: {len(blade_body_norm)} caracteres")
    
    # Compara classes
    print("\n" + "="*80)
    print("ANÁLISE DE CLASSES CSS")
    print("="*80)
    
    vue_classes, blade_classes = find_unique_classes(vue_body_norm, blade_body_norm)
    
    missing_in_blade = vue_classes - blade_classes
    extra_in_blade = blade_classes - vue_classes
    
    print(f"\nTotal de classes únicas:")
    print(f"  Vue:   {len(vue_classes)}")
    print(f"  Blade: {len(blade_classes)}")
    print(f"  Em comum: {len(vue_classes & blade_classes)}")
    
    # Classes críticas faltando
    critical_prefixes = {
        'container', 'row', 'col', 'flex', 'grid',
        'w-', 'h-', 'p-', 'm-', 'px-', 'py-', 'mx-', 'my-',
        'text-', 'font-', 'bg-', 'border-', 'rounded-',
        'sm:', 'md:', 'lg:', 'xl:', '2xl:'
    }
    
    critical_missing = sorted([c for c in missing_in_blade if any(c.startswith(p) or p in c for p in critical_prefixes)])
    critical_extra = sorted([c for c in extra_in_blade if any(c.startswith(p) or p in c for p in critical_prefixes)])
    
    print(f"\n🔴 CLASSES CRÍTICAS EM VUE MAS NÃO EM BLADE ({len(critical_missing)}):")
    for cls in critical_missing[:50]:
        print(f"  - {cls}")
    if len(critical_missing) > 50:
        print(f"  ... e mais {len(critical_missing) - 50}")
    
    print(f"\n🟡 CLASSES CRÍTICAS EM BLADE MAS NÃO EM VUE ({len(critical_extra)}):")
    for cls in critical_extra[:50]:
        print(f"  - {cls}")
    if len(critical_extra) > 50:
        print(f"  ... e mais {len(critical_extra) - 50}")
    
    # Compara estrutura
    print("\n" + "="*80)
    print("ANÁLISE DE ESTRUTURA")
    print("="*80)
    
    structural_diffs = compare_structural_elements(vue_body_norm, blade_body_norm)
    
    # Conta elementos principais
    vue_articles = len(re.findall(r'<article[^>]*>', vue_body_norm, re.IGNORECASE))
    blade_articles = len(re.findall(r'<article[^>]*>', blade_body_norm, re.IGNORECASE))
    
    vue_h1 = len(re.findall(r'<h1[^>]*>', vue_body_norm, re.IGNORECASE))
    blade_h1 = len(re.findall(r'<h1[^>]*>', blade_body_norm, re.IGNORECASE))
    
    print(f"\nElementos estruturais:")
    print(f"  <article>: Vue={vue_articles}, Blade={blade_articles}")
    print(f"  <h1>: Vue={vue_h1}, Blade={blade_h1}")
    
    # Salva relatório
    with open('tmp/diff_report_body.txt', 'w', encoding='utf-8') as f:
        f.write("RELATÓRIO DE DIFERENÇAS - BODY\n")
        f.write("="*80 + "\n\n")
        f.write(f"Classes em Vue mas não em Blade ({len(missing_in_blade)}):\n")
        for cls in sorted(missing_in_blade):
            f.write(f"  - {cls}\n")
        f.write(f"\nClasses em Blade mas não em Vue ({len(extra_in_blade)}):\n")
        for cls in sorted(extra_in_blade):
            f.write(f"  - {cls}\n")
    
    print(f"\n✅ Relatório completo salvo em: tmp/diff_report_body.txt")

if __name__ == '__main__':
    main()



