<script lang="ts" setup>
import { reactive, ref, onMounted, onUnmounted, computed } from 'vue'
import { GetPrinters, StartServer, StopServer, GetAppMode, GetLogPort, GetSettings, SaveSettings } from '../wailsjs/go/main/App'
import { EventsOn } from '../wailsjs/runtime/runtime'
import Help from './components/Help.vue'
import Settings from './components/Settings.vue'
import { useI18n } from 'vue-i18n'

const { t, locale } = useI18n()
const appMode = ref('main')
const logPort = ref(0)
const logs = ref<string[]>([])
const clientCount = ref(0)
let logPollInterval: number | null = null
let forwarderStream: EventSource | null = null
let forwarderPoll: number | null = null

const config = reactive({
  port: '1122',
  key: ''
})

const persistServerSettings = async () => {
  try {
    const s = await GetSettings()
    if (s) {
      s.serverPort = config.port
      s.serverKey = config.key
      await SaveSettings(s)
    }
  } catch (e) {
    console.error('Failed to save server settings', e)
  }
}

const connectionUrl = computed(() => {
  let url = `ws://localhost:${config.port}/ws`
  if (config.key) {
    url += `?key=${encodeURIComponent(config.key)}`
  }
  return url
})

const serverStatus = ref('Stopped')
type PrinterInfo = {
  name: string
  isDefault: boolean
}

const printers = ref<PrinterInfo[]>([])
const isLoadingPrinters = ref(false)

const refreshPrinters = async () => {
  if (isLoadingPrinters.value) return
  isLoadingPrinters.value = true
  printers.value = []

  const minDelay = new Promise((resolve) => setTimeout(resolve, 800))

  try {
    const [fetchedPrinters] = await Promise.all([
      GetPrinters(),
      minDelay
    ])
    printers.value = fetchedPrinters.slice().sort((a, b) => {
      if (a.isDefault !== b.isDefault) {
        return a.isDefault ? -1 : 1
      }
      return a.name.localeCompare(b.name)
    })
  } catch (e) {
    console.error(e)
  } finally {
    isLoadingPrinters.value = false
  }
}

const toggleServer = async () => {
  if (serverStatus.value === 'Running') {
    try {
      await StopServer()
      serverStatus.value = 'Stopped'
    } catch (e) {
      console.error(e)
    }
  } else {
    try {
      await StartServer(config.port, config.key)
      serverStatus.value = 'Running'
    } catch (e) {
      console.error(e)
    }
  }
}

type RemoteStatus = {
  connected: boolean
  lastError: string
  lastChange: number
  autoReconnect?: boolean
}

const remoteStatus = ref<RemoteStatus>({
  connected: false,
  lastError: '',
  lastChange: 0
})
const isConnecting = ref(false)
const isDisconnecting = ref(false)
const forwarderVisible = ref(false)

const fetchLogs = async () => {
  try {
    const res = await fetch(`http://localhost:${logPort.value}/api/logs`)
    if (res.ok) {
      const data = await res.json()
      logs.value = data.reverse()
    }
  } catch (e) {
    console.error('Failed to fetch logs', e)
  }
}

const clearAllLogs = async () => {
  logs.value = []
  try {
    await fetch(`http://localhost:${logPort.value}/api/logs/clear`, { method: 'POST' })
  } catch (e) {
    console.error('Failed to clear logs', e)
  }
}

const refreshRemoteStatus = async () => {
  if (logPort.value <= 0) return
  try {
    const resp = await fetch(`http://localhost:${logPort.value}/api/forwarder/status`)
    if (resp.ok) {
      remoteStatus.value = await resp.json()
    }
  } catch (e) {
    console.error('Failed to fetch forwarder status', e)
  }
}

const updateForwarderVisibility = (settings: any) => {
  if (!settings) {
    forwarderVisible.value = false
    return
  }
  const auth = (settings.remoteAuthUrl || '').trim()
  const ws = (settings.remoteWsUrl || '').trim()
  const clientId = (settings.remoteClientId || '').trim()
  const secret = (settings.remoteSecretKey || '').trim()
  forwarderVisible.value = auth !== '' && ws !== '' && clientId !== '' && secret !== ''
}

const connectForwarder = async () => {
  if (isConnecting.value || remoteStatus.value.connected || logPort.value <= 0) return
  isConnecting.value = true
  try {
    await fetch(`http://localhost:${logPort.value}/api/forwarder/connect`, { method: 'POST' })
  } catch (e) {
    console.error('Failed to connect forwarder', e)
  } finally {
    isConnecting.value = false
  }
}

const disconnectForwarder = async () => {
  if (isDisconnecting.value || !remoteStatus.value.connected || logPort.value <= 0) return
  isDisconnecting.value = true
  try {
    const s = await GetSettings()
    if (s) {
      s.remoteAutoConnect = false
      await SaveSettings(s)
    }
    await fetch(`http://localhost:${logPort.value}/api/forwarder/disconnect`, { method: 'POST' })
    await fetch(`http://localhost:${logPort.value}/api/reload`, { method: 'POST' })
  } catch (e) {
    console.error('Failed to disconnect forwarder', e)
  } finally {
    isDisconnecting.value = false
  }
}

onMounted(async () => {
  appMode.value = await GetAppMode()

  // Load settings for language
  try {
    const s = await GetSettings()
    if (s && s.language) {
      locale.value = s.language
    }
  } catch (e) {
    console.error("Failed to load settings", e)
  }

  if (appMode.value === "logs") {
    logPort.value = await GetLogPort()
    fetchLogs()
    logPollInterval = setInterval(fetchLogs, 1000)
  } else if (appMode.value === "main") {
    // Main mode
    logPort.value = await GetLogPort()
    try {
      const s = await GetSettings()
      if (s) {
        config.port = s.serverPort || config.port
        config.key = s.serverKey || ''
        updateForwarderVisibility(s)
      }
    } catch (e) {
      console.error('Failed to load server settings', e)
    }
    await refreshPrinters()
    await toggleServer()

    await refreshRemoteStatus()
    if (logPort.value > 0 && 'EventSource' in window) {
      forwarderStream = new EventSource(`http://localhost:${logPort.value}/api/forwarder/stream`)
      forwarderStream.onmessage = (event) => {
        try {
          remoteStatus.value = JSON.parse(event.data)
        } catch (e) {
          console.error(e)
        }
      }
      forwarderStream.onerror = () => {
        if (forwarderStream) {
          forwarderStream.close()
          forwarderStream = null
        }
        if (forwarderPoll === null) {
          forwarderPoll = window.setInterval(refreshRemoteStatus, 3000)
        }
      }
    } else {
      forwarderPoll = window.setInterval(refreshRemoteStatus, 3000)
    }
    
    // Listen for client count updates
    EventsOn("client_count", (count: number) => {
      clientCount.value = count
    })


    // Listen for settings reload
    EventsOn("reload_settings", async () => {
      try {
        const s = await GetSettings()
        if (s && s.language) {
          locale.value = s.language
        }
        if (s) {
          config.port = s.serverPort || config.port
          config.key = s.serverKey || ''
          updateForwarderVisibility(s)
        }
      } catch (e) {
        console.error("Failed to reload settings", e)
      }
    })
  }
})

onUnmounted(() => {
  if (logPollInterval) clearInterval(logPollInterval)
  if (forwarderPoll !== null) {
    window.clearInterval(forwarderPoll)
    forwarderPoll = null
  }
  if (forwarderStream) {
    forwarderStream.close()
    forwarderStream = null
  }
})
</script>

<template>
  <Help v-if="appMode === 'help'" />
  <Settings v-else-if="appMode === 'settings'" />
  
  <div v-else class="h-screen w-screen overflow-hidden bg-white text-gray-900 font-sans text-left flex flex-col relative">
    
    <!-- Content Area -->
    <div class="flex-1 overflow-hidden relative">
      
      <!-- LOGS MODE UI -->
      <div v-if="appMode === 'logs'" class="w-full h-full flex flex-col">
        <header class="p-4 border-b border-gray-200 bg-gray-50 flex justify-between items-center">
          <div>
            <h1 class="text-xl font-bold text-gray-800 mb-1 flex items-center gap-2">
              <i-material-symbols-terminal class="text-gray-700" />
              {{ t('logs.title') }}
            </h1>
            <p class="text-xs text-gray-500">{{ t('logs.subtitle') }}</p>
          </div>
          <button @click="clearAllLogs" class="text-xs text-red-600 hover:bg-red-50 px-3 py-1.5 border border-red-200 rounded-md transition-colors flex items-center gap-1">
            <i-material-symbols-delete-outline />
            {{ t('logs.clearAll') }}
          </button>
        </header>
        <div class="flex-1 bg-gray-900 text-gray-300 p-4 font-mono text-xs overflow-y-auto scrollbar-thin scrollbar-thumb-gray-700 scrollbar-track-transparent">
          <div v-for="(log, i) in logs" :key="i" class="border-b border-gray-800 last:border-0 pb-1 mb-1 break-words hover:bg-gray-800/50">
            {{ log }}
          </div>
          <div v-if="logs.length === 0" class="text-gray-600 italic py-4 text-center">{{ t('logs.empty') }}</div>
        </div>
      </div>

      <!-- MAIN APP UI -->
      <div v-else class="w-full h-full flex flex-col">
        <!-- Header -->
        <header 
          class="p-4 border-b border-gray-200 flex-none transition-colors duration-300"
          :class="clientCount > 0 ? 'bg-green-600 text-white' : 'bg-gray-50 text-gray-900'"
        >
          <div class="flex justify-between items-center">
            <div>
              <h1 class="text-xl font-bold mb-1 flex items-center gap-2">
                <i-material-symbols-print-connect :class="clientCount > 0 ? 'text-white' : 'text-blue-600'" />
                {{ t('main.title') }}
              </h1>
              <p class="text-xs" :class="clientCount > 0 ? 'text-green-100' : 'text-gray-500'">
                {{ t('main.subtitle') }}
              </p>
            </div>
            
            <!-- Client Count Badge -->
            <div 
              class="flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-bold transition-all"
              :class="clientCount > 0 ? 'bg-white text-green-700 shadow-sm' : 'bg-gray-200 text-gray-600'"
            >
              <i-material-symbols-devices />
              <span>{{ clientCount }} {{ t('main.clients') }}</span>
            </div>
          </div>

        </header>

        <div class="flex-1 overflow-y-auto scrollbar-hide">
          <!-- Server Control -->
          <div class="p-4 border-b border-gray-200">
            <h2 class="text-base font-semibold mb-4 flex items-center gap-2">
              <i-material-symbols-dns class="text-gray-600" />
              <span class="w-2.5 h-2.5 rounded-full" :class="serverStatus === 'Running' ? 'bg-green-500' : 'bg-red-500'"></span>
              {{ t('main.serverControl') }}
            </h2>

            <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
              <div>
                <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{{ t('main.port') }}</label>
                <input v-model="config.port" @change="persistServerSettings" type="text" class="w-full bg-white border border-gray-300 px-3 py-2 text-sm text-gray-800 focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all rounded-md" :disabled="serverStatus === 'Running'" />
              </div>
              <div>
                <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{{ t('main.secretKey') }}</label>
                <input v-model="config.key" @change="persistServerSettings" type="password" class="w-full bg-white border border-gray-300 px-3 py-2 text-sm text-gray-800 focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all rounded-md" :disabled="serverStatus === 'Running'" :placeholder="t('main.placeholderKey')" />
              </div>
            </div>

            <button 
              @click="toggleServer" 
              class="w-full py-2 px-4 font-semibold text-white transition-all active:opacity-90 rounded-md flex items-center justify-center gap-2"
              :class="serverStatus === 'Running' ? 'bg-red-500 hover:bg-red-600' : 'bg-blue-600 hover:bg-blue-700'"
            >
              <i-material-symbols-stop v-if="serverStatus === 'Running'" />
              <i-material-symbols-play-arrow v-else />
              {{ serverStatus === 'Running' ? t('main.stopServer') : t('main.startServer') }}
            </button>

            <div class="mt-4 p-3 bg-gray-50 border border-gray-200 rounded-md">
              <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{{ t('main.connectionUrl') }}</label>
              <div class="flex items-center gap-2">
                <code class="flex-1 bg-white border border-gray-300 px-2 py-1.5 text-xs text-gray-600 rounded select-all font-mono break-all">
                  {{ connectionUrl }}
                </code>
              </div>
            </div>
          </div>

          <!-- Forwarder -->
          <div v-if="forwarderVisible" class="p-4 border-t border-gray-200">
            <h2 class="text-base font-semibold mb-4 flex items-center gap-2">
              <i-material-symbols-cloud-sync class="text-gray-600" />
              <span class="w-2.5 h-2.5 rounded-full" :class="remoteStatus.connected ? 'bg-green-500' : 'bg-red-500'"></span>
              {{ t('settings.forwarding') }}
            </h2>

            <button
              @click="remoteStatus.connected ? disconnectForwarder() : connectForwarder()"
              :disabled="isConnecting || isDisconnecting"
              class="w-full py-2 px-4 font-semibold rounded-md transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
              :class="remoteStatus.connected ? 'bg-red-500 hover:bg-red-600 text-white' : 'bg-blue-600 hover:bg-blue-700 text-white'"
            >
              <i-material-symbols-stop v-if="remoteStatus.connected" />
              <i-material-symbols-play-arrow v-else />
              {{ remoteStatus.connected ? (isDisconnecting ? t('settings.disconnecting') : t('settings.disconnect')) : (isConnecting ? t('settings.connecting') : t('settings.connect')) }}
            </button>

            <p v-if="remoteStatus.lastError" class="text-xs text-red-500 mt-2">
              <span class="font-medium">{{ t('settings.lastError') }}:</span>
              <span class="break-words">{{ remoteStatus.lastError }}</span>
            </p>
          </div>

          <!-- Printers -->
          <div class="p-4 border-t border-gray-200">
            <div class="flex justify-between items-center mb-4">
              <h2 class="text-base font-semibold text-gray-800 flex items-center gap-2">
                <i-material-symbols-print class="text-gray-600" />
                {{ t('main.availablePrinters') }}
              </h2>
              <button 
                @click="refreshPrinters" 
                class="text-xs bg-gray-100 hover:bg-gray-200 text-blue-600 px-3 py-1.5 border border-gray-200 transition-colors rounded-md flex items-center gap-1"
                :disabled="isLoadingPrinters"
              >
                <i-material-symbols-refresh :class="{ 'animate-spin': isLoadingPrinters }" />
                {{ t('main.refresh') }}
              </button>
            </div>
            
            <div v-if="isLoadingPrinters" class="text-gray-500 italic text-center py-6 bg-gray-50 border border-dashed border-gray-200 flex flex-col items-center gap-2">
              <span>{{ t('main.loading') }}</span>
            </div>
            <div v-else-if="printers.length === 0" class="text-gray-400 italic text-center py-6 bg-gray-50 border border-dashed border-gray-200">
              {{ t('main.noPrinters') }}
            </div>
            <ul v-else class="grid grid-cols-1 gap-0 border border-gray-200 divide-y divide-gray-200">
              <li v-for="p in printers" :key="p.name" class="px-3 py-2 flex items-center gap-2 hover:bg-gray-50 transition-colors text-sm bg-white">
                <i-material-symbols-print class="text-lg opacity-70 text-gray-500" />
                <span class="font-medium truncate text-gray-700" :title="p.name">{{ p.name }}</span>
                <span v-if="p.isDefault" class="ml-auto text-[10px] px-2 py-0.5 rounded-full bg-blue-50 text-blue-700 border border-blue-100">
                  {{ t('main.defaultPrinter') }}
                </span>
              </li>
            </ul>
          </div>
        </div>
      </div>
      
    </div>
  </div>
</template>

<style>
/* Reset some Wails default styles if needed */
body {
  margin: 0;
  background-color: #f9fafb; /* gray-50 */
}
</style>
