"""
export_simatic_sd_tia20 : Script para exportar bloques de PLC desde TIA Portal 20 en formato SIMATIC SD.
Basado en la nueva funcionalidad de exportación SIMATIC SD disponible en TIA Portal V20.
"""

import tkinter as tk
from tkinter import filedialog
import os
import sys
import traceback

script_root = os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
)
sys.path.append(script_root)
from backend.script_utils import load_configuration

# --- Configuration ---
TIA_PORTAL_VERSION = "20.0"  # Target TIA Portal version for SIMATIC SD support
EXPORT_OPTIONS = None  # Use default export options
KEEP_FOLDER_STRUCTURE = (
    True  # Replicate TIA project folder structure in export directory
)

# --- TIA Scripting Import Handling ---
# Check if the TIA_SCRIPTING environment variable is set
if os.getenv("TIA_SCRIPTING"):
    sys.path.append(os.getenv("TIA_SCRIPTING"))
else:
    # Optional: Define a fallback path if the environment variable isn't set
    # fallback_path = "C:\\path\\to\\your\\TIA_Scripting_binaries"
    # if os.path.exists(fallback_path):
    #     sys.path.append(fallback_path)
    pass  # Allow import to fail if not found

try:
    import siemens_tia_scripting as ts

    EXPORT_OPTIONS = (
        ts.Enums.ExportOptions.WithDefaults
    )  # Set default options now that 'ts' is imported
except ImportError:
    print("ERROR: Failed to import 'siemens_tia_scripting'.")
    print("Ensure:")
    print(f"1. TIA Portal Openness for V{TIA_PORTAL_VERSION} is installed.")
    print(
        "2. The 'siemens_tia_scripting' Python module is installed (pip install ...) or"
    )
    print(
        "   the path to its binaries is set in the 'TIA_SCRIPTING' environment variable."
    )
    print(
        "3. You are using a compatible Python version (e.g., 3.12.X as per documentation)."
    )
    sys.exit(1)
except Exception as e:
    print(f"An unexpected error occurred during import: {e}")
    traceback.print_exc()
    sys.exit(1)

# --- Functions ---


def verify_export_format(export_path, expected_format="SIMATIC_SD"):
    """
    Verifies what format was actually exported by examining file extensions.
    Returns (actual_format, file_extensions, file_count)
    """
    if not os.path.exists(export_path):
        return "NO_FILES", [], 0

    files = [
        f
        for f in os.listdir(export_path)
        if os.path.isfile(os.path.join(export_path, f))
    ]
    if not files:
        return "EMPTY_FOLDER", [], 0

    extensions = [os.path.splitext(f)[1].lower() for f in files]
    extension_counts = {}
    for ext in extensions:
        extension_counts[ext] = extension_counts.get(ext, 0) + 1

    # Determine actual format based on file extensions
    if all(ext == ".xml" for ext in extensions):
        actual_format = "XML_ONLY"
    elif any(ext in [".sd", ".simatic"] for ext in extensions):
        actual_format = "SIMATIC_SD"
    elif ".xml" in extensions and len(set(extensions)) > 1:
        actual_format = "MIXED"
    else:
        actual_format = "UNKNOWN"

    return actual_format, extension_counts, len(files)


def check_simatic_sd_block_compatibility(block):
    """
    Checks if a block is compatible with SIMATIC SD export format.
    Returns (is_compatible, reason)
    """
    try:
        # Check if block is consistent
        if not block.is_consistent():
            return False, "Block is not consistent/compiled"

        # Check programming language - SIMATIC SD only supports LAD
        try:
            prog_lang = block.get_programming_language()
            if prog_lang != ts.Enums.ProgrammingLanguage.LAD:
                return (
                    False,
                    f"Language {prog_lang} not supported (SIMATIC SD requires LAD)",
                )
        except Exception:
            return False, "Could not determine programming language"

        # Check block type - SIMATIC SD typically supports FB, FC, OB
        try:
            block_type = block.get_block_type()
            supported_types = [
                ts.Enums.BlockType.FB,  # Function Block
                ts.Enums.BlockType.FC,  # Function
                ts.Enums.BlockType.OB,  # Organization Block
            ]
            if block_type not in supported_types:
                return False, f"Block type {block_type} may not be supported"
        except Exception:
            # If we can't determine type, assume it might work
            pass

        return True, "Block appears compatible with SIMATIC SD"

    except Exception as e:
        return False, f"Error checking compatibility: {e}"


def verify_export_format(export_path, expected_format="SimaticSD"):
    """
    Verifies if the exported files are actually in the expected format.
    For SIMATIC SD, looks for specific keywords like RUNG, END_RUNG, wire#
    Returns (is_correct_format, file_count, sample_files, format_details)
    """
    if not os.path.exists(export_path):
        return False, 0, [], "Directory does not exist"

    files = [
        f
        for f in os.listdir(export_path)
        if os.path.isfile(os.path.join(export_path, f))
    ]
    if not files:
        return False, 0, [], "No files found"

    # Check first few files for format
    sample_files = files[:3]
    format_details = []

    for file_name in sample_files:
        file_path = os.path.join(export_path, file_name)
        try:
            with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                content = f.read(2000)  # Read first 2KB

            file_info = {"file": file_name, "size": len(content)}

            if expected_format == "SimaticSD":
                # SIMATIC SD specific keywords and structure
                sd_keywords = ["RUNG", "END_RUNG", "wire#", "NETWORK", "TITLE", "LAD"]
                xml_indicators = ["<?xml", "<Document", "<SW.Blocks"]

                found_sd_keywords = [kw for kw in sd_keywords if kw in content]
                found_xml_indicators = [xi for xi in xml_indicators if xi in content]

                file_info["sd_keywords"] = found_sd_keywords
                file_info["xml_indicators"] = found_xml_indicators
                file_info["is_xml"] = len(found_xml_indicators) > 0
                file_info["is_simatic_sd"] = (
                    len(found_sd_keywords) > 0 and not file_info["is_xml"]
                )
                file_info["first_100_chars"] = (
                    content[:100].replace("\n", " ").replace("\r", "")
                )

            else:  # XML format
                file_info["is_xml"] = (
                    content.strip().startswith("<?xml") or "<Document" in content
                )
                file_info["first_100_chars"] = (
                    content[:100].replace("\n", " ").replace("\r", "")
                )

            format_details.append(file_info)

        except Exception as e:
            format_details.append({"file": file_name, "error": str(e)})

    # Determine overall result for SIMATIC SD
    if expected_format == "SimaticSD":
        is_correct_format = any(
            f.get("is_simatic_sd", False) for f in format_details if "error" not in f
        )
    else:
        is_correct_format = any(
            f.get("is_xml", False) for f in format_details if "error" not in f
        )

    return is_correct_format, len(files), sample_files, format_details


def select_project_file():
    """Opens a dialog to select a TIA Portal project file."""
    root = tk.Tk()
    root.withdraw()  # Hide the main tkinter window
    file_path = filedialog.askopenfilename(
        title="Select TIA Portal Project File",
        filetypes=[
            (
                f"TIA Portal V{TIA_PORTAL_VERSION} Projects",
                f"*.ap{TIA_PORTAL_VERSION.split('.')[0]}",
            )
        ],  # e.g. *.ap20
    )
    root.destroy()
    if not file_path:
        print("No project file selected. Exiting.")
        sys.exit(0)
    return file_path


def select_export_directory():
    """Opens a dialog to select the export directory."""
    root = tk.Tk()
    root.withdraw()  # Hide the main tkinter window
    dir_path = filedialog.askdirectory(title="Select Export Directory")
    root.destroy()
    if not dir_path:
        print("No export directory selected. Exiting.")
        sys.exit(0)
    return dir_path


def check_simatic_sd_support():
    """Verifies if SIMATIC SD format is available in the current TIA Scripting version."""
    try:
        # Check if SimaticSD is available in ExportFormats enum
        simatic_sd_format = ts.Enums.ExportFormats.SimaticSD
        print(f"✓ SIMATIC SD format enum found (value: {simatic_sd_format})")

        # Try to get more information about available formats
        try:
            all_formats = [
                attr for attr in dir(ts.Enums.ExportFormats) if not attr.startswith("_")
            ]
            print(f"  Available export formats: {all_formats}")
        except Exception:
            pass

        return True
    except AttributeError:
        print("✗ ERROR: SIMATIC SD format not available in this TIA Scripting version.")
        print(
            "Please ensure you are using TIA Portal V20 or later with compatible TIA Scripting."
        )
        return False


def check_tia_portal_version():
    """Check TIA Portal version and compatibility."""
    print("\n=== TIA PORTAL VERSION CHECK ===")
    try:
        # This will be filled when we connect to TIA Portal
        print("TIA Portal version check will be performed after connection...")
        return True
    except Exception as e:
        print(f"Could not check TIA Portal version: {e}")
        return False


def export_plc_data_simatic_sd(plc, export_base_dir):
    """Exports Blocks, UDTs, and Tag Tables from a given PLC in SIMATIC SD format."""
    plc_name = plc.get_name()
    print(f"\n--- Processing PLC: {plc_name} (SIMATIC SD Export) ---")

    # Define base export path for this PLC with timestamp to avoid conflicts
    import datetime

    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    plc_export_dir = os.path.join(export_base_dir, f"{plc_name}_SimaticSD_{timestamp}")
    os.makedirs(plc_export_dir, exist_ok=True)

    # --- Export Program Blocks in SIMATIC SD Format ---
    blocks_exported_sd = 0
    blocks_exported_xml = 0
    blocks_skipped = 0
    blocks_not_lad = 0
    print(f"\n[PLC: {plc_name}] Exporting Program Blocks (SIMATIC SD)...")
    print("  NOTE: SIMATIC SD format only supports LAD (Ladder) programming language!")
    sd_blocks_path = os.path.join(plc_export_dir, "01_ProgramBlocks_SD")
    os.makedirs(sd_blocks_path, exist_ok=True)
    print(f"  SIMATIC SD Target: {sd_blocks_path}")

    # Also create a separate SimaticML export for comparison
    xml_blocks_path = os.path.join(plc_export_dir, "02_ProgramBlocks_XML_Compare")
    os.makedirs(xml_blocks_path, exist_ok=True)

    try:
        program_blocks = plc.get_program_blocks()
        print(f"  Found {len(program_blocks)} program blocks.")
        for block in program_blocks:
            block_name = block.get_name()
            print(f"    Processing block: {block_name}...")
            try:
                if not block.is_consistent():
                    print(f"      Compiling block {block_name}...")
                    block.compile()
                    if not block.is_consistent():
                        print(
                            f"      WARNING: Block {block_name} inconsistent after compile. Skipping."
                        )
                        blocks_skipped += 1
                        continue

                # Check programming language - CRITICAL for SIMATIC SD
                is_compatible, compatibility_reason = (
                    check_simatic_sd_block_compatibility(block)
                )
                print(f"      Compatibility check: {compatibility_reason}")

                if not is_compatible:
                    print(f"      Block {block_name} not compatible with SIMATIC SD.")
                    print(f"      Exporting XML only: {compatibility_reason}")
                    blocks_not_lad += 1

                    # Export only in XML for incompatible blocks
                    block.export(
                        target_directory_path=xml_blocks_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticML,
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )
                    blocks_exported_xml += 1
                    print(
                        f"      ✓ Exported {block_name} in XML (incompatible with SIMATIC SD)"
                    )
                    continue

                # Try SIMATIC SD export for LAD blocks
                print(f"      Exporting LAD block {block_name} as SIMATIC SD...")
                try:
                    block.export(
                        target_directory_path=sd_blocks_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticSD,  # SIMATIC SD format
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )

                    # Verify if the export was actually in SIMATIC SD format
                    print(f"      Verifying SIMATIC SD format for {block_name}...")
                    is_sd, file_count, sample_files, format_details = (
                        verify_export_format(sd_blocks_path, "SimaticSD")
                    )

                    if is_sd:
                        blocks_exported_sd += 1
                        print(
                            f"      ✓ Successfully exported {block_name} in REAL SIMATIC SD format"
                        )
                        # Show sample of SD content
                        for detail in format_details:
                            if detail.get("is_simatic_sd") and detail.get(
                                "sd_keywords"
                            ):
                                print(
                                    f"        🎯 SD Keywords found: {', '.join(detail['sd_keywords'])}"
                                )
                                break
                    else:
                        print(
                            f"      ❌ FAILED: Export claimed SD but files are actually XML!"
                        )
                        print(f"      📋 Format analysis:")
                        for detail in format_details:
                            if "error" not in detail:
                                print(f"        File: {detail['file']}")
                                print(
                                    f"          SIMATIC SD: {detail.get('is_simatic_sd', False)}"
                                )
                                print(
                                    f"          XML format: {detail.get('is_xml', False)}"
                                )
                                if detail.get("sd_keywords"):
                                    print(
                                        f"          SD keywords: {detail['sd_keywords']}"
                                    )
                                if detail.get("xml_indicators"):
                                    print(
                                        f"          XML indicators: {detail['xml_indicators']}"
                                    )
                                print(
                                    f"          Content start: {detail.get('first_100_chars', '')[:50]}..."
                                )

                    # Also export same block in XML for comparison
                    print(f"      Exporting {block_name} as XML for comparison...")
                    block.export(
                        target_directory_path=xml_blocks_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticML,  # Traditional XML format
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )
                    blocks_exported_xml += 1
                    print(f"      + Also exported {block_name} in XML for comparison")

                except Exception as export_ex:
                    print(f"      ERROR during SIMATIC SD export: {export_ex}")
                    print(
                        f"      This is likely because SIMATIC SD has specific requirements:"
                    )
                    print(f"        - Block must be in LAD (Ladder) format")
                    print(
                        f"        - Block must be compatible with SIMATIC SD specification"
                    )
                    # Try to export only in XML if SD fails
                    try:
                        print(
                            f"      Attempting fallback XML export for {block_name}..."
                        )
                        block.export(
                            target_directory_path=xml_blocks_path,
                            export_options=EXPORT_OPTIONS,
                            export_format=ts.Enums.ExportFormats.SimaticML,
                            keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                        )
                        print(
                            f"      ✓ Fallback XML export successful for {block_name}"
                        )
                        blocks_exported_xml += 1
                    except Exception as fallback_ex:
                        print(
                            f"      ERROR: Both SD and XML export failed: {fallback_ex}"
                        )
                        blocks_skipped += 1

            except Exception as block_ex:
                print(f"      ERROR exporting block {block_name}: {block_ex}")
                blocks_skipped += 1

        print(
            f"  Program Blocks Export Summary: SIMATIC SD={blocks_exported_sd}, XML={blocks_exported_xml}, Non-LAD={blocks_not_lad}, Skipped/Errors={blocks_skipped}"
        )
    except Exception as e:
        print(f"  ERROR processing Program Blocks: {e}")
        traceback.print_exc()

    # --- Export PLC Data Types (UDTs) in SIMATIC SD Format ---
    udts_exported = 0
    udts_skipped = 0
    print(f"\n[PLC: {plc_name}] Exporting PLC Data Types - UDTs (SIMATIC SD)...")
    udt_sd_export_path = os.path.join(plc_export_dir, "03_PlcDataTypes_SD")
    udt_xml_export_path = os.path.join(plc_export_dir, "04_PlcDataTypes_XML_Compare")
    os.makedirs(udt_sd_export_path, exist_ok=True)
    os.makedirs(udt_xml_export_path, exist_ok=True)
    print(f"  SIMATIC SD Target: {udt_sd_export_path}")
    print(f"  XML Compare Target: {udt_xml_export_path}")

    try:
        udts = plc.get_user_data_types()
        print(f"  Found {len(udts)} UDTs.")
        for udt in udts:
            udt_name = udt.get_name()
            print(f"    Processing UDT: {udt_name}...")
            try:
                if not udt.is_consistent():
                    print(f"      Compiling UDT {udt_name}...")
                    udt.compile()
                    if not udt.is_consistent():
                        print(
                            f"      WARNING: UDT {udt_name} inconsistent after compile. Skipping."
                        )
                        udts_skipped += 1
                        continue

                print(f"      Exporting {udt_name} as SIMATIC SD...")
                try:
                    udt.export(
                        target_directory_path=udt_sd_export_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticSD,  # SIMATIC SD format for UDTs
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )
                    # Also export in XML for comparison
                    udt.export(
                        target_directory_path=udt_xml_export_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticML,
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )
                    udts_exported += 1
                    print(f"      ✓ Successfully exported {udt_name} (SD + XML)")
                except Exception as udt_export_ex:
                    print(f"      ERROR during UDT export: {udt_export_ex}")
                    udts_skipped += 1

            except Exception as udt_ex:
                print(f"      ERROR exporting UDT {udt_name}: {udt_ex}")
                udts_skipped += 1

        print(
            f"  UDT Export Summary: Exported={udts_exported}, Skipped/Errors={udts_skipped}"
        )
    except Exception as e:
        print(f"  ERROR processing UDTs: {e}")
        traceback.print_exc()

    # --- Export PLC Tag Tables in SIMATIC SD Format ---
    tags_exported = 0
    tags_skipped = 0
    print(f"\n[PLC: {plc_name}] Exporting PLC Tag Tables (SIMATIC SD)...")
    tags_sd_export_path = os.path.join(plc_export_dir, "05_PlcTags_SD")
    tags_xml_export_path = os.path.join(plc_export_dir, "06_PlcTags_XML_Compare")
    os.makedirs(tags_sd_export_path, exist_ok=True)
    os.makedirs(tags_xml_export_path, exist_ok=True)
    print(f"  SIMATIC SD Target: {tags_sd_export_path}")
    print(f"  XML Compare Target: {tags_xml_export_path}")

    try:
        tag_tables = plc.get_plc_tag_tables()
        print(f"  Found {len(tag_tables)} Tag Tables.")
        for table in tag_tables:
            table_name = table.get_name()
            print(f"    Processing Tag Table: {table_name}...")
            try:
                print(f"      Exporting {table_name} as SIMATIC SD...")
                try:
                    table.export(
                        target_directory_path=tags_sd_export_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticSD,  # SIMATIC SD format for Tag Tables
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )
                    # Also export in XML for comparison
                    table.export(
                        target_directory_path=tags_xml_export_path,
                        export_options=EXPORT_OPTIONS,
                        export_format=ts.Enums.ExportFormats.SimaticML,
                        keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                    )
                    tags_exported += 1
                    print(f"      ✓ Successfully exported {table_name} (SD + XML)")
                except Exception as tag_export_ex:
                    print(f"      ERROR during Tag Table export: {tag_export_ex}")
                    tags_skipped += 1

            except Exception as table_ex:
                print(f"      ERROR exporting Tag Table {table_name}: {table_ex}")
                tags_skipped += 1

        print(
            f"  Tag Table Export Summary: Exported={tags_exported}, Skipped/Errors={tags_skipped}"
        )
    except Exception as e:
        print(f"  ERROR processing Tag Tables: {e}")
        traceback.print_exc()

    print(f"\n--- Finished processing PLC: {plc_name} ---")


def export_additional_formats(plc, export_base_dir):
    """Optional: Export in traditional formats alongside SIMATIC SD for comparison."""
    plc_name = plc.get_name()
    print(
        f"\n[Optional] Exporting traditional formats for comparison - PLC: {plc_name}"
    )

    # Create comparison directory
    comparison_dir = os.path.join(export_base_dir, plc_name, "Comparison_Formats")
    os.makedirs(comparison_dir, exist_ok=True)

    # Export a few blocks in SimaticML for comparison
    xml_comparison_path = os.path.join(comparison_dir, "SimaticML_Sample")
    os.makedirs(xml_comparison_path, exist_ok=True)

    try:
        program_blocks = plc.get_program_blocks()
        # Export first 3 blocks in SimaticML for comparison
        for i, block in enumerate(program_blocks[:3]):
            if block.is_consistent():
                block_name = block.get_name()
                print(f"    Exporting {block_name} in SimaticML for comparison...")
                block.export(
                    target_directory_path=xml_comparison_path,
                    export_options=EXPORT_OPTIONS,
                    export_format=ts.Enums.ExportFormats.SimaticML,
                    keep_folder_structure=KEEP_FOLDER_STRUCTURE,
                )
    except Exception as e:
        print(f"  Warning: Could not export comparison formats: {e}")


# --- Main Script ---


if __name__ == "__main__":
    configs = load_configuration()
    working_directory = configs.get("working_directory")

    print("--- TIA Portal 20 SIMATIC SD Exporter ---")
    print("Exporting Blocks, UDTs, and Tags in SIMATIC SD Format")

    # Check SIMATIC SD support first
    if not check_simatic_sd_support():
        sys.exit(1)

    # Validate working directory
    if not working_directory or not os.path.isdir(working_directory):
        print("ERROR: Working directory not set or invalid in configuration.")
        print("Please configure the working directory using the main application.")
        sys.exit(1)

    # 1. Select Project File, Export Directory comes from config
    project_file = select_project_file()
    export_dir = working_directory  # Use working directory from config

    print(f"\nSelected Project: {project_file}")
    print(f"Using Export Directory (Working Directory): {export_dir}")

    portal_instance = None
    project_object = None

    try:
        # 2. Connect to TIA Portal V20
        print(f"\nConnecting to TIA Portal V{TIA_PORTAL_VERSION}...")
        portal_instance = ts.open_portal(
            version=TIA_PORTAL_VERSION,
            portal_mode=ts.Enums.PortalMode.WithGraphicalUserInterface,
        )
        print("Connected to TIA Portal V20.")
        print(f"Portal Process ID: {portal_instance.get_process_id()}")

        # Get TIA Portal version information
        try:
            portal_version = portal_instance.get_version()
            print(f"TIA Portal Version: {portal_version}")

            # Check if this version really supports SIMATIC SD
            version_parts = portal_version.split(".")
            major_version = int(version_parts[0]) if version_parts else 0
            if major_version < 20:
                print(
                    f"⚠️  WARNING: TIA Portal V{major_version} may not fully support SIMATIC SD (requires V20+)"
                )
            else:
                print(f"✓ TIA Portal V{major_version} should support SIMATIC SD")

        except Exception as ver_ex:
            print(f"Could not get TIA Portal version: {ver_ex}")

        # 3. Open Project
        print(f"Opening project: {os.path.basename(project_file)}...")
        project_object = portal_instance.open_project(project_file_path=project_file)
        if project_object is None:
            print("Project might already be open, attempting to get handle...")
            project_object = portal_instance.get_project()
            if project_object is None:
                raise Exception("Failed to open or get the specified project.")
        print("Project opened successfully.")

        # 4. Get PLCs
        plcs = project_object.get_plcs()
        if not plcs:
            print("No PLC devices found in the project.")
        else:
            print(f"Found {len(plcs)} PLC(s). Starting SIMATIC SD export process...")

            # 5. Iterate and Export Data for each PLC in SIMATIC SD format
            import datetime  # Add this import for timestamp

            for plc_device in plcs:
                export_plc_data_simatic_sd(plc=plc_device, export_base_dir=export_dir)

        print("\n🎉 SIMATIC SD Export process completed successfully!")
        print("\nExported files structure:")
        print("├── [PLC_Name]_SimaticSD_[timestamp]/")
        print(
            "│   ├── 01_ProgramBlocks_SD/          # SIMATIC SD format (LAD blocks only)"
        )
        print("│   ├── 02_ProgramBlocks_XML_Compare/ # Traditional XML for comparison")
        print("│   ├── 03_PlcDataTypes_SD/")
        print("│   ├── 04_PlcDataTypes_XML_Compare/")
        print("│   ├── 05_PlcTags_SD/")
        print("│   └── 06_PlcTags_XML_Compare/")
        print("\n📋 IMPORTANT SIMATIC SD LIMITATIONS:")
        print("   • SIMATIC SD format ONLY supports LAD (Ladder) programming language")
        print("   • SCL, STL, FBD blocks are exported as XML only")
        print("   • Only FB, FC, OB block types are typically supported")
        print("   • Complex LAD elements may still fall back to XML")
        print(
            "\nNow you can compare the differences between SIMATIC SD and traditional XML formats!"
        )

        # Add file analysis
        print("\n=== FILE FORMAT ANALYSIS ===")
        for plc_device in plcs:
            plc_name = plc_device.get_name()
            import datetime

            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            plc_export_dir = os.path.join(
                export_dir, f"{plc_name}_SimaticSD_{timestamp}"
            )

            print(f"\nAnalyzing exported files for PLC: {plc_name}")
            folders_to_check = [
                ("01_ProgramBlocks_SD", "SIMATIC SD Blocks"),
                ("02_ProgramBlocks_XML_Compare", "XML Blocks"),
                ("03_PlcDataTypes_SD", "SIMATIC SD UDTs"),
                ("04_PlcDataTypes_XML_Compare", "XML UDTs"),
                ("05_PlcTags_SD", "SIMATIC SD Tags"),
                ("06_PlcTags_XML_Compare", "XML Tags"),
            ]

            simatic_sd_working = False
            total_sd_files = 0
            total_xml_fallbacks = 0

            for folder_name, description in folders_to_check:
                folder_path = os.path.join(plc_export_dir, folder_name)
                if os.path.exists(folder_path):
                    actual_format, extensions, file_count = verify_export_format(
                        folder_path
                    )
                    print(f"  {description}: {file_count} files")
                    print(f"    Format detected: {actual_format}")
                    print(f"    File extensions: {extensions}")

                    if "SD" in folder_name:  # This should be SIMATIC SD folder
                        if actual_format == "XML_ONLY":
                            print(
                                f"    ⚠️  WARNING: Expected SIMATIC SD but got XML only!"
                            )
                            total_xml_fallbacks += file_count
                        elif actual_format == "SIMATIC_SD":
                            simatic_sd_working = True
                            total_sd_files += file_count
                        elif actual_format == "UNKNOWN" and file_count > 0:
                            print(f"    🔍 UNKNOWN format - needs manual inspection")

                else:
                    print(f"  {description}: Folder not found")

            print(f"\n🔍 SIMATIC SD DIAGNOSIS FOR {plc_name}:")
            if simatic_sd_working:
                print(
                    f"  ✅ SIMATIC SD is working: {total_sd_files} files in true SD format"
                )
            else:
                print(f"  ❌ SIMATIC SD NOT working: All 'SD' exports are actually XML")
                print(f"  📊 Total XML fallbacks: {total_xml_fallbacks}")

                if total_xml_fallbacks > 0:
                    print(f"\n  💡 POSSIBLE CAUSES:")
                    print(f"     • TIA Portal version doesn't fully support SIMATIC SD")
                    print(f"     • TIA Scripting version incompatible with SIMATIC SD")
                    print(f"     • Project blocks contain unsupported LAD elements")
                    print(
                        f"     • SIMATIC SD enum exists but falls back to XML silently"
                    )

    except ts.TiaException as tia_ex:
        print(f"\nTIA Portal Openness Error: {tia_ex}")
        traceback.print_exc()
    except FileNotFoundError:
        print(f"\nERROR: Project file not found at {project_file}")
    except Exception as e:
        print(f"\nAn unexpected error occurred: {e}")
        traceback.print_exc()
    finally:
        # 6. Cleanup
        if portal_instance:
            try:
                print("\nClosing TIA Portal...")
                portal_instance.close_portal()
                print("TIA Portal closed.")
            except Exception as close_ex:
                print(f"Error during TIA Portal cleanup: {close_ex}")

        print("\nScript finished.")
