import { defineStore } from 'pinia'
import { ref } from 'vue'
import { dataStore } from '@/types/dataStore'
import { apiClient } from '@/utils/fetchUtils'
import { Package } from '@/types/Package'
import { Stats } from '@/types/Stats'

const UpdateInterval = Number(import.meta.env.VITE_UPDATE_INTERVAL) || 5

export const useDataStore = defineStore('data', () => {
  const data = ref<dataStore>()
  const loading = ref(false)
  const error = ref<Error | null>(null)
  let refreshInterval: NodeJS.Timeout | null = null

  const init = () => {
    data.value = {
      lastUpdated: Date.now(),
      packages: {
        offset: 0,
        limit: Number(import.meta.env.VITE_OFFSET) || 50,
        totalPackages: [],
        byStatus: {
          latest: [],
          built: [],
          failed: [],
          skipped: [],
          delayed: [],
          queued: [],
          building: [],
          signing: [],
          unknown: []
        },
        byRepo: {
          core: {
            v2: [],
            v3: [],
            v4: []
          },
          extra: {
            v2: [],
            v3: [],
            v4: []
          },
          multilib: {
            v2: [],
            v3: [],
            v4: []
          }
        }
      },
      stats: {
        total: 0,
        built: 0,
        building: 0,
        latest: 0,
        queued: 0,
        skipped: 0,
        failed: 0,
        lto: {
          enabled: 0,
          disabled: 0,
          unknown: 0
        }
      }
    }
  }

  // Fetch all package data from the API
  const fetchAllPackageData = async () => {
    loading.value = true
    error.value = null
    try {
      const [totalStats, totalPackages] = await Promise.allSettled([
        apiClient.getStats(),
        apiClient.getPackages({ limit: 0, offset: 0 })
      ])

      // Combine into a single data structure
      if (
        totalPackages.status === 'fulfilled' &&
        totalStats.status === 'fulfilled' &&
        totalPackages.value &&
        totalStats.value
      ) {
        // Initialize if needed
        if (!data.value) init()

        // Update with the fetched data
        data.value!.lastUpdated = Date.now()
        data.value!.packages.totalPackages = [...totalPackages.value.packages]
        data.value!.packages.offset = totalPackages.value.offset
        data.value!.packages.limit = totalPackages.value.limit

        // Update byStatus categorization
        data.value!.packages.byStatus = {
          latest: totalPackages.value.packages.filter((pkg) => pkg.status === 'latest') || [],
          built: totalPackages.value.packages.filter((pkg) => pkg.status === 'built') || [],
          failed: totalPackages.value.packages.filter((pkg) => pkg.status === 'failed') || [],
          skipped: totalPackages.value.packages.filter((pkg) => pkg.status === 'skipped') || [],
          delayed: totalPackages.value.packages.filter((pkg) => pkg.status === 'delayed') || [],
          queued: totalPackages.value.packages.filter((pkg) => pkg.status === 'queued') || [],
          building: totalPackages.value.packages.filter((pkg) => pkg.status === 'building') || [],
          signing: totalPackages.value.packages.filter((pkg) => pkg.status === 'signing') || [],
          unknown: totalPackages.value.packages.filter((pkg) => pkg.status === 'unknown') || []
        }

        // Update byRepo categorization
        data.value!.packages.byRepo = {
          core: {
            v2: totalPackages.value.packages.filter((pkg) => pkg.repo === 'core-x86-64-v2') || [],
            v3: totalPackages.value.packages.filter((pkg) => pkg.repo === 'core-x86-64-v3') || [],
            v4: totalPackages.value.packages.filter((pkg) => pkg.repo === 'core-x86-64-v4') || []
          },
          extra: {
            v2: totalPackages.value.packages.filter((pkg) => pkg.repo === 'extra-x86-64-v2') || [],
            v3: totalPackages.value.packages.filter((pkg) => pkg.repo === 'extra-x86-64-v3') || [],
            v4: totalPackages.value.packages.filter((pkg) => pkg.repo === 'extra-x86-64-v4') || []
          },
          multilib: {
            v2:
              totalPackages.value.packages.filter((pkg) => pkg.repo === 'multilib-x86-64-v2') || [],
            v3:
              totalPackages.value.packages.filter((pkg) => pkg.repo === 'multilib-x86-64-v3') || [],
            v4:
              totalPackages.value.packages.filter((pkg) => pkg.repo === 'multilib-x86-64-v4') || []
          }
        }

        // Update stats
        data.value!.stats = {
          ...totalStats.value,
          total: totalPackages.value.total, // Total count from API
          built: data.value!.packages.byStatus.built.length,
          building: data.value!.packages.byStatus.building.length
        }
      }
    } catch (e) {
      console.error('Error fetching package data:', e)
      error.value = e as Error
    } finally {
      loading.value = false
    }
  }

  // Fetch a specific page of packages
  const fetchPackagePage = async (offset: number, limit: number) => {
    loading.value = true
    error.value = null
    try {
      const packageData = await apiClient.getPackages({ limit, offset })

      if (packageData && data.value) {
        data.value.packages.totalPackages = [...packageData.packages]
        data.value.packages.offset = offset
        data.value.packages.limit = limit

        // Update byStatus categorization
        data.value.packages.byStatus = {
          latest: packageData.packages.filter((pkg) => pkg.status === 'latest') || [],
          built: packageData.packages.filter((pkg) => pkg.status === 'built') || [],
          failed: packageData.packages.filter((pkg) => pkg.status === 'failed') || [],
          skipped: packageData.packages.filter((pkg) => pkg.status === 'skipped') || [],
          delayed: packageData.packages.filter((pkg) => pkg.status === 'delayed') || [],
          queued: packageData.packages.filter((pkg) => pkg.status === 'queued') || [],
          building: packageData.packages.filter((pkg) => pkg.status === 'building') || [],
          signing: packageData.packages.filter((pkg) => pkg.status === 'signing') || [],
          unknown: packageData.packages.filter((pkg) => pkg.status === 'unknown') || []
        }

        // Update byRepo categorization
        data.value.packages.byRepo = {
          core: {
            v2: packageData.packages.filter((pkg) => pkg.repo === 'core-x86-64-v2') || [],
            v3: packageData.packages.filter((pkg) => pkg.repo === 'core-x86-64-v3') || [],
            v4: packageData.packages.filter((pkg) => pkg.repo === 'core-x86-64-v4') || []
          },
          extra: {
            v2: packageData.packages.filter((pkg) => pkg.repo === 'extra-x86-64-v2') || [],
            v3: packageData.packages.filter((pkg) => pkg.repo === 'extra-x86-64-v3') || [],
            v4: packageData.packages.filter((pkg) => pkg.repo === 'extra-x86-64-v4') || []
          },
          multilib: {
            v2: packageData.packages.filter((pkg) => pkg.repo === 'multilib-x86-64-v2') || [],
            v3: packageData.packages.filter((pkg) => pkg.repo === 'multilib-x86-64-v3') || [],
            v4: packageData.packages.filter((pkg) => pkg.repo === 'multilib-x86-64-v4') || []
          }
        }
      }
    } catch (e) {
      console.error('Error fetching page data:', e)
      error.value = e as Error
    } finally {
      loading.value = false
    }
  }

  const startAutoRefresh = async () => {
    stopAutoRefresh()

    init()
    await fetchAllPackageData()

    refreshInterval = setInterval(fetchAllPackageData, UpdateInterval * 60 * 1000)
  }

  const stopAutoRefresh = () => {
    if (refreshInterval) {
      clearInterval(refreshInterval)
      refreshInterval = null
    }
  }

  const getAllPackages = (): { packages: Package[]; total: number } => {
    if (!data.value) return { packages: [], total: 0 }

    return {
      packages: data.value.packages.totalPackages || [],
      total: data.value.stats.total || 0
    }
  }

  const getPackagesByStatus = (
    status: Package['status']
  ): { packages: Array<Package>; total: number } => {
    if (!data.value) return { packages: [], total: 0 }

    return {
      packages: data.value.packages.byStatus[status],
      total:
        status in data.value.stats
          ? typeof data.value.stats[status as keyof typeof data.value.stats] === 'number'
            ? (data.value.stats[status as keyof typeof data.value.stats] as number)
            : 0
          : 0
    }
  }

  const getPackageStats = ():
    | (Stats & { total: number; built: number; building: number })
    | null => {
    return data.value?.stats ?? null
  }

  return {
    data,
    loading,
    error,
    init,
    fetchAllPackageData,
    fetchPackagePage,
    startAutoRefresh,
    stopAutoRefresh,
    getAllPackages,
    getPackageStats,
    getPackagesByStatus
  }
})
