import requests
from bs4 import BeautifulSoup
import logging
import tinycss2

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def extract_css(url):
    try:
        # Download webpage content
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')

        # Collect all CSS content
        all_css = ""

        # Inline CSS
        for style in soup.find_all('style'):
            all_css += style.string or ""

        # External CSS files
        for link in soup.find_all('link', rel='stylesheet'):
            css_url = link.get('href')
            if css_url:
                if not css_url.startswith(('http:', 'https:')):
                    css_url = requests.compat.urljoin(url, css_url)
                try:
                    css_response = requests.get(css_url)
                    css_response.raise_for_status()
                    all_css += css_response.text
                except requests.RequestException as e:
                    logger.warning(f"Cannot load CSS from {css_url}: {e}")

        return extract_relevant_css(all_css)

    except Exception as e:
        logger.error(f"Error extracting CSS: {e}")
        return ""

def extract_relevant_css(css_content):
    relevant_css = ""
    parsed_css = tinycss2.parse_stylesheet(css_content, skip_comments=True, skip_whitespace=True)

    # Define selectors and properties of interest
    selectors_of_interest = {
        'background_color': ['body', 'html'],
        'button_color': ['button', '.button', '.btn', '[type="button"]', 'input[type="submit"]'],
        'text_color': ['body', 'html', 'p'],
        'font_style': ['body', 'html']
    }

    properties_of_interest = {
        'background_color': ['background-color', 'background'],
        'button_color': ['background-color', 'background', 'color', 'border-color'],
        'text_color': ['color'],
        'font_style': ['font-family', 'font-style', 'font-weight', 'font-size']
    }

    extracted_properties = {
        'background_color': [],
        'button_color': [],
        'text_color': [],
        'font_style': []
    }

    for rule in parsed_css:
        if rule.type != 'qualified-rule':
            continue

        # Get the selector
        selector = tinycss2.serialize(rule.prelude).strip()
        declarations = tinycss2.parse_declaration_list(rule.content)

        for prop in extracted_properties.keys():
            if any(sel in selector for sel in selectors_of_interest[prop]):
                for declaration in declarations:
                    if declaration.type != 'declaration':
                        continue
                    name = declaration.name.lower()
                    value = tinycss2.serialize(declaration.value).strip()
                    if name in properties_of_interest[prop]:
                        extracted_properties[prop].append({
                            'selector': selector,
                            'property': name,
                            'value': value
                        })

    # Build the relevant CSS string
    for prop, styles in extracted_properties.items():
        if styles:
            relevant_css += f"/* {prop.replace('_', ' ').title()} */\n"
            for style in styles:
                relevant_css += f"{style['selector']} {{ {style['property']}: {style['value']}; }}\n"
            relevant_css += "\n"

    return relevant_css

# Use the function
url = "https://www.vsatech.net/"  # Replace with the actual URL
result = extract_css(url)
print(result) \n Cho đoạn code trích xuất các dòng css code từ web url. Mục đích là lấy các dòng css code liên quan đến các thuộc tính sau: background_color: str = Field(description="the primary background color used on the website. Must be a valid hex color code and not transparent.")
button_color: str = Field(description="The primary color used for buttons on the website. Must be a valid hex color code, not transparent.")
text_color: str = Field(description="the primary text color used on the website. Must be a valid hex color code and not transparent.")
font_style: str = Field(description="the main font style used on the website.") \n Để sau đó LLMs sẽ dựa vào đó để phân tích, trích xuất ra các properties trên.
Làm thế nào lấy không thừa (thừa thì tốn prompt dẫn đến tăng cost), cũng không thiếu (thiếu thì không đủ thông tin, phân tích sai). Hiện tại button color dùng LLMs trích xuất từ các css code trên không chính xác, hãy cải tiến giúp tôi. Có thể những thông tin liên quan đến button color đang bị thiếu. Bạn có thể cân nhắc xem thông tin về CSS variable cũng như body trong CSS code.