export type { FileInfo, Manifest } from '@types'

import type { FileInfo, Manifest } from '@types'
import { loadGitignore } from '@gitignore'
import { createHash } from 'crypto'
import { readdirSync, readFileSync, statSync } from 'fs'
import { join, relative } from 'path'

export function computeHash(content: Buffer | string): string {
  return createHash('sha256').update(content).digest('hex')
}

export function generateManifest(appPath: string, appName: string): Manifest {
  const files: Record<string, FileInfo> = {}
  const gitignore = loadGitignore(appPath)

  function walkDir(dir: string) {
    const entries = readdirSync(dir, { withFileTypes: true })

    for (const entry of entries) {
      const fullPath = join(dir, entry.name)
      const relativePath = relative(appPath, fullPath)

      if (gitignore.shouldExclude(relativePath)) continue

      if (entry.isDirectory()) {
        walkDir(fullPath)
      } else if (entry.isFile()) {
        const content = readFileSync(fullPath)
        const stats = statSync(fullPath)

        files[relativePath] = {
          hash: computeHash(content),
          mtime: stats.mtime.toISOString(),
          size: stats.size,
        }
      }
    }
  }

  walkDir(appPath)

  return {
    name: appName,
    files,
  }
}
