"""
11 — Full workflow: end-to-end pipeline.

This example runs an end-to-end narrative: create nodes/edges (GeoDataFrames),
create walk DataFrame in superset format, validate_schema, write_walks to temp
Parquet (optionally partitioned). Then read_dataset (or Network + WalkFrame),
chain only_simple_paths, passing_through, filter(time_range=...), edge_frequencies,
compute(). Save network with Network.save(); reload with Network.load() or
connect(); run the same chain again and show identical (or expected) results.
All data stays in a temp directory; script is self-contained.
"""

import shutil
import sys
import tempfile
from datetime import datetime
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
import walkingpandas as wp
from walkingpandas.io.ingest import validate_schema, write_walks, read_dataset

from _data_helpers import (
    make_simple_network_gdf,
    make_simple_walks_df,
    make_string_id_network_gdf,
    make_string_id_walks_df,
    make_walks_with_timestamps,
    write_to_temp_parquet,
)


def main():
    print("=" * 60)
    print("11 — Full workflow")
    print("=" * 60)

    nodes_gdf, edges_gdf = make_simple_network_gdf()
    walks_df = make_simple_walks_df()
    temp_dir = Path(tempfile.mkdtemp())
    try:
        # Write nodes/edges/walks to temp Parquet
        nodes_gdf.to_parquet(temp_dir / "nodes.parquet", index=False)
        edges_gdf.to_parquet(temp_dir / "edges.parquet", index=False)
        validate_schema(walks_df, strict=True)
        write_walks(walks_df, temp_dir / "walks.parquet", schema_validate=True)
        print("\n1. Created nodes/edges/walks and wrote to temp Parquet")

        # read_dataset → chain only_simple_paths, passing_through, edge_frequencies
        walks = read_dataset(
            nodes=temp_dir / "nodes.parquet",
            edges=temp_dir / "edges.parquet",
            walks=temp_dir / "walks.parquet",
        )
        result1 = (
            walks.only_simple_paths()
            .passing_through(1)
            .edge_frequencies()
            .compute()
        )
        print("2. read_dataset → only_simple_paths().passing_through('B').edge_frequencies().compute()")
        print(result1.to_string(index=False))

        # Alternative: infer network from walks (no separate nodes/edges files)
        walks_inferred = wp.WalkFrame.from_walks(temp_dir / "walks.parquet", infer_network=True)
        result_inferred = walks_inferred.only_simple_paths().passing_through(1).edge_frequencies().compute()
        print("2b. WalkFrame.from_walks(..., infer_network=True) → same chain → compute()")
        print(result_inferred.to_string(index=False))

        # Save network to .duckdb
        network = wp.Network(nodes=temp_dir / "nodes.parquet", edges=temp_dir / "edges.parquet")
        db_path = temp_dir / "network.duckdb"
        network.save(db_path)
        print("\n3. Network.save() →", db_path.name)

        # Reload with connect() and run same chain
        walks2 = wp.connect(db_path, walks_path=temp_dir / "walks.parquet")
        result2 = (
            walks2.only_simple_paths()
            .passing_through(1)
            .edge_frequencies()
            .compute()
        )
        print("4. connect() → same chain → compute()")
        print(result2.to_string(index=False))

        # --- Full workflow with string IDs ---
        print("\n--- String-ID end-to-end ---")
        str_nodes, str_edges = make_string_id_network_gdf()
        str_walks = make_string_id_walks_df()

        str_net = wp.Network()
        str_net.add_nodes(str_nodes)
        str_net.add_edges(str_edges)
        str_wf = wp.WalkFrame.from_dataframe(str_walks, network=str_net)

        result_str = (
            str_wf
            .only_simple_paths()
            .passing_through("Station_B")
            .edge_frequencies()
            .compute(decode=True)
        )
        print("5. String IDs → only_simple_paths().passing_through('Station_B').edge_frequencies()")
        print(result_str.to_string(index=False))

        result_raw = (
            str_wf
            .only_simple_paths()
            .passing_through("Station_B")
            .edge_frequencies()
            .compute(decode=False)
        )
        print("\n6. Same chain with decode=False → raw integers")
        print(result_raw.to_string(index=False))

        print("\nDone.")
    finally:
        shutil.rmtree(temp_dir, ignore_errors=True)


if __name__ == "__main__":
    main()
