// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========

import { createRequire } from 'node:module'
import dotenv from 'dotenv'
import {
  DiscordResource,
  MountMode,
  patchNodeFs,
  Workspace,
  type DiscordConfig,
} from '@struktoai/mirage-node'

const require = createRequire(import.meta.url)
const fs = require('fs') as typeof import('fs')

dotenv.config({ path: '.env.development' })

function buildConfig(): DiscordConfig {
  const token = process.env.DISCORD_BOT_TOKEN
  if (token === undefined || token === '') {
    throw new Error('DISCORD_BOT_TOKEN env var is required')
  }
  return { token }
}

const exists = (p: string): Promise<boolean> =>
  fs.promises.stat(p).then(
    () => true,
    () => false,
  )

async function main(): Promise<void> {
  const resource = new DiscordResource(buildConfig())
  const ws = new Workspace({ '/discord': resource }, { mode: MountMode.READ })
  const restore = patchNodeFs(ws)
  try {
    console.log('=== VFS MODE: fs.readFile() reads from Discord transparently ===\n')

    console.log('--- fs.readdir() guilds ---')
    const guilds = await fs.promises.readdir('/discord')
    for (const g of guilds) {
      console.log(`  ${g}`)
    }

    let path = ''
    if (guilds.length > 0) {
      const guild = guilds[0]!

      console.log(`\n--- fs.readdir() ${guild} ---`)
      const sections = await fs.promises.readdir(`/discord/${guild}`)
      for (const s of sections) {
        console.log(`  ${s}`)
      }

      console.log(`\n--- fs.readdir() ${guild}/channels ---`)
      const channels = await fs.promises.readdir(`/discord/${guild}/channels`)
      for (const ch of channels.slice(0, 5)) {
        console.log(`  ${ch}`)
      }

      if (channels.length > 0) {
        const ch = channels[0]!

        console.log(`\n--- fs.readdir() ${ch} (last 5 dates) ---`)
        const dates = await fs.promises.readdir(`/discord/${guild}/channels/${ch}`)
        for (const d of dates.slice(-5)) {
          console.log(`  ${d}`)
        }

        if (dates.length > 0) {
          let found = false
          for (const d of [...dates].reverse()) {
            const chatPath = `/discord/${guild}/channels/${ch}/${d}/chat.jsonl`
            let content: string
            try {
              content = await fs.promises.readFile(chatPath, 'utf-8')
            } catch {
              continue
            }
            const lines = content
              .trim()
              .split('\n')
              .filter((line) => line.trim() !== '')
            if (lines.length > 0) {
              console.log(`\n--- fs.readFile() ${d}/chat.jsonl ---`)
              console.log(`  messages: ${String(lines.length)}`)
              for (const line of lines.slice(0, 3)) {
                try {
                  const rec = JSON.parse(line) as {
                    author?: { username?: string }
                    content?: string
                  }
                  const author = rec.author?.username ?? '?'
                  const text = (rec.content ?? '').slice(0, 80)
                  console.log(`  [${author}] ${text}`)
                } catch {
                  console.log(`  (unparseable: ${line.slice(0, 80)})`)
                }
              }
              // list attachments
              const filesDir = `/discord/${guild}/channels/${ch}/${d}/files`
              try {
                const atts = await fs.promises.readdir(filesDir)
                if (atts.length > 0) {
                  console.log(`\n--- fs.readdir() ${d}/files ---`)
                  for (const a of atts.slice(0, 5)) console.log(`  ${a}`)
                }
              } catch {
                // no files dir or unreadable
              }
              path = chatPath
              found = true
              break
            }
          }
          if (!found) {
            console.log('\n  (no messages found in recent dates)')
          }

          console.log('\n--- exists via fs.promises.stat() ---')
          console.log(`  exists: ${String(await exists(path))}`)
          console.log(`  nonexistent: ${String(await exists('/discord/nope'))}`)
        }
      }

      console.log(`\n--- fs.readdir() ${guild}/members ---`)
      const members = await fs.promises.readdir(`/discord/${guild}/members`)
      for (const m of members.slice(0, 5)) {
        console.log(`  ${m}`)
      }
    }

    console.log('\n--- bash history ---')
    const history = await fs.promises.readFile('/.bash_history', 'utf-8')
    const histLines = history.split('\n').filter((line) => line.trim() !== '')
    for (let i = 0; i < Math.min(6, histLines.length); i++) {
      console.log(`  ${histLines[i]!.slice(0, 120)}`)
    }

    const records = ws.records
    const total = records.reduce((acc, r) => acc + (r.bytes ?? 0), 0)
    console.log(
      `\nStats: ${String(records.length)} ops, ${String(total)} bytes transferred`,
    )
  } finally {
    restore()
    await ws.close()
  }
}

main().catch((err: unknown) => {
  console.error(err)
  process.exit(1)
})
