import { ParsedFile } from '../parsed-file'
import {
  isInsideTryCatch,
  hasTryCatchNearby,
  extractFunctionContext,
  searchSurroundingLines,
} from '../code-analysis'

describe('isInsideTryCatch', () => {
  it('returns true when line is inside try block', () => {
    const code = `
function foo() {
  try {
    doSomething()
  } catch (e) {
    handleError(e)
  }
}`
    const file = new ParsedFile(code, 'test.ts')
    // Line 3 is "    doSomething()" inside try
    expect(isInsideTryCatch(file, 3)).toBe(true)
  })

  it('returns false when line is outside try block', () => {
    const code = `
function foo() {
  const x = 1
  try {
    doSomething()
  } catch (e) {
    handleError(e)
  }
}`
    const file = new ParsedFile(code, 'test.ts')
    // Line 2 is "  const x = 1" before try
    expect(isInsideTryCatch(file, 2)).toBe(false)
  })

  it('returns false when no try-catch exists', () => {
    const code = `
function foo() {
  doSomething()
}`
    const file = new ParsedFile(code, 'test.ts')
    expect(isInsideTryCatch(file, 2)).toBe(false)
  })
})

describe('hasTryCatchNearby', () => {
  it('returns true when try-catch wraps the target line', () => {
    const code = `
function foo() {
  try {
    JSON.parse(data)
  } catch (e) {
    console.error(e)
  }
}`
    const file = new ParsedFile(code, 'test.ts')
    expect(hasTryCatchNearby(file, 3)).toBe(true)
  })

  it('returns false when no try-catch nearby', () => {
    const code = `
function foo() {
  JSON.parse(data)
  return data
}`
    const file = new ParsedFile(code, 'test.ts')
    expect(hasTryCatchNearby(file, 2)).toBe(false)
  })

  it('respects function boundaries', () => {
    const code = `
function bar() {
  try {
    something()
  } catch (e) {}
}
function foo() {
  JSON.parse(data)
}`
    const file = new ParsedFile(code, 'test.ts')
    // Line 7 is inside foo(), try-catch is in bar()
    expect(hasTryCatchNearby(file, 7)).toBe(false)
  })
})

describe('extractFunctionContext', () => {
  it('finds named function declaration', () => {
    const code = `
function processData() {
  const result = JSON.parse(data)
}`
    const file = new ParsedFile(code, 'test.ts')
    expect(extractFunctionContext(file, 2)).toBe('processdata')
  })

  it('finds arrow function', () => {
    const code = `
const handleRequest = (req) => {
  const body = JSON.parse(req.body)
}`
    const file = new ParsedFile(code, 'test.ts')
    expect(extractFunctionContext(file, 2)).toBe('handlerequest')
  })

  it('finds method declaration', () => {
    const code = `
class Foo {
  processInput() {
    return JSON.parse(this.data)
  }
}`
    const file = new ParsedFile(code, 'test.ts')
    expect(extractFunctionContext(file, 3)).toBe('processinput')
  })

  it('returns null when no function context found', () => {
    const code = `
const x = JSON.parse(data)
`
    const file = new ParsedFile(code, 'test.ts')
    expect(extractFunctionContext(file, 1)).toBeNull()
  })
})

describe('searchSurroundingLines', () => {
  const code = `import express from 'express'
const app = express()
app.use(authMiddleware)
app.get('/api/data', handler)
app.listen(3000)`
  const file = new ParsedFile(code, 'test.ts')

  it('finds a matching pattern within window', () => {
    const result = searchSurroundingLines(
      file, 3, [/authMiddleware/], 2
    )
    expect(result.found).toBe(true)
    expect(result.matchedLine).toBe(2)
  })

  it('returns not found when pattern is outside window', () => {
    const result = searchSurroundingLines(
      file, 4, [/authMiddleware/], 1
    )
    expect(result.found).toBe(false)
  })

  it('matches multiple patterns (returns first)', () => {
    const result = searchSurroundingLines(
      file, 2, [/express\(\)/, /authMiddleware/], 1
    )
    expect(result.found).toBe(true)
    expect(result.matchedLine).toBe(1)
  })

  it('clamps to file boundaries', () => {
    const result = searchSurroundingLines(
      file, 0, [/express/], 100
    )
    expect(result.found).toBe(true)
  })
})
