import { Args, Command } from '@oclif/core'
import { type LoadedModule, loadModules } from '../modules.js'

type HookParams = {
  modules: LoadedModule[]
  account: string
}

export class Serve extends Command {
  static args = {
    account: Args.string({
      required: true,
      description:
        'Store name key to be considered. It must match the keys on faststore.json, otherwise the first one found will be used.',
    }),
  }
  static description = 'Runs the local server for the storefront environment.'
  static examples = ['<%= config.bin %> <%= command.id %>']

  static flags = {}

  async run(): Promise<void> {
    this.log('Running faststore serve  🚀')

    const {
      args: { account },
    } = await this.parse(Serve)

    const modules = await loadModules(account)

    try {
      await this.runPreTasks({ modules, account })
      await this.runMainTasks({ modules, account })
      await this.runPostTasks({ modules, account })
    } catch (error) {
      /**
       *  TODO: How do we deal with errors?
       *  Should we log any specific feedback given the failed task?
       */
      this.logToStderr('Something went wrong.')
      console.log(error)
    }
  }

  private async runMainTasks({ modules, account }: HookParams): Promise<void> {
    try {
      await Promise.all(
        modules.map(({ loadedCli, path, port }) => {
          const { serve } = loadedCli.commands
          return serve.run([account, path, port?.toString() ?? ''])
        })
      )
    } catch (error) {
      // FIXME: Add error handling
      console.log(error)
    }
  }

  private async runPostTasks({ modules }: HookParams): Promise<void> {
    try {
      await Promise.all(
        modules.map(({ loadedCli }) => {
          const postServe = loadedCli.hooks?.postServe
          if (postServe) return postServe()

          return Promise.resolve()
        })
      )
    } catch (error) {
      // FIXME: Add error handling
      console.log(error)
    }
  }

  private async runPreTasks({ modules }: HookParams): Promise<void> {
    try {
      await Promise.all(
        modules.map(({ loadedCli }) => {
          const preServe = loadedCli.hooks?.preServe
          if (preServe) return preServe()

          return Promise.resolve()
        })
      )
    } catch (error) {
      // FIXME: Add error handling
      this.logToStderr('Something went wrong.')
      console.log(error)
    }
  }
}
