import * as path from 'path'
import * as fs from 'fs/promises'
import { fileURLToPath } from 'url'
import { dirname } from 'path'
import { TemplateEngine } from '../template-engine/engine.js'
import inquirer from 'inquirer'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

export interface CreateAppOptions {
  type: 'web' | 'mobile' | 'api' | 'desktop'
  name?: string
  displayName?: string
  appId?: string
  framework?: string
  includeRouter?: boolean
  includeTailwind?: boolean
  includeNavigator?: boolean
  includeAuth?: boolean
  includeApiClient?: boolean
  port?: number
  includeDatabase?: boolean
  includeValidation?: boolean
  includeSwagger?: boolean
  includeGraphQL?: boolean
  includeAutoUpdater?: boolean
  includeSystemTray?: boolean
  includeMenuBar?: boolean
  includeIpc?: boolean
  includeDarkMode?: boolean
}

export class CreateAppCommand {
  private engine: TemplateEngine

  constructor(engine: TemplateEngine) {
    this.engine = engine
  }

  async execute(options: CreateAppOptions): Promise<void> {
    const finalOptions = await this.promptMissingOptions(options)
    
    const templatePath = path.join(
      __dirname,
      '../templates/typescript/apps',
      finalOptions.type
    )
    
    const targetPath = path.join(process.cwd(), 'apps', finalOptions.name!)
    
    // Ensure the apps directory exists
    await fs.mkdir(path.join(process.cwd(), 'apps'), { recursive: true })
    
    await this.engine.generateFromTemplate(
      templatePath,
      {
        appName: finalOptions.name,
        displayName: finalOptions.displayName,
        appId: finalOptions.appId,
        framework: finalOptions.framework,
        includeRouter: finalOptions.includeRouter,
        includeTailwind: finalOptions.includeTailwind,
        includeNavigator: finalOptions.includeNavigator,
        includeAuth: finalOptions.includeAuth,
        includeApiClient: finalOptions.includeApiClient,
        port: finalOptions.port,
        includeDatabase: finalOptions.includeDatabase,
        includeValidation: finalOptions.includeValidation,
        includeSwagger: finalOptions.includeSwagger,
        includeGraphQL: finalOptions.includeGraphQL,
        includeAutoUpdater: finalOptions.includeAutoUpdater,
        includeSystemTray: finalOptions.includeSystemTray,
        includeMenuBar: finalOptions.includeMenuBar,
        includeIpc: finalOptions.includeIpc,
        includeDarkMode: finalOptions.includeDarkMode
      },
      {
        outputPath: targetPath,
        dryRun: false
      }
    )
    
    console.log(`✨ Created ${finalOptions.type} app: ${finalOptions.name}`)
    console.log(`📁 Location: ${targetPath}`)
    console.log('\nNext steps:')
    console.log(`  cd apps/${finalOptions.name}`)
    console.log('  pnpm install')
    console.log(finalOptions.type === 'mobile' ? '  pnpm start' : '  pnpm dev')
  }

  private async promptMissingOptions(options: CreateAppOptions): Promise<Required<CreateAppOptions>> {
    const questions = []
    
    if (!options.name) {
      questions.push({
        type: 'input',
        name: 'name',
        message: 'App name:',
        validate: (input: string) => {
          if (!input.trim()) return 'App name is required'
          if (!/^[a-z0-9-]+$/.test(input)) {
            return 'App name must be lowercase alphanumeric with dashes'
          }
          return true
        }
      })
    }
    
    if (options.type === 'web') {
      if (options.framework === undefined) {
        questions.push({
          type: 'list',
          name: 'framework',
          message: 'Choose a framework:',
          choices: [
            { name: 'Vite + React', value: 'vite-react' },
            { name: 'Next.js', value: 'nextjs' }
          ],
          default: 'vite-react'
        })
      }
      
      if (options.includeRouter === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeRouter',
          message: 'Include React Router?',
          default: true
        })
      }
      
      if (options.includeTailwind === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeTailwind',
          message: 'Include Tailwind CSS?',
          default: false
        })
      }
    }

    if (options.type === 'mobile') {
      if (options.displayName === undefined) {
        questions.push({
          type: 'input',
          name: 'displayName',
          message: 'Display name (shown to users):',
          default: options.name || 'Vibes App'
        })
      }

      if (options.includeNavigator === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeNavigator',
          message: 'Include React Navigation?',
          default: true
        })
      }

      if (options.includeAuth === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeAuth',
          message: 'Include authentication setup?',
          default: false
        })
      }

      if (options.includeApiClient === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeApiClient',
          message: 'Include API client?',
          default: true
        })
      }
    }

    if (options.type === 'api') {
      if (options.port === undefined) {
        questions.push({
          type: 'number',
          name: 'port',
          message: 'Port number:',
          default: 3001
        })
      }

      if (options.includeDatabase === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeDatabase',
          message: 'Include database (PostgreSQL with Prisma)?',
          default: true
        })
      }

      if (options.includeAuth === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeAuth',
          message: 'Include authentication (JWT)?',
          default: true
        })
      }

      if (options.includeValidation === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeValidation',
          message: 'Include request validation (Zod)?',
          default: true
        })
      }

      if (options.includeSwagger === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeSwagger',
          message: 'Include Swagger documentation?',
          default: false
        })
      }

      if (options.includeGraphQL === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeGraphQL',
          message: 'Include GraphQL support?',
          default: false
        })
      }
    }

    if (options.type === 'desktop') {
      if (options.displayName === undefined) {
        questions.push({
          type: 'input',
          name: 'displayName',
          message: 'Display name (shown to users):',
          default: options.name || 'Vibes Desktop'
        })
      }

      if (options.appId === undefined) {
        questions.push({
          type: 'input',
          name: 'appId',
          message: 'Application ID:',
          default: `com.vibes.${options.name || 'desktop'}`
        })
      }

      if (options.includeAutoUpdater === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeAutoUpdater',
          message: 'Include auto-updater?',
          default: true
        })
      }

      if (options.includeSystemTray === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeSystemTray',
          message: 'Include system tray support?',
          default: false
        })
      }

      if (options.includeMenuBar === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeMenuBar',
          message: 'Include custom menu bar?',
          default: true
        })
      }

      if (options.includeIpc === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeIpc',
          message: 'Include IPC communication examples?',
          default: true
        })
      }

      if (options.includeDarkMode === undefined) {
        questions.push({
          type: 'confirm',
          name: 'includeDarkMode',
          message: 'Include dark mode support?',
          default: true
        })
      }
    }

    const answers = questions.length > 0
      ? await inquirer.prompt(questions)
      : {}

    return {
      ...options,
      ...answers
    } as Required<CreateAppOptions>
  }
}