"""
Parking MCP Server - A Model Context Protocol server for parking system.
Provides tools to query user info, parking plans, orders, and parking space status.
"""

import asyncio
import sqlite3
import os
import json
import sys
from typing import Any, Optional

from mcp.server import Server
from mcp.types import Tool, TextContent
from mcp.server.stdio import stdio_server


class ParkingMCPServer:
    """Parking system MCP server implementation."""
    
    def __init__(self, db_path: Optional[str] = None):
        """
        Initialize the MCP server.
        
        Args:
            db_path: Path to SQLite database file. If None, uses environment variable
                    PARKING_DB_PATH or defaults to packaged 'parking.db' or current directory.
        """
        if db_path:
            # Use explicitly provided path
            self.db_path = db_path
        elif os.environ.get('PARKING_DB_PATH'):
            # Use environment variable
            self.db_path = os.environ.get('PARKING_DB_PATH')
        else:
            # Check for packaged database
            packaged_db = os.path.join(os.path.dirname(__file__), 'parking.db')
            if os.path.exists(packaged_db):
                # Use packaged database
                self.db_path = packaged_db
            else:
                # Fall back to current directory
                self.db_path = 'parking.db'
        
        self.app = Server("parking-mcp-server")
        self._setup_tools()
        
        # Print startup info to stderr
        print(f"🚀 Parking MCP Server starting...", file=sys.stderr)
        print(f"📊 Database: {os.path.abspath(self.db_path)}", file=sys.stderr)
        print(f"🛠️  Available tools: get_user_info, get_user_parking_plans, get_user_orders, get_parking_space_status", file=sys.stderr)
        print(f"⏳ Waiting for MCP client connection...", file=sys.stderr)
        print("=" * 60, file=sys.stderr)
    
    def _setup_tools(self):
        """Setup MCP tools."""
        
        @self.app.list_tools()
        async def list_tools() -> list[Tool]:
            """List available tools."""
            return [
                Tool(
                    name="get_user_info",
                    description="Query user basic information, parking habits, common parking lots, etc.",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "user_id": {
                                "type": "integer",
                                "description": "User ID"
                            }
                        },
                        "required": ["user_id"]
                    }
                ),
                Tool(
                    name="get_user_parking_plans",
                    description="Query today's parking plans for a specific user",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "user_id": {
                                "type": "integer",
                                "description": "User ID"
                            }
                        },
                        "required": ["user_id"]
                    }
                ),
                Tool(
                    name="get_user_orders",
                    description="Query parking orders (history + current) for a specific user",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "user_id": {
                                "type": "integer",
                                "description": "User ID"
                            }
                        },
                        "required": ["user_id"]
                    }
                ),
                Tool(
                    name="get_parking_space_status",
                    description="Query parking space occupancy status",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "park_id": {
                                "type": "string",
                                "description": "Parking lot ID (optional, leave empty to query all)"
                            }
                        }
                    }
                )
            ]
        
        @self.app.call_tool()
        async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
            """Handle tool calls."""
            
            if name == "get_user_info":
                return self._get_user_info(arguments)
            elif name == "get_user_parking_plans":
                return self._get_user_parking_plans(arguments)
            elif name == "get_user_orders":
                return self._get_user_orders(arguments)
            elif name == "get_parking_space_status":
                return self._get_parking_space_status(arguments)
            else:
                return [TextContent(type="text", text=f"Unknown tool: {name}")]
    
    def _get_db_connection(self):
        """Get database connection."""
        if not os.path.exists(self.db_path):
            raise FileNotFoundError(f"Database file not found: {self.db_path}")
        
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        return conn
    
    def _get_user_info(self, arguments: dict[str, Any]) -> list[TextContent]:
        """Get user information."""
        user_id = arguments.get("user_id")
        if not user_id:
            return [TextContent(type="text", text="Error: Missing user_id parameter")]
        
        try:
            with self._get_db_connection() as conn:
                user = conn.execute(
                    """SELECT user_id, user_name, plate_number, phone_number, 
                              payment_habit, parking_habit, working_time, offwork_time,
                              common_park_ids, common_park_label, is_wechat_bound,
                              create_time
                       FROM t_users WHERE user_id = ?""",
                    (user_id,)
                ).fetchone()
                
                if not user:
                    return [TextContent(type="text", text=f"User {user_id} not found")]
                
                user_dict = dict(user)
                result = {
                    "user_info": {
                        "user_id": user_dict["user_id"],
                        "name": user_dict["user_name"],
                        "plate_number": user_dict["plate_number"] or "None",
                        "phone_number": user_dict["phone_number"] or "None",
                        "payment_habit": user_dict["payment_habit"],
                        "parking_habit": user_dict["parking_habit"],
                        "working_time": user_dict["working_time"] or "None",
                        "offwork_time": user_dict["offwork_time"] or "None",
                        "common_park_ids": user_dict["common_park_ids"] or "None",
                        "common_park_label": user_dict["common_park_label"] or "None",
                        "is_wechat_bound": bool(user_dict["is_wechat_bound"]),
                        "created_at": user_dict["create_time"]
                    }
                }
                
                return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=f"Database error: {e}")]
    
    def _get_user_parking_plans(self, arguments: dict[str, Any]) -> list[TextContent]:
        """Get user parking plans."""
        user_id = arguments.get("user_id")
        if not user_id:
            return [TextContent(type="text", text="Error: Missing user_id parameter")]
        
        try:
            with self._get_db_connection() as conn:
                plans = conn.execute(
                    """SELECT id, parking_in_time, parking_out_time, 
                              target_zones, status, plan_date
                       FROM t_will_parking 
                       WHERE user_id = ? 
                       ORDER BY parking_in_time""",
                    (user_id,)
                ).fetchall()
                
                if not plans:
                    return [TextContent(type="text", text=f"User {user_id} has no parking plans")]
                
                status_map = {0: "pending", 1: "active", 2: "completed", -1: "cancelled"}
                plan_list = []
                for plan in plans:
                    plan_dict = dict(plan)
                    plan_list.append({
                        "plan_id": plan_dict["id"],
                        "entry_time": plan_dict["parking_in_time"],
                        "exit_time": plan_dict["parking_out_time"],
                        "target_zones": plan_dict["target_zones"],
                        "status": status_map.get(plan_dict["status"], str(plan_dict["status"])),
                        "plan_date": plan_dict["plan_date"]
                    })
                
                result = {"parking_plans": plan_list}
                return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=f"Database error: {e}")]
    
    def _get_user_orders(self, arguments: dict[str, Any]) -> list[TextContent]:
        """Get user parking orders."""
        user_id = arguments.get("user_id")
        if not user_id:
            return [TextContent(type="text", text="Error: Missing user_id parameter")]
        
        try:
            with self._get_db_connection() as conn:
                orders = conn.execute(
                    """SELECT order_id, space_id, park_id, 
                              start_time, end_time
                       FROM t_parking_orders 
                       WHERE user_id = ? 
                       ORDER BY start_time DESC""",
                    (user_id,)
                ).fetchall()
                
                if not orders:
                    return [TextContent(type="text", text=f"User {user_id} has no parking orders")]
                
                order_list = []
                for order in orders:
                    order_dict = dict(order)
                    order_list.append({
                        "order_id": order_dict["order_id"],
                        "space_id": order_dict["space_id"],
                        "park_id": order_dict["park_id"],
                        "entry_time": order_dict["start_time"],
                        "exit_time": order_dict["end_time"] or "in_progress",
                        "status": "completed" if order_dict["end_time"] else "in_progress"
                    })
                
                result = {"parking_orders": order_list}
                return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=f"Database error: {e}")]
    
    def _get_parking_space_status(self, arguments: dict[str, Any]) -> list[TextContent]:
        """Get parking space status."""
        park_id = arguments.get("park_id")
        
        try:
            with self._get_db_connection() as conn:
                if park_id:
                    spaces = conn.execute(
                        """SELECT space_id, park_id, zone_type, is_used, used_time
                           FROM t_parking_space 
                           WHERE park_id = ?
                           ORDER BY space_id""",
                        (park_id,)
                    ).fetchall()
                else:
                    spaces = conn.execute(
                        """SELECT space_id, park_id, zone_type, is_used, used_time
                           FROM t_parking_space 
                           ORDER BY park_id, space_id"""
                    ).fetchall()
                
                if not spaces:
                    return [TextContent(type="text", text="No parking space data found")]
                
                park_stats = {}
                for space in spaces:
                    space_dict = dict(space)
                    park_id = space_dict["park_id"]
                    
                    if park_id not in park_stats:
                        park_stats[park_id] = {
                            "park_id": park_id,
                            "zone_type": space_dict["zone_type"],
                            "total_spaces": 0,
                            "occupied": 0,
                            "available": 0,
                            "spaces": []
                        }
                    
                    park_stats[park_id]["total_spaces"] += 1
                    if space_dict["is_used"]:
                        park_stats[park_id]["occupied"] += 1
                    else:
                        park_stats[park_id]["available"] += 1
                    
                    park_stats[park_id]["spaces"].append({
                        "space_id": space_dict["space_id"],
                        "status": "occupied" if space_dict["is_used"] else "available",
                        "used_since": space_dict["used_time"] or "-"
                    })
                
                result = {"parking_lots": list(park_stats.values())}
                return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=f"Database error: {e}")]
    
    async def run(self):
        """Run the MCP server."""
        try:
            # Test database connection
            with self._get_db_connection() as conn:
                conn.execute("SELECT 1")
            
            async with stdio_server() as streams:
                await self.app.run(
                    streams[0],
                    streams[1],
                    self.app.create_initialization_options()
                )
        except Exception as e:
            print(f"Server error: {e}", file=sys.stderr)
            import traceback
            traceback.print_exc(file=sys.stderr)
            sys.exit(1)


def main():
    """Main entry point."""
    import argparse
    
    parser = argparse.ArgumentParser(description="Parking MCP Server")
    parser.add_argument(
        "--db-path",
        help="Path to SQLite database file",
        default=os.environ.get("PARKING_DB_PATH", "parking.db")
    )
    
    args = parser.parse_args()
    
    server = ParkingMCPServer(db_path=args.db_path)
    asyncio.run(server.run())


if __name__ == "__main__":
    main()
