#!/usr/bin/env python3
"""
Miku Discord Bot CLI
A command-line interface for interacting with the Miku Discord bot API.
"""

import requests
import argparse
import sys
import json
import shlex
from typing import Optional, Dict, Any
from pathlib import Path

# Default API base URL
DEFAULT_API_URL = "http://192.168.1.2:3939"

class MikuCLI:
    def __init__(self, base_url: str = DEFAULT_API_URL):
        self.base_url = base_url.rstrip('/')
    
    def _get(self, endpoint: str) -> Dict[str, Any]:
        """Make a GET request to the API."""
        try:
            response = requests.get(f"{self.base_url}{endpoint}")
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"❌ Error: {e}")
            sys.exit(1)
    
    def _post(self, endpoint: str, data: Optional[Dict] = None, json_data: Optional[Dict] = None, files: Optional[Dict] = None) -> Dict[str, Any]:
        """Make a POST request to the API."""
        try:
            response = requests.post(f"{self.base_url}{endpoint}", data=data, json=json_data, files=files)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"❌ Error: {e}")
            if hasattr(e.response, 'text'):
                print(f"Response: {e.response.text}")
            sys.exit(1)
    
    def _delete(self, endpoint: str) -> Dict[str, Any]:
        """Make a DELETE request to the API."""
        try:
            response = requests.delete(f"{self.base_url}{endpoint}")
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"❌ Error: {e}")
            sys.exit(1)
    
    def _put(self, endpoint: str, json_data: Dict) -> Dict[str, Any]:
        """Make a PUT request to the API."""
        try:
            response = requests.put(f"{self.base_url}{endpoint}", json=json_data)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"❌ Error: {e}")
            sys.exit(1)
    
    # ========== Status & Info ==========
    def get_status(self):
        """Get bot status."""
        result = self._get("/status")
        print(f"✅ Bot Status: {result['status']}")
        print(f"😊 DM Mood: {result['mood']}")
        print(f"🌐 Servers: {result['servers']}")
        print(f"📊 Active Schedulers: {result['active_schedulers']}")
        if result.get('server_moods'):
            print("\n📋 Server Moods:")
            for guild_id, mood in result['server_moods'].items():
                print(f"  Server {guild_id}: {mood}")
    
    def get_logs(self):
        """Get recent bot logs."""
        result = self._get("/logs")
        print(result)
    
    def get_prompt(self):
        """Get last prompt sent to LLM."""
        result = self._get("/prompt")
        print(f"Last prompt:\n{result['prompt']}")
    
    # ========== Mood Management ==========
    def get_mood(self, guild_id: Optional[int] = None):
        """Get current mood (global or per-server)."""
        if guild_id:
            result = self._get(f"/servers/{guild_id}/mood")
            print(f"😊 Server {guild_id} Mood: {result['mood']}")
            print(f"📝 Description: {result['description']}")
        else:
            result = self._get("/mood")
            print(f"😊 DM Mood: {result['mood']}")
            print(f"📝 Description: {result['description']}")
    
    def set_mood(self, mood: str, guild_id: Optional[int] = None):
        """Set mood (global or per-server)."""
        if guild_id:
            result = self._post(f"/servers/{guild_id}/mood", json_data={"mood": mood})
        else:
            result = self._post("/mood", json_data={"mood": mood})
        
        if result['status'] == 'ok':
            print(f"✅ Mood set to: {result['new_mood']}")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def reset_mood(self, guild_id: Optional[int] = None):
        """Reset mood to neutral."""
        if guild_id:
            result = self._post(f"/servers/{guild_id}/mood/reset")
        else:
            result = self._post("/mood/reset")
        
        if result['status'] == 'ok':
            print(f"✅ Mood reset to neutral")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def list_moods(self):
        """List available moods."""
        result = self._get("/moods/available")
        print("Available moods:")
        for mood, emoji in result['moods'].items():
            print(f"  {emoji} {mood}")
    
    # ========== Sleep Management ==========
    def sleep(self):
        """Put Miku to sleep."""
        result = self._post("/sleep")
        print(f"✅ {result['message']}")
    
    def wake(self):
        """Wake Miku up."""
        result = self._post("/wake")
        print(f"✅ {result['message']}")
    
    # ========== Autonomous Actions ==========
    def autonomous_general(self, guild_id: Optional[int] = None):
        """Trigger general autonomous message."""
        if guild_id:
            result = self._post(f"/autonomous/general?guild_id={guild_id}")
        else:
            result = self._post("/autonomous/general")
        print(f"✅ {result['message']}")
    
    def autonomous_engage(self, guild_id: Optional[int] = None):
        """Trigger autonomous user engagement."""
        if guild_id:
            result = self._post(f"/autonomous/engage?guild_id={guild_id}")
        else:
            result = self._post("/autonomous/engage")
        print(f"✅ {result['message']}")
    
    def autonomous_tweet(self, guild_id: Optional[int] = None):
        """Trigger autonomous tweet sharing."""
        if guild_id:
            result = self._post(f"/autonomous/tweet?guild_id={guild_id}")
        else:
            result = self._post("/autonomous/tweet")
        print(f"✅ {result['message']}")
    
    def autonomous_reaction(self, guild_id: Optional[int] = None):
        """Trigger autonomous reaction."""
        if guild_id:
            result = self._post(f"/autonomous/reaction?guild_id={guild_id}")
        else:
            result = self._post("/autonomous/reaction")
        print(f"✅ {result['message']}")
    
    def autonomous_join_conversation(self, guild_id: Optional[int] = None):
        """Trigger detect and join conversation."""
        if guild_id:
            result = self._post(f"/autonomous/join-conversation?guild_id={guild_id}")
        else:
            result = self._post("/autonomous/join-conversation")
        print(f"✅ {result['message']}")
    
    def autonomous_custom(self, prompt: str, guild_id: Optional[int] = None):
        """Send custom autonomous message."""
        if guild_id:
            result = self._post(f"/autonomous/custom?guild_id={guild_id}", json_data={"prompt": prompt})
        else:
            result = self._post("/autonomous/custom", json_data={"prompt": prompt})
        print(f"✅ {result['message']}")
    
    def autonomous_stats(self):
        """Get autonomous engine stats."""
        result = self._get("/autonomous/stats")
        print(json.dumps(result, indent=2))
    
    # ========== Server Management ==========
    def list_servers(self):
        """List all configured servers."""
        result = self._get("/servers")
        if not result.get('servers'):
            print("No servers configured")
            return
        
        print(f"\n📋 Configured Servers ({len(result['servers'])}):\n")
        for server in result['servers']:
            print(f"🌐 {server['guild_name']} (ID: {server['guild_id']})")
            print(f"   Channel: #{server['autonomous_channel_name']} (ID: {server['autonomous_channel_id']})")
            if server.get('bedtime_channel_ids'):
                print(f"   Bedtime Channels: {server['bedtime_channel_ids']}")
            if server.get('enabled_features'):
                print(f"   Features: {', '.join(server['enabled_features'])}")
            print()
    
    def bedtime(self, guild_id: Optional[int] = None):
        """Send bedtime reminder."""
        if guild_id:
            result = self._post(f"/bedtime?guild_id={guild_id}")
        else:
            result = self._post("/bedtime")
        print(f"✅ {result['message']}")
    
    # ========== DM Management ==========
    def list_dm_users(self):
        """List all users with DM history."""
        result = self._get("/dms/users")
        if not result.get('users'):
            print("No DM users found")
            return
        
        print(f"\n💬 Users with DM History ({len(result['users'])}):\n")
        for user in result['users']:
            print(f"\n👤 {user.get('username', 'Unknown')} (ID: {user.get('user_id', 'N/A')})")
            if 'message_count' in user:
                print(f"   Messages: {user['message_count']}")
            if 'last_message_date' in user:
                print(f"   Last seen: {user['last_message_date']}")
            elif 'last_seen' in user:
                print(f"   Last seen: {user['last_seen']}")
            elif 'timestamp' in user:
                print(f"   Last seen: {user['timestamp']}")
            if user.get('is_blocked'):
                print(f"   ⛔ BLOCKED")
            print()
    
    def dm_custom(self, user_id: str, prompt: str):
        """Send custom DM to user."""
        result = self._post(f"/dm/{user_id}/custom", json_data={"prompt": prompt})
        if result['status'] == 'ok':
            print(f"✅ Custom DM queued for user {user_id}")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def dm_manual(self, user_id: str, message: str):
        """Send manual DM to user."""
        result = self._post(f"/dm/{user_id}/manual", data={"message": message})
        if result['status'] == 'ok':
            print(f"✅ Manual DM sent to user {user_id}")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def block_user(self, user_id: str):
        """Block a user from DMing."""
        result = self._post(f"/dms/users/{user_id}/block")
        if result['status'] == 'ok':
            print(f"✅ User {user_id} blocked")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def unblock_user(self, user_id: str):
        """Unblock a user."""
        result = self._post(f"/dms/users/{user_id}/unblock")
        if result['status'] == 'ok':
            print(f"✅ User {user_id} unblocked")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def list_blocked_users(self):
        """List blocked users."""
        result = self._get("/dms/blocked-users")
        if not result.get('blocked_users'):
            print("No blocked users")
            return
        
        print(f"\n⛔ Blocked Users ({len(result['blocked_users'])}):\n")
        for user_id, username in result['blocked_users'].items():
            print(f"  {username} (ID: {user_id})")
    
    # ========== Profile Picture ==========
    def change_profile_picture(self, image_path: Optional[str] = None, guild_id: Optional[int] = None):
        """Change profile picture."""
        files = None
        if image_path:
            files = {'file': open(image_path, 'rb')}
        
        params = f"?guild_id={guild_id}" if guild_id else ""
        result = self._post(f"/profile-picture/change{params}", files=files)
        
        if result['status'] == 'ok':
            print(f"✅ {result['message']}")
            print(f"📸 Source: {result['source']}")
            if result.get('metadata'):
                print(f"📝 Metadata: {json.dumps(result['metadata'], indent=2)}")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")
    
    def get_profile_metadata(self):
        """Get profile picture metadata."""
        result = self._get("/profile-picture/metadata")
        if result.get('metadata'):
            print(json.dumps(result['metadata'], indent=2))
        else:
            print("No metadata found")
    
    # ========== Conversation Management ==========
    def reset_conversation(self, user_id: str):
        """Reset conversation history for a user."""
        result = self._post("/conversation/reset", json_data={"user_id": user_id})
        print(f"✅ {result['message']}")
    
    # ========== Manual Send ==========
    def manual_send(self, channel_id: str, message: str, files: Optional[list] = None):
        """Send manual message to a channel."""
        data = {"channel_id": channel_id, "message": message}
        file_data = {}
        
        if files:
            for i, file_path in enumerate(files):
                file_data[f'files'] = open(file_path, 'rb')
        
        result = self._post("/manual/send", data=data, files=file_data if file_data else None)
        
        if result['status'] == 'ok':
            print(f"✅ {result['message']}")
        else:
            print(f"❌ Error: {result.get('message', 'Unknown error')}")


def interactive_shell(base_url: str = DEFAULT_API_URL):
    """Run an interactive shell for Miku CLI commands."""
    cli = MikuCLI(base_url)
    
    print("╔══════════════════════════════════════════╗")
    print("║     Miku Discord Bot - Interactive      ║")
    print("║           Shell Mode v1.0                ║")
    print("╚══════════════════════════════════════════╝")
    print(f"\n🌐 Connected to: {base_url}")
    print("💡 Type 'help' for available commands")
    print("💡 Type 'exit' or 'quit' to leave\n")
    
    while True:
        try:
            # Get user input
            user_input = input("miku> ").strip()
            
            if not user_input:
                continue
            
            # Parse the command
            try:
                parts = shlex.split(user_input)
            except ValueError as e:
                print(f"❌ Invalid command syntax: {e}")
                continue
            
            command = parts[0].lower()
            args = parts[1:] if len(parts) > 1 else []
            
            # Handle built-in commands
            if command in ['exit', 'quit', 'q']:
                print("\n👋 Goodbye!")
                break
            elif command == 'help':
                print_help()
                continue
            elif command == 'clear':
                print("\033[H\033[J", end="")
                continue
            
            # Execute Miku commands
            try:
                execute_command(cli, command, args)
            except Exception as e:
                print(f"❌ Error executing command: {e}")
                
        except KeyboardInterrupt:
            print("\n\n👋 Goodbye!")
            break
        except EOFError:
            print("\n\n👋 Goodbye!")
            break


def print_help():
    """Print help for interactive mode."""
    help_text = """
📖 Available Commands:

  Status & Info:
    status                    - Get bot status
    logs                      - Get recent logs
    prompt                    - Get current prompt
    servers                   - List all servers
    
  Mood Management:
    mood-list                 - List available moods
    mood-get [server_id]      - Get current mood
    mood-set <mood> [server_id] - Set mood
    mood-reset [server_id]    - Reset mood to neutral
    
  Sleep/Wake:
    sleep                     - Put bot to sleep
    wake                      - Wake the bot up
    bedtime [server_id]       - Set bedtime for server
    
  Autonomous Actions:
    autonomous-general [server_id]  - Generate general message
    autonomous-engage [server_id]   - Engage with conversation
    autonomous-tweet [server_id]    - Post tweet-style message
    autonomous-reaction [server_id] - Generate reaction
    autonomous-join-conversation [server_id] - Detect and join conversation
    autonomous-custom <prompt> [server_id] - Custom autonomous action
    autonomous-stats                - Show autonomous statistics
    
  DM Management:
    dm-users                  - List users with DM history
    dm-custom <user_id> <prompt> - Send custom DM
    dm-manual <user_id> <msg> - Send manual DM
    reset-conversation <user_id> - Reset conversation history
    
  User Blocking:
    block <user_id>           - Block a user
    unblock <user_id>         - Unblock a user
    blocked-users             - List blocked users
    
  Profile Pictures:
    change-pfp [image_path] [server_id] - Change profile picture
    pfp-metadata              - Get profile picture metadata
    
  Manual Actions:
    send <channel_id> <message> - Send message to channel
    
  Shell Commands:
    help                      - Show this help
    clear                     - Clear screen
    exit, quit, q             - Exit interactive mode
"""
    print(help_text)


def execute_command(cli: MikuCLI, command: str, args: list):
    """Execute a command in interactive mode."""
    
    # Status & Info
    if command == 'status':
        cli.get_status()
    elif command == 'logs':
        cli.get_logs()
    elif command == 'prompt':
        cli.get_prompt()
    elif command == 'servers':
        cli.list_servers()
    
    # Mood Management
    elif command == 'mood-list':
        cli.list_moods()
    elif command == 'mood-get':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.get_mood(server_id)
    elif command == 'mood-set':
        if not args:
            print("❌ Usage: mood-set <mood> [server_id]")
            return
        mood = args[0]
        server_id = int(args[1]) if len(args) > 1 and args[1].isdigit() else None
        cli.set_mood(mood, server_id)
    elif command == 'mood-reset':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.reset_mood(server_id)
    
    # Sleep/Wake
    elif command == 'sleep':
        cli.sleep()
    elif command == 'wake':
        cli.wake()
    elif command == 'bedtime':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.bedtime(server_id)
    
    # Autonomous Actions
    elif command == 'autonomous-general':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.autonomous_general(server_id)
    elif command == 'autonomous-engage':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.autonomous_engage(server_id)
    elif command == 'autonomous-tweet':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.autonomous_tweet(server_id)
    elif command == 'autonomous-reaction':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.autonomous_reaction(server_id)
    elif command == 'autonomous-join-conversation':
        server_id = int(args[0]) if args and args[0].isdigit() else None
        cli.autonomous_join_conversation(server_id)
    elif command == 'autonomous-custom':
        if not args:
            print("❌ Usage: autonomous-custom <prompt> [server_id]")
            return
        # Find server_id if provided
        server_id = None
        prompt_parts = []
        for arg in args:
            if arg.isdigit():
                server_id = int(arg)
            else:
                prompt_parts.append(arg)
        prompt = ' '.join(prompt_parts)
        cli.autonomous_custom(prompt, server_id)
    elif command == 'autonomous-stats':
        cli.autonomous_stats()
    
    # DM Management
    elif command == 'dm-users':
        cli.list_dm_users()
    elif command == 'dm-custom':
        if len(args) < 2:
            print("❌ Usage: dm-custom <user_id> <prompt>")
            return
        user_id = args[0]
        prompt = ' '.join(args[1:])
        cli.dm_custom(user_id, prompt)
    elif command == 'dm-manual':
        if len(args) < 2:
            print("❌ Usage: dm-manual <user_id> <message>")
            return
        user_id = args[0]
        message = ' '.join(args[1:])
        cli.dm_manual(user_id, message)
    elif command == 'reset-conversation':
        if not args:
            print("❌ Usage: reset-conversation <user_id>")
            return
        cli.reset_conversation(args[0])
    
    # User Blocking
    elif command == 'block':
        if not args:
            print("❌ Usage: block <user_id>")
            return
        cli.block_user(args[0])
    elif command == 'unblock':
        if not args:
            print("❌ Usage: unblock <user_id>")
            return
        cli.unblock_user(args[0])
    elif command == 'blocked-users':
        cli.list_blocked_users()
    
    # Profile Pictures
    elif command == 'change-pfp':
        image_path = args[0] if args else None
        server_id = int(args[1]) if len(args) > 1 and args[1].isdigit() else None
        cli.change_profile_picture(image_path, server_id)
    elif command == 'pfp-metadata':
        cli.get_profile_metadata()
    
    # Manual Actions
    elif command == 'send':
        if len(args) < 2:
            print("❌ Usage: send <channel_id> <message>")
            return
        channel_id = args[0]
        message = ' '.join(args[1:])
        cli.manual_send(channel_id, message)
    
    else:
        print(f"❌ Unknown command: {command}")
        print("💡 Type 'help' for available commands")


def main():
    parser = argparse.ArgumentParser(
        description="Miku Discord Bot CLI",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s status                          # Get bot status
  %(prog)s mood --get                      # Get current DM mood
  %(prog)s mood --set bubbly               # Set DM mood to bubbly
  %(prog)s mood --set excited --server 123 # Set server mood
  %(prog)s mood --list                     # List available moods
  %(prog)s autonomous general --server 123 # Trigger autonomous message
  %(prog)s servers                         # List all servers
  %(prog)s dm-users                        # List DM users
  %(prog)s sleep                           # Put Miku to sleep
  %(prog)s wake                            # Wake Miku up
        """
    )
    
    parser.add_argument('--url', default=DEFAULT_API_URL, help=f'API base URL (default: {DEFAULT_API_URL})')
    
    subparsers = parser.add_subparsers(dest='command', help='Command to execute')
    
    # Shell mode
    subparsers.add_parser('shell', help='Start interactive shell mode')
    
    # Status commands
    subparsers.add_parser('status', help='Get bot status')
    subparsers.add_parser('logs', help='Get recent logs')
    subparsers.add_parser('prompt', help='Get last LLM prompt')
    
    # Mood commands
    mood_parser = subparsers.add_parser('mood', help='Mood management')
    mood_parser.add_argument('--get', action='store_true', help='Get current mood')
    mood_parser.add_argument('--set', metavar='MOOD', help='Set mood')
    mood_parser.add_argument('--reset', action='store_true', help='Reset mood to neutral')
    mood_parser.add_argument('--list', action='store_true', help='List available moods')
    mood_parser.add_argument('--server', type=int, help='Server/guild ID')
    
    # Sleep commands
    subparsers.add_parser('sleep', help='Put Miku to sleep')
    subparsers.add_parser('wake', help='Wake Miku up')
    
    # Autonomous commands
    auto_parser = subparsers.add_parser('autonomous', help='Autonomous actions')
    auto_parser.add_argument('action', choices=['general', 'engage', 'tweet', 'reaction', 'join-conversation', 'custom', 'stats'])
    auto_parser.add_argument('--prompt', help='Custom prompt (for custom action)')
    auto_parser.add_argument('--server', type=int, help='Server/guild ID')
    
    # Server commands
    subparsers.add_parser('servers', help='List configured servers')
    
    bedtime_parser = subparsers.add_parser('bedtime', help='Send bedtime reminder')
    bedtime_parser.add_argument('--server', type=int, help='Server/guild ID')
    
    # DM commands
    subparsers.add_parser('dm-users', help='List users with DM history')
    
    dm_custom_parser = subparsers.add_parser('dm-custom', help='Send custom DM')
    dm_custom_parser.add_argument('user_id', help='User ID')
    dm_custom_parser.add_argument('prompt', help='Custom prompt')
    
    dm_manual_parser = subparsers.add_parser('dm-manual', help='Send manual DM')
    dm_manual_parser.add_argument('user_id', help='User ID')
    dm_manual_parser.add_argument('message', help='Message to send')
    
    block_parser = subparsers.add_parser('block', help='Block a user')
    block_parser.add_argument('user_id', help='User ID')
    
    unblock_parser = subparsers.add_parser('unblock', help='Unblock a user')
    unblock_parser.add_argument('user_id', help='User ID')
    
    subparsers.add_parser('blocked-users', help='List blocked users')
    
    # Profile picture commands
    pfp_parser = subparsers.add_parser('change-pfp', help='Change profile picture')
    pfp_parser.add_argument('--image', help='Path to image file')
    pfp_parser.add_argument('--server', type=int, help='Server/guild ID')
    
    subparsers.add_parser('pfp-metadata', help='Get profile picture metadata')
    
    # Conversation commands
    conv_parser = subparsers.add_parser('reset-conversation', help='Reset conversation history')
    conv_parser.add_argument('user_id', help='User ID')
    
    # Manual send command
    send_parser = subparsers.add_parser('send', help='Send manual message to channel')
    send_parser.add_argument('channel_id', help='Channel ID')
    send_parser.add_argument('message', help='Message to send')
    send_parser.add_argument('--files', nargs='+', help='File paths to attach')
    
    args = parser.parse_args()
    
    # If no command provided, start shell mode
    if not args.command:
        interactive_shell(args.url)
        sys.exit(0)
    
    # If shell command, start interactive mode
    if args.command == 'shell':
        interactive_shell(args.url)
        sys.exit(0)
    
    cli = MikuCLI(args.url)
    
    # Execute commands
    try:
        if args.command == 'status':
            cli.get_status()
        elif args.command == 'logs':
            cli.get_logs()
        elif args.command == 'prompt':
            cli.get_prompt()
        elif args.command == 'mood':
            if args.list:
                cli.list_moods()
            elif args.get:
                cli.get_mood(args.server)
            elif args.set:
                cli.set_mood(args.set, args.server)
            elif args.reset:
                cli.reset_mood(args.server)
            else:
                mood_parser.print_help()
        elif args.command == 'sleep':
            cli.sleep()
        elif args.command == 'wake':
            cli.wake()
        elif args.command == 'autonomous':
            if args.action == 'general':
                cli.autonomous_general(args.server)
            elif args.action == 'engage':
                cli.autonomous_engage(args.server)
            elif args.action == 'tweet':
                cli.autonomous_tweet(args.server)
            elif args.action == 'reaction':
                cli.autonomous_reaction(args.server)
            elif args.action == 'join-conversation':
                cli.autonomous_join_conversation(args.server)
            elif args.action == 'custom':
                if not args.prompt:
                    print("❌ --prompt is required for custom action")
                    sys.exit(1)
                cli.autonomous_custom(args.prompt, args.server)
            elif args.action == 'stats':
                cli.autonomous_stats()
        elif args.command == 'servers':
            cli.list_servers()
        elif args.command == 'bedtime':
            cli.bedtime(args.server)
        elif args.command == 'dm-users':
            cli.list_dm_users()
        elif args.command == 'dm-custom':
            cli.dm_custom(args.user_id, args.prompt)
        elif args.command == 'dm-manual':
            cli.dm_manual(args.user_id, args.message)
        elif args.command == 'block':
            cli.block_user(args.user_id)
        elif args.command == 'unblock':
            cli.unblock_user(args.user_id)
        elif args.command == 'blocked-users':
            cli.list_blocked_users()
        elif args.command == 'change-pfp':
            cli.change_profile_picture(args.image, args.server)
        elif args.command == 'pfp-metadata':
            cli.get_profile_metadata()
        elif args.command == 'reset-conversation':
            cli.reset_conversation(args.user_id)
        elif args.command == 'send':
            cli.manual_send(args.channel_id, args.message, args.files)
    except KeyboardInterrupt:
        print("\n\n👋 Bye!")
        sys.exit(0)


if __name__ == '__main__':
    main()
