import { constants } from 'fs'
import { join } from 'node:path'
import { access, readFile, open, unlink, readdir } from 'fs/promises'

import type { Items } from './type'

class Repository {
  #rootPath: string

  constructor(rootPath: string) {
    this.#rootPath = rootPath
  }

  async isFile(path: string) {
    try {
      await access(path, constants.F_OK | constants.R_OK)
      return true
    } catch (error) {
      return false
    }
  }

  async infoRoot() {
    try {
      const buffer = await readdir(this.#rootPath)
      console.log(buffer)
      return true
    } catch (error) {
      return false
    }
  }

  async tree({
    root = this.#rootPath,
    tree,
    depth = 1,
  }: {
    root?: string
    tree: Items
    depth?: number
  }) {
    try {
      const entries = await readdir(root, { withFileTypes: true })
      for (const dirent of entries) {
        if (dirent.name !== '.pijul') {
          const item = {
            isDir: dirent.isDirectory(),
            extension: dirent.name.split('.').at(-1) ?? null,
            name: dirent.name,
            path: join(root, dirent.name),
            depth,
          }
          tree.push({...item, id: tree.length + 1})
          if (dirent.isDirectory()) {
            await this.tree({
              root: join(root, dirent.name),
              tree,
              depth: depth + 1,
            })
          }
        }
      }
    } catch (error) {
      console.error(error)
    }
  }

  async getContent(path: string) {
    const filePath = join(this.#rootPath + path)
    const isFileExist = await this.isFile(filePath)

    if (!isFileExist) {
      console.error(`The file located at ${path} do not exist`)
    }

    try {
      const buffer = readFile(filePath)
      console.log(buffer)
    } catch (error) {
      console.error(error)
    }
  }

  async addFile(path: string) {
    const filePath = join(this.#rootPath, path)
    const isFileExist = await this.isFile(filePath)

    if (!isFileExist) {
      return
    }

    try {
      await open(filePath, 'w')
      return true
    } catch (error) {
      return false
    }
  }

  async delFile(path: string) {
    const filePath = join(this.#rootPath, path)
    const isFileExist = await this.isFile(filePath)

    if (!isFileExist) {
      return
    }

    try {
      await unlink(filePath)
      return true
    } catch (error) {
      return false
    }
  }
}

export default Repository