const { login, getToken } = require('../lib/auth')
const { getConfig, setConfig, normalizeUrl } = require('../lib/config')
const chalk = require('chalk')
const inquirer = require('inquirer')

function detectShell() {
  const shell = process.env.SHELL || ''
  
  if (shell.includes('fish')) {
    return 'fish'
  }
  
  if (shell.includes('zsh')) {
    return 'zsh'
  }
  
  if (shell.includes('bash')) {
    return 'bash'
  }
  
  if (process.platform === 'win32') {
    if (process.env.PSModulePath) {
      return 'powershell'
    }
    return 'cmd'
  }
  
  return 'bash'
}

function getExportCommand(tokenValue, shell) {
  switch (shell) {
    case 'fish':
      return `set -x BILD_TOKEN "${tokenValue}"`
    case 'powershell':
      return `$env:BILD_TOKEN="${tokenValue}"`
    case 'cmd':
      return `set BILD_TOKEN=${tokenValue}`
    default:
      return `export BILD_TOKEN="${tokenValue}"`
  }
}

async function displayTokenExport() {
  const token = await getToken()
  
  if (!token) {
    console.log(chalk.yellow('\nWarning: No token found to export'))
    return
  }
  
  const shell = detectShell()
  const exportCmd = getExportCommand(token, shell)
  
  console.log(chalk.blue(`\nDetected shell: ${shell}`))
  console.log(chalk.yellow('Copy and run this command to set the environment variable:'))
  console.log(chalk.green(exportCmd))
  console.log('')
  console.log(chalk.dim('Or copy the token directly:'))
  console.log(chalk.dim(token))
}

async function loginCommand(cmsUrl, options = {}) {
  try {
    const config = getConfig()
    let url = cmsUrl || config.cmsUrl

    if (!url) {
      console.error(chalk.red('Error: CMS URL is required'))
      console.log(chalk.yellow('Usage: bild login <cms-url>'))
      console.log(chalk.yellow('Or run: bild init'))
      process.exit(1)
    }

    // Normalize URL to remove trailing slashes
    url = normalizeUrl(url)

    // Validate URL
    try {
      new URL(url)
    } catch {
      console.error(chalk.red('Error: Invalid URL format'))
      process.exit(1)
    }

    // Email/password sign-in (CMS identity provider)
    const usePasswordLogin = Boolean(options.passwordLogin || options.firebase)
    const authApiKeyOpt = options.authApiKey || options.firebaseApiKey

    if (usePasswordLogin) {
      const prompt = inquirer.createPromptModule()
      console.log(chalk.blue(`Email/password sign-in for ${url}...`))
      console.log('')

      const answers = await prompt([
        {
          type: 'input',
          name: 'email',
          message: 'Email:',
          validate: (input) => {
            if (!input) return 'Email is required'
            if (!input.includes('@')) return 'Please enter a valid email address'
            return true
          },
        },
        {
          type: 'password',
          name: 'password',
          message: 'Password:',
          mask: '*',
          validate: (input) => !!input || 'Password is required',
        },
        {
          type: 'input',
          name: 'apiKey',
          message: 'Auth API key (optional; fetched from CMS when omitted):',
          default: authApiKeyOpt || '',
        },
      ])

      try {
        const { login } = require('../lib/auth')
        await login(url, null, {
          email: answers.email,
          password: answers.password,
          apiKey: answers.apiKey || authApiKeyOpt || null,
        })
        
        if (options.env) {
          await displayTokenExport()
        }
        
        return
      } catch (error) {
        console.error(chalk.red(`Sign-in failed: ${error.message}`))
        process.exit(1)
      }
    }

    // If --token flag is used, prompt for token directly
    if (options.token) {
      const prompt = inquirer.createPromptModule()
      console.log(chalk.blue(`Configuring authentication for ${url}...`))
      console.log('')
      
      const { token } = await prompt([
        {
          type: 'input',
          name: 'token',
          message: 'Enter your bearer token:',
          validate: (input) => {
            if (!input) return 'Token is required'
            if (input.length < 50) return 'Token seems too short (should be at least 50 characters)'
            return true
          },
        },
      ])
      
      // Remove "Bearer " prefix if present
      const cleanToken = token.replace(/^Bearer\s+/i, '').trim()
      const { storeToken } = require('../lib/auth')
      await storeToken(cleanToken)
      setConfig('cmsUrl', url)
      console.log(chalk.green('\n✓ Token stored successfully!'))
      
      if (options.env) {
        await displayTokenExport()
      }
      
      return
    }

    console.log(chalk.blue(`Authenticating with ${url}...`))
    
    // Check if user wants to provide Auth0 config manually
    const userConfig = getConfig()
    let auth0Config = null
    
    // Check if Auth0 config is in user config
    if (userConfig.auth0Domain && userConfig.auth0ClientId) {
      auth0Config = {
        domain: userConfig.auth0Domain,
        clientId: userConfig.auth0ClientId,
        clientSecret: userConfig.auth0ClientSecret,
      }
      console.log(chalk.green('Using Auth0 configuration from config file'))
    }
    
    try {
      await login(url, auth0Config, null)
      
      if (options.env) {
        await displayTokenExport()
      }
    } catch (error) {
      if (error.message.includes('timeout') || error.message.includes('callback') || error.message.includes('Authentication timeout')) {
        // Offer to configure Auth0 or manual token entry
        const prompt = inquirer.createPromptModule()
        
        const { action } = await prompt([
          {
            type: 'list',
            name: 'action',
            message: 'How would you like to proceed?',
            choices: [
              { name: 'Configure Auth0 (recommended - enables automatic OAuth)', value: 'auth0' },
              { name: 'Enter token manually', value: 'manual' },
              { name: 'Cancel', value: 'cancel' },
            ],
          },
        ])
        
        if (action === 'auth0') {
          const auth0Answers = await prompt([
            {
              type: 'input',
              name: 'domain',
              message: 'Auth0 Domain (e.g., dev-bildit.auth0.com):',
              validate: (input) => !!input || 'Domain is required',
            },
            {
              type: 'input',
              name: 'clientId',
              message: 'Auth0 Client ID:',
              validate: (input) => !!input || 'Client ID is required',
            },
            {
              type: 'input',
              name: 'clientSecret',
              message: 'Auth0 Client Secret (optional, for confidential clients):',
            },
          ])
          
          // Save to config
          setConfig('auth0Domain', auth0Answers.domain)
          setConfig('auth0ClientId', auth0Answers.clientId)
          if (auth0Answers.clientSecret) {
            setConfig('auth0ClientSecret', auth0Answers.clientSecret)
          }
          
          // Retry with Auth0 config
          console.log(chalk.blue('\nRetrying with Auth0 configuration...'))
          try {
            await login(url, {
              domain: auth0Answers.domain,
              clientId: auth0Answers.clientId,
              clientSecret: auth0Answers.clientSecret || undefined,
            }, null)
            
            if (options.env) {
              await displayTokenExport()
            }
            
            return
          } catch (retryError) {
            console.error(chalk.red(`Auth0 authentication failed: ${retryError.message}`))
            throw retryError
          }
        } else if (action === 'manual') {
          const { manualToken } = await prompt([
            {
              type: 'input',
              name: 'manualToken',
              message: 'Paste your auth token here:',
              validate: (input) => {
                if (!input) return 'Token is required'
                if (input.length < 50) return 'Token seems too short (should be at least 50 characters)'
                return true
              },
            },
          ])
          
          // Remove "Bearer " prefix if present
          const cleanToken = manualToken.replace(/^Bearer\s+/i, '').trim()
          const { storeToken } = require('../lib/auth')
          await storeToken(cleanToken)
          setConfig('cmsUrl', url)
          console.log(chalk.green('\n✓ Token stored successfully!'))
          
          if (options.env) {
            await displayTokenExport()
          }
          
          return
        } else {
          console.log(chalk.red('\n✗ Authentication cancelled.'))
          process.exit(1)
        }
      }
      throw error
    }
  } catch (error) {
    console.error(chalk.red(`Authentication failed: ${error.message}`))
    process.exit(1)
  }
}

module.exports = loginCommand

