import { describe, it, beforeEach, afterEach } from 'node:test'
import assert from 'node:assert'
import { FCPClient } from '../../client.js'
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs'
import { tmpdir, homedir } from 'os'
import { join } from 'path'
import yaml from 'js-yaml'

describe('FCPClient - Flow Config Fallback', () => {
  let originalEnv
  let tempHome
  let originalHome

  beforeEach(() => {
    originalEnv = { ...process.env }
    tempHome = mkdtempSync(join(tmpdir(), 'mithril-test-'))
    originalHome = process.env.HOME
    process.env.HOME = tempHome
    process.env.NODE_ENV = 'test'
  })

  afterEach(() => {
    // Restore env properly
    Object.keys(process.env).forEach(key => {
      if (!(key in originalEnv)) {
        delete process.env[key]
      }
    })
    Object.assign(process.env, originalEnv)
    rmSync(tempHome, { recursive: true, force: true })
  })

  it('reads Flow config when env vars missing', () => {
    delete process.env.FCP_API_KEY
    delete process.env.FCP_PROJECT

    // Create Flow config
    const flowDir = join(tempHome, '.flow')
    mkdirSync(flowDir, { recursive: true })
    const config = {
      api_key: 'flow-test-key',
      project: 'flow-test-project'
    }
    writeFileSync(join(flowDir, 'config.yaml'), yaml.dump(config))

    // Should read from config
    const client = new FCPClient()
    assert.strictEqual(client.apiKey, 'flow-test-key')
    assert.strictEqual(client.project, 'flow-test-project')
  })

  it('env vars take precedence over Flow config', () => {
    process.env.FCP_API_KEY = 'env-key'
    process.env.FCP_PROJECT = 'env-project'

    // Create Flow config with different values
    const flowDir = join(tempHome, '.flow')
    mkdirSync(flowDir, { recursive: true })
    const config = {
      api_key: 'flow-key',
      project: 'flow-project'
    }
    writeFileSync(join(flowDir, 'config.yaml'), yaml.dump(config))

    // Should use env vars
    const client = new FCPClient()
    assert.strictEqual(client.apiKey, 'env-key')
    assert.strictEqual(client.project, 'env-project')
  })

  it('partial env vars are supplemented by config', () => {
    process.env.FCP_API_KEY = 'env-key'
    delete process.env.FCP_PROJECT

    // Config has project
    const flowDir = join(tempHome, '.flow')
    mkdirSync(flowDir, { recursive: true })
    const config = {
      api_key: 'flow-key',
      project: 'flow-project'
    }
    writeFileSync(join(flowDir, 'config.yaml'), yaml.dump(config))

    // Should use env key but config project
    const client = new FCPClient()
    assert.strictEqual(client.apiKey, 'env-key')
    assert.strictEqual(client.project, 'flow-project')
  })

  it('handles missing config file gracefully', () => {
    process.env.FCP_API_KEY = 'test-key'
    process.env.FCP_PROJECT = 'test-project'

    // No config file exists
    const client = new FCPClient()
    assert.strictEqual(client.apiKey, 'test-key')
    assert.strictEqual(client.project, 'test-project')
  })

  it('handles invalid YAML gracefully', () => {
    process.env.FCP_API_KEY = 'test-key'
    process.env.FCP_PROJECT = 'test-project'

    // Create invalid YAML
    const flowDir = join(tempHome, '.flow')
    mkdirSync(flowDir, { recursive: true })
    writeFileSync(join(flowDir, 'config.yaml'), 'invalid: yaml: content: {')

    // Should work with env vars despite bad config
    const client = new FCPClient()
    assert.strictEqual(client.apiKey, 'test-key')
    assert.strictEqual(client.project, 'test-project')
  })

  it('error message mentions flow init', () => {
    delete process.env.FCP_API_KEY
    delete process.env.FCP_PROJECT

    // No config file
    assert.throws(
      () => new FCPClient(),
      {
        message: /flow init/
      }
    )
  })

})