import type { CrawlStatus } from "@prisma/client"
import { prisma } from "~/server/utils/prisma"
import {
  type PersistedSourceSlug,
  getSourceConfig,
  persistedSourceSlugs,
  scrapeAndStoreSource
} from "~/server/utils/scrape-storage"

const runningSources = new Set<PersistedSourceSlug>()

export interface ScrapeQueueResult {
  accepted: boolean
  alreadyRunning: boolean
  slug: PersistedSourceSlug
  source: string
  message: string
}

export interface ScrapeStatusItem {
  slug: PersistedSourceSlug
  source: string
  isRunning: boolean
  latestRun: {
    startedAt: string
    finishedAt: string | null
    status: CrawlStatus
    fetchedCount: number
    newCount: number
    updatedCount: number
    unavailableCount: number
    errorMessage: string | null
  } | null
}

export const queueScrapeSource = (sourceSlug: PersistedSourceSlug): ScrapeQueueResult => {
  const config = getSourceConfig(sourceSlug)

  if (runningSources.has(sourceSlug)) {
    return {
      accepted: false,
      alreadyRunning: true,
      slug: sourceSlug,
      source: config.displayName,
      message: `Ya hay una corrida en progreso para ${config.displayName}.`
    }
  }

  runningSources.add(sourceSlug)

  void scrapeAndStoreSource(sourceSlug)
    .catch((error) => {
      console.error(`[scrape:${sourceSlug}]`, error)
    })
    .finally(() => {
      runningSources.delete(sourceSlug)
    })

  return {
    accepted: true,
    alreadyRunning: false,
    slug: sourceSlug,
    source: config.displayName,
    message: `Corrida iniciada para ${config.displayName}. La pagina se actualizara cuando termine.`
  }
}

export const loadScrapeStatuses = async (): Promise<ScrapeStatusItem[]> => {
  const latestRuns = await Promise.all(
    persistedSourceSlugs.map(async (slug) => {
      const config = getSourceConfig(slug)
      const latestRun = await prisma.crawlRun.findFirst({
        where: {
          source: config.sourceName
        },
        orderBy: {
          startedAt: "desc"
        },
        select: {
          startedAt: true,
          finishedAt: true,
          status: true,
          fetchedCount: true,
          newCount: true,
          updatedCount: true,
          unavailableCount: true,
          errorMessage: true
        }
      })

      return {
        slug,
        source: config.displayName,
        isRunning: runningSources.has(slug),
        latestRun: latestRun
          ? {
              startedAt: latestRun.startedAt.toISOString(),
              finishedAt: latestRun.finishedAt?.toISOString() ?? null,
              status: latestRun.status,
              fetchedCount: latestRun.fetchedCount,
              newCount: latestRun.newCount,
              updatedCount: latestRun.updatedCount,
              unavailableCount: latestRun.unavailableCount,
              errorMessage: latestRun.errorMessage
            }
          : null
      } satisfies ScrapeStatusItem
    })
  )

  return latestRuns
}
