#!/usr/bin/env python3
"""
Demonstration of the Fingerprint Cache Feature

This script shows how to use the fingerprint cache for efficient file change detection
in build systems and development workflows.
"""

import os
import tempfile
import time
from pathlib import Path

from ci.fingerprint import FingerprintCache


def has_changed(src_path: Path, previous_modtime: float, cache_file: Path) -> bool:
    """Convenience wrapper for backward compatibility."""
    cache = FingerprintCache(cache_file)
    return cache.has_changed(src_path, previous_modtime)


def demo_basic_usage() -> None:
    """Demonstrate basic fingerprint cache usage."""
    print("=== Basic Fingerprint Cache Demo ===")

    with tempfile.TemporaryDirectory() as temp_dir:
        temp_path = Path(temp_dir)
        cache_file = temp_path / "demo_cache.json"
        cache = FingerprintCache(cache_file)

        # Create a source file
        source_file = temp_path / "example.cpp"
        with open(source_file, "w") as f:
            f.write("#include <iostream>\nint main() { return 0; }")

        baseline_time = time.time() - 3600  # 1 hour ago
        current_modtime = os.path.getmtime(source_file)

        print(f"Source file: {source_file}")
        print(f"Baseline time: {baseline_time}")
        print(f"Current modtime: {current_modtime}")

        # First check - file is newer than baseline
        changed = cache.has_changed(source_file, baseline_time)
        print(f"First check (vs baseline): {changed} (expected: True)")

        # Second check - same modtime
        changed = cache.has_changed(source_file, current_modtime)
        print(f"Second check (same modtime): {changed} (expected: False)")

        # Touch file (change modtime but not content)
        time.sleep(0.01)
        source_file.touch()

        # Third check - modtime changed but content same
        changed = cache.has_changed(source_file, current_modtime)
        print(
            f"Third check (touched file): {changed} (expected: False - content unchanged)"
        )

        # Actually modify content
        time.sleep(0.01)
        with open(source_file, "w") as f:
            f.write(
                '#include <iostream>\nint main() { std::cout << "Hello"; return 0; }'
            )

        # Fourth check - content actually changed
        changed = cache.has_changed(source_file, current_modtime)
        print(f"Fourth check (content changed): {changed} (expected: True)")


def demo_build_system_workflow() -> None:
    """Demonstrate build system integration workflow."""
    print("\n=== Build System Workflow Demo ===")

    with tempfile.TemporaryDirectory() as temp_dir:
        temp_path = Path(temp_dir)
        cache_file = temp_path / "build_cache.json"
        cache = FingerprintCache(cache_file)

        # Simulate multiple source files
        source_files = [
            temp_path / "main.cpp",
            temp_path / "utils.cpp",
            temp_path / "config.h",
        ]

        # Create source files
        contents = [
            '#include "config.h"\n#include "utils.h"\nint main() { return 0; }',
            '#include "utils.h"\nvoid utility_function() {}',
            '#pragma once\n#define VERSION "1.0"',
        ]

        for src_file, content in zip(source_files, contents):
            with open(src_file, "w") as f:
                f.write(content)

        print(f"Created {len(source_files)} source files")

        # Simulate first build
        print("\n--- First Build (all files new) ---")
        last_build_time = time.time() - 3600  # 1 hour ago
        changed_files: list[str] = []

        for src_file in source_files:
            if cache.has_changed(src_file, last_build_time):
                changed_files.append(src_file.name)

        print(
            f"Files to rebuild: {changed_files} ({len(changed_files)}/{len(source_files)})"
        )

        # Update last build time
        current_modtimes = [os.path.getmtime(f) for f in source_files]

        # Simulate second build (no changes)
        print("\n--- Second Build (no changes) ---")
        changed_files: list[str] = []

        for src_file, modtime in zip(source_files, current_modtimes):
            if cache.has_changed(src_file, modtime):
                changed_files.append(src_file.name)

        print(
            f"Files to rebuild: {changed_files} ({len(changed_files)}/{len(source_files)})"
        )

        # Modify one file
        print("\n--- Third Build (one file modified) ---")
        time.sleep(0.01)
        with open(source_files[0], "a") as f:
            f.write("\n// Added comment")

        changed_files: list[str] = []
        for src_file, modtime in zip(source_files, current_modtimes):
            if cache.has_changed(src_file, modtime):
                changed_files.append(src_file.name)

        print(
            f"Files to rebuild: {changed_files} ({len(changed_files)}/{len(source_files)})"
        )


def demo_performance() -> None:
    """Demonstrate cache performance characteristics."""
    print("\n=== Performance Demo ===")

    with tempfile.TemporaryDirectory() as temp_dir:
        temp_path = Path(temp_dir)
        cache_file = temp_path / "perf_cache.json"
        cache = FingerprintCache(cache_file)

        # Create multiple test files
        num_files = 20
        test_files: list[Path] = []

        for i in range(num_files):
            test_file = temp_path / f"file_{i:03d}.cpp"
            with open(test_file, "w") as f:
                f.write(
                    f"// File {i}\n#include <iostream>\nint func_{i}() {{ return {i}; }}"
                )
            test_files.append(test_file)

        print(f"Created {num_files} test files")

        # Measure cache miss performance (first check)
        start_time = time.time()
        baseline_time = time.time() - 3600

        for test_file in test_files:
            cache.has_changed(test_file, baseline_time)

        miss_time = time.time() - start_time
        print(
            f"Cache miss time: {miss_time * 1000:.1f}ms ({miss_time * 1000 / num_files:.2f}ms per file)"
        )

        # Measure cache hit performance (second check with same modtime)
        modtimes = [os.path.getmtime(f) for f in test_files]

        start_time = time.time()
        for test_file, modtime in zip(test_files, modtimes):
            cache.has_changed(test_file, modtime)

        hit_time = time.time() - start_time
        print(
            f"Cache hit time: {hit_time * 1000:.1f}ms ({hit_time * 1000 / num_files:.2f}ms per file)"
        )
        print(f"Speedup: {miss_time / hit_time:.1f}x faster")

        # Show cache statistics
        stats = cache.get_cache_stats()
        print(f"Cache entries: {stats['total_entries']}")
        print(f"Cache file size: {stats['cache_file_size_bytes']} bytes")


def demo_convenience_function() -> None:
    """Demonstrate the convenience has_changed function."""
    print("\n=== Convenience Function Demo ===")

    with tempfile.TemporaryDirectory() as temp_dir:
        temp_path = Path(temp_dir)
        cache_file = temp_path / "convenience_cache.json"

        # Create test file
        test_file = temp_path / "test.h"
        with open(test_file, "w") as f:
            f.write("#pragma once\n#define API_VERSION 1")

        baseline_time = time.time() - 1800  # 30 minutes ago

        # Use convenience function
        changed = has_changed(test_file, baseline_time, cache_file)
        print(f"Convenience function result: {changed}")
        print(f"Cache file created: {cache_file.exists()}")


if __name__ == "__main__":
    print("Fingerprint Cache Feature Demonstration")
    print("=" * 50)

    demo_basic_usage()
    demo_build_system_workflow()
    demo_performance()
    demo_convenience_function()

    print("\n" + "=" * 50)
    print("Demo completed successfully!")
    print("\nKey Benefits:")
    print("- Fast modification time checks avoid expensive MD5 computation")
    print("- Content-based verification prevents false positives")
    print("- Persistent cache survives across tool invocations")
    print("- Significant speedup for incremental builds and testing")
