// Pinia store for container management
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { containerClient, type ContainerStatus } from '@/api/container-client'

// Bundled apps that come pre-loaded with Archipelago
export interface BundledApp {
  id: string
  name: string
  image: string
  description: string
  icon: string
  ports: { host: number; container: number }[]
  volumes: { host: string; container: string }[]
  category: 'bitcoin' | 'lightning' | 'home' | 'other'
  lan_address?: string // Runtime launch URL from backend
}

export const BUNDLED_APPS: BundledApp[] = [
  {
    id: 'bitcoin-knots',
    name: 'Bitcoin Knots',
    image: 'localhost/bitcoinknots/bitcoin:29',
    description: 'Full Bitcoin node with additional features',
    icon: '₿',
    ports: [{ host: 8332, container: 8332 }, { host: 8333, container: 8333 }],
    volumes: [{ host: '/var/lib/archipelago/bitcoin', container: '/data' }],
    category: 'bitcoin',
  },
  {
    id: 'lnd',
    name: 'Lightning (LND)',
    image: 'docker.io/lightninglabs/lnd:v0.18.4-beta',
    description: 'Lightning Network Daemon for fast Bitcoin payments',
    icon: '⚡',
    ports: [{ host: 9735, container: 9735 }, { host: 10009, container: 10009 }],
    volumes: [{ host: '/var/lib/archipelago/lnd', container: '/root/.lnd' }],
    category: 'lightning',
  },
  {
    id: 'homeassistant',
    name: 'Home Assistant',
    image: 'ghcr.io/home-assistant/home-assistant:stable',
    description: 'Open source home automation platform',
    icon: '🏠',
    ports: [{ host: 8123, container: 8123 }],
    volumes: [{ host: '/var/lib/archipelago/homeassistant', container: '/config' }],
    category: 'home',
  },
  {
    id: 'btcpayserver',
    name: 'BTCPay Server',
    image: 'docker.io/btcpayserver/btcpayserver:latest',
    description: 'Self-hosted Bitcoin payment processor',
    icon: '💳',
    ports: [{ host: 23000, container: 23000 }],
    volumes: [{ host: '/var/lib/archipelago/btcpay', container: '/datadir' }],
    category: 'bitcoin',
  },
  {
    id: 'mempool',
    name: 'Mempool Explorer',
    image: 'docker.io/mempool/frontend:latest',
    description: 'Bitcoin blockchain and mempool visualizer',
    icon: '🔍',
    ports: [{ host: 8080, container: 8080 }],
    volumes: [{ host: '/var/lib/archipelago/mempool', container: '/data' }],
    category: 'bitcoin',
  },
  {
    id: 'nostr-rs-relay',
    name: 'Nostr Relay (RS)',
    image: 'docker.io/scsibug/nostr-rs-relay:latest',
    description: 'Rust-based Nostr relay for decentralized social',
    icon: '🦩',
    ports: [{ host: 8008, container: 8080 }],
    volumes: [{ host: '/var/lib/archipelago/nostr-rs', container: '/usr/src/app/db' }],
    category: 'other',
  },
  {
    id: 'strfry',
    name: 'Strfry Relay',
    image: 'docker.io/hoytech/strfry:latest',
    description: 'High-performance Nostr relay',
    icon: '⚡',
    ports: [{ host: 7777, container: 7777 }],
    volumes: [{ host: '/var/lib/archipelago/strfry', container: '/app/strfry-db' }],
    category: 'other',
  },
  {
    id: 'tailscale',
    name: 'Tailscale VPN',
    image: 'docker.io/tailscale/tailscale:latest',
    description: 'Zero-config VPN mesh network',
    icon: '🔒',
    ports: [],
    volumes: [{ host: '/var/lib/archipelago/tailscale', container: '/var/lib/tailscale' }],
    category: 'other',
  },
]

export const useContainerStore = defineStore('container', () => {
  // State
  const containers = ref<ContainerStatus[]>([])
  const healthStatus = ref<Record<string, string>>({})
  const loading = ref(false)
  const loadingApps = ref<Set<string>>(new Set()) // Track loading state per app
  const error = ref<string | null>(null)

  // Getters
  const runningContainers = computed(() => 
    containers.value.filter(c => c.state === 'running')
  )

  const stoppedContainers = computed(() => 
    containers.value.filter(c => c.state === 'stopped' || c.state === 'exited')
  )

  const getContainerById = computed(() => (id: string) => 
    containers.value.find(c => c.name.includes(id))
  )

  const getHealthStatus = computed(() => (appId: string) => 
    healthStatus.value[appId] || 'unknown'
  )

  // Get container for a bundled app (matches by name)
  const getContainerForApp = computed(() => (appId: string) => {
    return containers.value.find(c => 
      c.name === appId || 
      c.name.includes(appId) ||
      c.name === `archipelago-${appId}` ||
      c.name === `archipelago-${appId}-dev`
    )
  })

  // Check if an app is currently loading (starting/stopping)
  const isAppLoading = computed(() => (appId: string) => 
    loadingApps.value.has(appId)
  )

  // Get app state: 'running', 'stopped', 'not-installed'
  const getAppState = computed(() => (appId: string) => {
    const container = getContainerForApp.value(appId)
    if (!container) return 'not-installed'
    return container.state
  })

  // Get enriched bundled apps with runtime data (like lan_address)
  const enrichedBundledApps = computed(() => {
    return BUNDLED_APPS.map(app => {
      const container = getContainerForApp.value(app.id)
      return {
        ...app,
        lan_address: container?.lan_address
      }
    })
  })

  // Actions
  async function fetchContainers() {
    loading.value = true
    error.value = null
    try {
      containers.value = await containerClient.listContainers()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to fetch containers'
      console.error('Failed to fetch containers:', e)
    } finally {
      loading.value = false
    }
  }

  async function fetchHealthStatus() {
    try {
      healthStatus.value = await containerClient.getHealthStatus()
    } catch (e) {
      console.error('Failed to fetch health status:', e)
    }
  }

  async function installApp(manifestPath: string) {
    loading.value = true
    error.value = null
    try {
      const containerName = await containerClient.installApp(manifestPath)
      await fetchContainers()
      return containerName
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to install app'
      throw e
    } finally {
      loading.value = false
    }
  }

  async function startContainer(appId: string) {
    loadingApps.value.add(appId)
    error.value = null
    try {
      await containerClient.startContainer(appId)
      await fetchContainers()
      await fetchHealthStatus()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to start container'
      throw e
    } finally {
      loadingApps.value.delete(appId)
    }
  }

  async function stopContainer(appId: string) {
    loadingApps.value.add(appId)
    error.value = null
    try {
      await containerClient.stopContainer(appId)
      await fetchContainers()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to stop container'
      throw e
    } finally {
      loadingApps.value.delete(appId)
    }
  }

  // Start a bundled app (creates and starts container)
  async function startBundledApp(app: BundledApp) {
    loadingApps.value.add(app.id)
    error.value = null
    try {
      await containerClient.startBundledApp(app)
      await fetchContainers()
      await fetchHealthStatus()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to start app'
      throw e
    } finally {
      loadingApps.value.delete(app.id)
    }
  }

  // Stop a bundled app
  async function stopBundledApp(appId: string) {
    loadingApps.value.add(appId)
    error.value = null
    try {
      await containerClient.stopBundledApp(appId)
      await fetchContainers()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to stop app'
      throw e
    } finally {
      loadingApps.value.delete(appId)
    }
  }

  async function removeContainer(appId: string) {
    loading.value = true
    error.value = null
    try {
      await containerClient.removeContainer(appId)
      await fetchContainers()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to remove container'
      throw e
    } finally {
      loading.value = false
    }
  }

  async function getContainerLogs(appId: string, lines: number = 100) {
    try {
      return await containerClient.getContainerLogs(appId, lines)
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to get logs'
      throw e
    }
  }

  async function getContainerStatus(appId: string) {
    try {
      return await containerClient.getContainerStatus(appId)
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to get status'
      throw e
    }
  }

  return {
    // State
    containers,
    healthStatus,
    loading,
    loadingApps,
    error,
    // Getters
    runningContainers,
    stoppedContainers,
    getContainerById,
    getHealthStatus,
    getContainerForApp,
    isAppLoading,
    getAppState,
    enrichedBundledApps,
    // Actions
    fetchContainers,
    fetchHealthStatus,
    installApp,
    startContainer,
    stopContainer,
    removeContainer,
    getContainerLogs,
    getContainerStatus,
    startBundledApp,
    stopBundledApp,
  }
})
