#!/usr/bin/env python
 
import asyncio
import datetime
import time
import json
import cProfile
import os
import random
import signal
import traceback
from datetime import date
from http import server
import logging

import websockets
from events import *
from functions import *
from functions import saveGameAsync, loadGameAsync
from intradayActivity import *
import tutorial_events
from event_handlers import register_event_handler, call_event_handler, InvalidEventError
import dayEvents
import conversationEvents
from rate_limiter import RateLimiter
from config import config
from event_registry import register_event, get_applicable_events, event_count
from player_cache import PlayerCache
from server.event_registration import register_all_event_handlers, register_all_events
from server.websocket_registry import UserRegistry, USERS, get_websocket_for_player
from server.websocket_messaging import BatchedUpdate, serverClass, ComplexHandler, sendToUser, sendEventMessage, sendUserInfo, sendDict
from server.websocket_handlers import start, shutdown, error, every_minute, handler, initialize_dummy_user

# Setup logging
logger = logging.getLogger(__name__)

# Register all valid event handlers at startup
register_all_event_handlers()

# Register all game events at startup
register_all_events()

print('startup')

# Global instances (imported from server modules)
# USERS is imported from server.websocket_registry
playerRecords = PlayerCache(max_size=config.MAX_CONNECTIONS)
lastIteration = False
server = serverClass()


# Import producer/consumer functions from game_loop module
from game_loop.producer_consumer import producer_handler, consumer_handler
from game_loop.loop_manager import iterateGames

async def main():
    loop = asyncio.get_running_loop()
    stop = loop.create_future()

    loop.add_signal_handler(signal.SIGTERM, stop.set_result, None)

    # Initialize async database pool BEFORE starting server
    from database_async import initialize_pool
    from config import config
    await initialize_pool(pool_size=config.MAX_CONNECTIONS)
    print(f"Database connection pool initialized: size={config.MAX_CONNECTIONS}")

    # Initialize retention systems
    print("Initializing retention systems...")
    from retention.daily_quests import initialize_quest_templates
    from retention.daily_rewards import initialize_daily_rewards
    await initialize_quest_templates()
    await initialize_daily_rewards()
    print("Retention systems initialized")

    port = int(os.environ.get("PORT", "8001"))
    print('running...')

    # Start WebSocket server and get server object for proper shutdown
    ws_server = await websockets.serve(handler, "", port)
    print(f"WebSocket server listening on port {port}")

    # Start the every_minute background task
    minute_task = asyncio.create_task(every_minute())

    await asyncio.sleep(1)  # Adjust the delay as needed

    # Now initialize the dummy user
    await initialize_dummy_user()

    # Wait for SIGTERM signal
    await stop

    # Graceful shutdown sequence
    print("Shutting down gracefully...")

    # 1. Stop accepting new connections
    ws_server.close()

    # 2. Wait for existing connections to close (with timeout)
    try:
        await asyncio.wait_for(ws_server.wait_closed(), timeout=5.0)
        print("WebSocket server closed")
    except asyncio.TimeoutError:
        print("WebSocket server close timed out, forcing shutdown")

    # 3. Cancel background tasks
    minute_task.cancel()
    try:
        await minute_task
    except asyncio.CancelledError:
        pass

    # 4. Close database pool
    from database_async import close_pool
    await close_pool()
    print("Database pool closed")

    print("Shutdown complete")

if __name__ == "__main__":
    asyncio.run(main())