"""
route_manager_node — List, inspect, and delete saved route files.

Provides a management interface for the /data/routes/ directory.
All routes are .jsonl files written by route_recorder_node.

Services:
  /route/list    std_srvs/Trigger  — returns JSON list of all routes in status message
  /route/delete  std_srvs/Trigger  — delete route named by route_name param
  /route/info    std_srvs/Trigger  — return metadata for route named by route_name param

Parameters:
  save_dir     (default /data/routes)
  route_name   (default 'route')   — used by /route/delete and /route/info

Topics published:
  /route/manager_status  std_msgs/String  — last operation result

Response format (in message field):
  /route/list → JSON string: [{"name":..., "distance_m":..., "recorded_at":..., "waypoint_count":...}, ...]
  /route/info → JSON string: {full metadata dict}
  /route/delete → "Deleted: <name>"
"""

import json
import os
from datetime import datetime, timezone

import rclpy
from rclpy.node import Node

from std_msgs.msg import String
from std_srvs.srv import Trigger


class RouteManagerNode(Node):

    def __init__(self):
        super().__init__('route_manager')

        self.declare_parameter('save_dir',    '/data/routes')
        self.declare_parameter('route_name',  'route')

        self._status_pub = self.create_publisher(String, '/route/manager_status', 10)

        self.create_service(Trigger, '/route/list',   self._list_cb)
        self.create_service(Trigger, '/route/delete', self._delete_cb)
        self.create_service(Trigger, '/route/info',   self._info_cb)

        self.get_logger().info('route_manager: ready.')

    # ── Service handlers ──────────────────────────────────────────────────────

    def _list_cb(self, _req, response):
        save_dir = self.get_parameter('save_dir').value
        if not os.path.isdir(save_dir):
            response.success = True
            response.message = '[]'
            return response

        routes = []
        for fname in sorted(os.listdir(save_dir)):
            if not fname.endswith('.jsonl'):
                continue
            path = os.path.join(save_dir, fname)
            try:
                with open(path) as f:
                    meta = json.load(f)
                routes.append({
                    'name':          meta.get('name', fname[:-6]),
                    'distance_m':    meta.get('total_distance_m', 0.0),
                    'duration_s':    meta.get('duration_s', 0.0),
                    'recorded_at':   meta.get('recorded_at', ''),
                    'waypoint_count': meta.get('waypoint_count', 0),
                    'file':          fname,
                })
            except Exception as e:
                self.get_logger().warn(f'route_manager: could not read {fname}: {e}')

        result = json.dumps(routes)
        self._pub_status(f'list:{len(routes)}_routes')
        response.success = True
        response.message = result
        self.get_logger().info(f'route_manager: listed {len(routes)} routes')
        return response

    def _delete_cb(self, _req, response):
        name     = self.get_parameter('route_name').value
        save_dir = self.get_parameter('save_dir').value
        path     = os.path.join(save_dir, f'{name}.jsonl')

        if not os.path.exists(path):
            response.success = False
            response.message = f'Route not found: {name}'
            return response

        os.remove(path)
        self._pub_status(f'deleted:{name}')
        self.get_logger().info(f'route_manager: deleted "{name}"')
        response.success = True
        response.message = f'Deleted: {name}'
        return response

    def _info_cb(self, _req, response):
        name     = self.get_parameter('route_name').value
        save_dir = self.get_parameter('save_dir').value
        path     = os.path.join(save_dir, f'{name}.jsonl')

        if not os.path.exists(path):
            response.success = False
            response.message = f'Route not found: {name}'
            return response

        try:
            with open(path) as f:
                meta = json.load(f)
            # Return metadata without the full waypoints array (can be large)
            info = {k: v for k, v in meta.items() if k != 'waypoints'}
            result = json.dumps(info, indent=2)
            self._pub_status(f'info:{name}')
            response.success = True
            response.message = result
        except Exception as e:
            response.success = False
            response.message = f'Error reading route: {e}'
        return response

    # ── Helpers ───────────────────────────────────────────────────────────────

    def _pub_status(self, s: str) -> None:
        msg = String()
        msg.data = s
        self._status_pub.publish(msg)


def main(args=None):
    rclpy.init(args=args)
    node = RouteManagerNode()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    finally:
        node.destroy_node()
        rclpy.try_shutdown()


if __name__ == '__main__':
    main()
