import { ref } from 'vue'
import type { AuthMessage, AuthResponseMessage } from '../types/sync'

export interface WebSocketMessage {
  type: string
  [key: string]: any
}

export type MessageHandler = (message: WebSocketMessage) => void

export interface AuthResult {
  success: boolean
  needsConfirmation: boolean
  message: string
}

class WebSocketManager {
  private ws: WebSocket | null = null
  private handlers: Set<MessageHandler> = new Set()
  private reconnectTimeout: number | null = null
  public isConnected = ref(false)
  public isAuthenticated = ref(false)
  private authResolve: ((result: AuthResult) => void) | null = null
  private shouldReconnect = false  // Disable auto-reconnect (user must re-authenticate)
  private storedPassword: string | null = null
  private storedConfirmPassword: string | undefined = undefined

  async connect(
    password: string,
    confirmPassword?: string,
    changeToPassword?: string,
    confirmNewPassword?: string
  ): Promise<AuthResult> {
    // Store password for potential reconnection
    this.storedPassword = password
    this.storedConfirmPassword = confirmPassword

    // Close existing connection if any
    if (this.ws) {
      this.shouldReconnect = false
      this.ws.close()
      this.ws = null
    }

    return new Promise((resolve, reject) => {
      // Use env variable for WebSocket URL, fallback to localhost for dev
      const wsUrl = import.meta.env.VITE_WS_URL || 'ws://localhost:8080/ws'
      this.ws = new WebSocket(wsUrl)

      this.authResolve = resolve

      this.ws.onopen = () => {
        console.log('WebSocket connected, sending auth...')

        // Send authentication message
        const authMsg: AuthMessage = {
          type: 'auth',
          password,
          confirm_password: confirmPassword,
          change_to_password: changeToPassword,
          confirm_new_password: confirmNewPassword
        }
        this.ws?.send(JSON.stringify(authMsg))
      }

      this.ws.onmessage = (event) => {
        try {
          const message = JSON.parse(event.data)

          // Handle auth response
          if (message.type === 'auth_response') {
            const authResponse = message as AuthResponseMessage
            console.log('Auth response:', authResponse)

            if (authResponse.success) {
              this.isConnected.value = true
              this.isAuthenticated.value = true
              this.shouldReconnect = true
              console.log('Authentication successful')
            } else {
              this.isAuthenticated.value = false
              console.warn('Authentication failed:', authResponse.message)
            }

            if (this.authResolve) {
              this.authResolve({
                success: authResponse.success,
                needsConfirmation: authResponse.needs_confirmation || false,
                message: authResponse.message
              })
              this.authResolve = null
            }

            // Don't return, let other handlers process this message too
          }

          // Pass to all handlers
          this.handlers.forEach(handler => handler(message))
        } catch (err) {
          console.error('Error parsing WebSocket message:', err)
        }
      }

      this.ws.onerror = (error) => {
        console.error('WebSocket error:', error)
        this.isConnected.value = false
        this.isAuthenticated.value = false

        if (this.authResolve) {
          this.authResolve({
            success: false,
            needsConfirmation: false,
            message: 'Connection error'
          })
          this.authResolve = null
        }
      }

      this.ws.onclose = (event) => {
        this.isConnected.value = false
        this.isAuthenticated.value = false
        console.log('WebSocket disconnected:', event.code, event.reason)

        if (this.authResolve) {
          this.authResolve({
            success: false,
            needsConfirmation: false,
            message: event.reason || 'Connection closed'
          })
          this.authResolve = null
        }

        // No auto-reconnect - user must re-authenticate manually
        // This prevents reconnection attempts without proper password
      }

      // Timeout for auth
      setTimeout(() => {
        if (this.authResolve) {
          this.authResolve({
            success: false,
            needsConfirmation: false,
            message: 'Authentication timeout'
          })
          this.authResolve = null
          this.ws?.close()
        }
      }, 30000)
    })
  }

  addHandler(handler: MessageHandler) {
    this.handlers.add(handler)
  }

  removeHandler(handler: MessageHandler) {
    this.handlers.delete(handler)
  }

  send(message: WebSocketMessage) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(message))
    }
  }

  disconnect() {
    if (this.reconnectTimeout) {
      clearTimeout(this.reconnectTimeout)
    }
    if (this.ws) {
      this.ws.close()
      this.ws = null
    }
  }

  getWebSocket() {
    return this.ws
  }
}

export const wsManager = new WebSocketManager()
