#!/usr/bin/env python3
"""
extract-pptx-theme.py — extrai design tokens de um ficheiro PPTX

Uso:
    python3 extract-pptx-theme.py <caminho.pptx> [--output tokens.json]

Devolve JSON no mesmo formato do extract-web-tokens.js para que /clone-style apply
seja unificado entre os 2 modos.
"""
import sys
import json
import zipfile
import xml.etree.ElementTree as ET
from pathlib import Path
from datetime import datetime, timezone

NS = {'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'}


def extract_theme(pptx_path: Path) -> dict:
    if not pptx_path.exists():
        raise FileNotFoundError(f"Não encontrado: {pptx_path}")

    with zipfile.ZipFile(pptx_path) as z:
        # Listar themes (pode haver múltiplos; usar o primeiro)
        theme_files = sorted([n for n in z.namelist() if n.startswith('ppt/theme/theme') and n.endswith('.xml')])
        if not theme_files:
            raise ValueError("PPTX sem theme — formato inválido ou corrompido")

        theme_xml = z.read(theme_files[0])
        root = ET.fromstring(theme_xml)

    # Extrair cores do clrScheme
    colors = {}
    for clr_scheme in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}clrScheme'):
        for color_node in clr_scheme:
            name = color_node.tag.split('}')[1]  # ex: 'accent1', 'dk1', 'lt1'
            srgb = color_node.find('a:srgbClr', NS)
            sysclr = color_node.find('a:sysClr', NS)
            if srgb is not None:
                colors[name] = '#' + srgb.get('val')
            elif sysclr is not None:
                # sysClr usa o lastClr como fallback (cor resolvida)
                colors[name] = '#' + sysclr.get('lastClr', '000000')

    # Extrair fontes do fontScheme
    fonts = {'headline': None, 'body': None}
    for fs in root.iter('{http://schemas.openxmlformats.org/drawingml/2006/main}fontScheme'):
        major = fs.find('a:majorFont/a:latin', NS)
        minor = fs.find('a:minorFont/a:latin', NS)
        if major is not None:
            fonts['headline'] = major.get('typeface')
        if minor is not None:
            fonts['body'] = minor.get('typeface')

    # Mapear cores PPTX → estrutura unificada
    accent_keys = ['accent1', 'accent2', 'accent3', 'accent4', 'accent5', 'accent6']
    accents = [colors[k] for k in accent_keys if k in colors]

    primary = colors.get('accent1') or accents[0] if accents else '#000000'
    secondary = colors.get('accent2')
    tertiary = colors.get('accent3')
    neutral = colors.get('lt1') or colors.get('dk1') or '#ffffff'
    background = colors.get('lt1') or colors.get('bg1') or '#ffffff'

    is_dark = colors.get('lt1', '#ffffff').lstrip('#').upper() != 'FFFFFF'

    return {
        'url': str(pptx_path),
        'title': pptx_path.stem,
        'source': 'pptx',
        'timestamp': datetime.now(timezone.utc).isoformat(),
        'colors': {
            'top': [{'value': v, 'count': 1} for v in accents],
            'backgrounds': [{'value': background, 'count': 1}],
            'dominant': primary,
            'raw_scheme': colors,
        },
        'fonts': {
            'families': [
                {'value': fonts['headline'], 'count': 1, 'role': 'headline'},
                {'value': fonts['body'], 'count': 1, 'role': 'body'},
            ],
            'sizes': [],
            'weights': [],
            'lineHeights': [],
        },
        'borderRadius': [],
        'shadows': [],
        'spacing': {'gridBaseGuess': 8, 'top': []},
        'components': {},
        'meta': {
            'colorMode': 'DARK' if is_dark else 'LIGHT',
            'theme_file': theme_files[0],
            'accent_count': len(accents),
        },
        'mapping_hint': {
            'stitch_customColor': primary,
            'stitch_overrideSecondary': secondary,
            'stitch_overrideTertiary': tertiary,
            'stitch_overrideNeutral': neutral,
            'note': 'PPTX só fornece cores e fontes — borderRadius/shadows/spacing têm de ser definidos manualmente em designMd',
        },
    }


def main():
    if len(sys.argv) < 2:
        print(__doc__, file=sys.stderr)
        sys.exit(1)

    pptx = Path(sys.argv[1]).expanduser().resolve()

    output_path = None
    if '--output' in sys.argv:
        idx = sys.argv.index('--output')
        if idx + 1 < len(sys.argv):
            output_path = Path(sys.argv[idx + 1]).expanduser().resolve()

    tokens = extract_theme(pptx)
    js = json.dumps(tokens, indent=2, ensure_ascii=False)

    if output_path:
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(js, encoding='utf-8')
        print(f"✅ Tokens guardados em {output_path}", file=sys.stderr)
    else:
        print(js)


if __name__ == '__main__':
    main()
