import path from 'node:path'
import * as fs from 'node:fs'

import { app } from 'electron'
import { getManifest } from '../api'
import { Manifest } from '../api/types'

export const manifestFolder = path.join(app.getPath('userData'), 'manifest')

function extToJson(value: string): string {
  return value + '.json'
}

function isManifestExists(name: string): boolean {
  return fs.existsSync(path.join(manifestFolder, name))
}

function readManifest(id: string): Manifest {
  const manifest = fs.readFileSync(path.join(manifestFolder, extToJson(id)), 'utf-8')
  return JSON.parse(manifest) as Manifest
}

async function downloadNewManifest(id: string): Promise<void> {
  const manifest = isManifestExists(extToJson(id))
  const oldManifest = isManifestExists(extToJson(`${id}.old`))

  if (manifest) {
    if (oldManifest) {
      const pathToOldManifest = path.join(manifestFolder, extToJson(`${id}.old`))
      fs.rmSync(pathToOldManifest)
    }

    const pathToNewManifest = path.join(manifestFolder, extToJson(id))
    fs.renameSync(pathToNewManifest, path.join(manifestFolder, extToJson(`${id}.old`)))
  }

  const downloadedManifest = await getManifest(id)
  fs.writeFileSync(path.join(manifestFolder, extToJson(id)), JSON.stringify(downloadedManifest))
}

/**
 * Compares old and new manifests to determine file changes
 * @param {string} id - The manifest identifier
 * @returns {Object} Object containing arrays of removed, new, and modified files
 */
function compareManifests(id: string): { removedFiles: Manifest; filesToDownload: Manifest } {
  const newManifest = readManifest(id)
  const oldManifest = readManifest(`${id}.old`)

  // Find removed files (present in old but not in new)
  const removedFiles = oldManifest.filter(
    (oldFile) => !newManifest.some((newFile) => newFile.path === oldFile.path)
  )

  // Find new and modified files
  const filesToDownload = newManifest.filter((newFile) => {
    const oldFile = oldManifest.find((old) => old.path === newFile.path)

    // If file doesn't exist in old manifest, it's new
    if (!oldFile) {
      return true
    }

    // If file exists but hash or size is different, it needs to be redownloaded
    return newFile.hash !== oldFile.hash || newFile.size !== oldFile.size
  })

  return {
    removedFiles,
    filesToDownload
  }
}

/**
 * Process manifest changes and return detailed information
 * @param {string} id - The manifest identifier
 * @returns {Object} Detailed manifest comparison results
 */
function processManifestChanges(id: string): { removedFiles: Manifest; filesToDownload: Manifest } {
  const { removedFiles, filesToDownload } = compareManifests(id)

  return {
    removedFiles,
    filesToDownload
    // summary: {
    //   removedCount: removedFiles.length,
    //   downloadCount: filesToDownload.length,
    //   totalChanges: removedFiles.length + filesToDownload.length
    // }
  }
}
