import { HubConnection, HubConnectionBuilder, LogLevel, HttpTransportType } from '@microsoft/signalr';
import { AppState, AppStateStatus } from 'react-native';
import { SOCKET_URL } from './config';

export interface SocketClient {
  on(event: string, callback: (...args: any[]) => void): void;
  off(event: string, callback?: (...args: any[]) => void): void;
  emit(event: string, ...args: any[]): void;
  disconnect(): void;
  status: string;
}

let connection: HubConnection | null = null;
let socketClient: SocketClient | null = null;
let appStateListener: any = null;

export function connectSocket(token: string): SocketClient {
  if (connection && (connection.state === 'Connected' || connection.state === 'Connecting')) {
    return socketClient!;
  }

  connection = new HubConnectionBuilder()
    .withUrl(SOCKET_URL, {
      accessTokenFactory: () => token,
      transport: HttpTransportType.WebSockets | HttpTransportType.LongPolling,
      skipNegotiation: false,
    })
    .withAutomaticReconnect({
      nextRetryDelayInMilliseconds: retryContext => {
        if (retryContext.elapsedMilliseconds < 10000) return 2000;
        if (retryContext.elapsedMilliseconds < 30000) return 10000;
        return 30000;
      }
    })
    .configureLogging(LogLevel.Information)
    .build();

  socketClient = {
    on: (event: string, callback: (...args: any[]) => void) => {
      connection?.on(event, callback);
    },
    off: (event: string, callback?: (...args: any[]) => void) => {
      if (callback) {
        connection?.off(event, callback);
      } else {
        connection?.off(event);
      }
    },
    emit: (event: string, ...args: any[]) => {
      if (connection?.state === 'Connected') {
        connection.invoke(event, ...args).catch(err => {
          console.error(`SignalR emit error (${event}):`, err);
        });
      } else {
        console.warn(`SignalR emit skipped (${event}): not connected`);
      }
    },
    disconnect: () => {
      if (appStateListener) {
        appStateListener.remove();
        appStateListener = null;
      }
      connection?.stop();
    },
    get status() {
      return connection?.state || 'Disconnected';
    }
  };

  // Lifecycle handling (AppState)
  appStateListener = AppState.addEventListener('change', (nextAppState: AppStateStatus) => {
    if (nextAppState === 'active') {
       if (connection?.state === 'Disconnected') {
         console.log('SignalR: Re-connecting on App Foreground...');
         connection.start().catch(e => console.error('SignalR start error (background to foreground):', e));
       }
    }
  });

  connection.start()
    .then(() => console.log('SignalR: Connected!'))
    .catch(err => console.error('SignalR: Initial connection error:', err));

  return socketClient;
}

export function getSocket(): SocketClient | null {
  return socketClient;
}

export function disconnectSocket() {
  if (socketClient) {
    socketClient.disconnect();
    socketClient = null;
    connection = null;
  }
}
