import { describe, it, expect } from 'vitest'
import { renderHook } from '@testing-library/react'
import { useTreeValidation } from './useTreeValidation'
import type { TreeStructure } from '@/types'

function makeDecisionNode(overrides: Partial<TreeStructure> = {}): TreeStructure {
  return {
    id: 'root',
    type: 'decision',
    question: 'Is it working?',
    options: [
      { label: 'Yes', next_node_id: 'yes' },
      { label: 'No', next_node_id: 'no' },
    ],
    children: [
      { id: 'yes', type: 'solution', title: 'Great', description: 'All good' },
      { id: 'no', type: 'action', title: 'Fix it', description: 'Try restarting' },
    ],
    ...overrides,
  } as TreeStructure
}

function makeSolutionNode(overrides: Partial<TreeStructure> = {}): TreeStructure {
  return {
    id: 'root',
    type: 'solution',
    title: 'Done',
    description: 'Problem solved',
    ...overrides,
  } as TreeStructure
}

describe('useTreeValidation', () => {
  describe('name validation', () => {
    it('requires a name', () => {
      const { result } = renderHook(() => useTreeValidation('', null, makeSolutionNode()))
      expect(result.current.canPublish).toBe(false)
      expect(result.current.errors.some(e => e.field === 'name')).toBe(true)
    })

    it('rejects whitespace-only name', () => {
      const { result } = renderHook(() => useTreeValidation('   ', null, makeSolutionNode()))
      expect(result.current.canPublish).toBe(false)
    })

    it('rejects name over 255 characters', () => {
      const longName = 'a'.repeat(256)
      const { result } = renderHook(() => useTreeValidation(longName, null, makeSolutionNode()))
      expect(result.current.canPublish).toBe(false)
      expect(result.current.errors.some(e => e.message.includes('255'))).toBe(true)
    })

    it('accepts valid name', () => {
      const { result } = renderHook(() => useTreeValidation('My Tree', 'desc', makeSolutionNode()))
      expect(result.current.canPublish).toBe(true)
    })
  })

  describe('structure validation', () => {
    it('requires tree structure', () => {
      const { result } = renderHook(() => useTreeValidation('My Tree', null, null))
      expect(result.current.canPublish).toBe(false)
      expect(result.current.errors.some(e => e.field === 'tree_structure')).toBe(true)
    })

    it('requires root node type', () => {
      const node = { id: 'root' } as TreeStructure
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
      expect(result.current.errors.some(e => e.field.includes('type'))).toBe(true)
    })

    it('requires decision node question', () => {
      const node = makeDecisionNode({ question: '' })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
      expect(result.current.errors.some(e => e.message.includes('question'))).toBe(true)
    })

    it('requires decision node options', () => {
      const node = makeDecisionNode({ options: [] })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('validates option labels', () => {
      const node = makeDecisionNode({
        options: [{ label: '', next_node_id: 'n1' }],
      })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
      expect(result.current.errors.some(e => e.field.includes('options'))).toBe(true)
    })

    it('requires action node title', () => {
      const node = { id: 'root', type: 'action', title: '', description: 'desc' } as TreeStructure
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('requires action node description', () => {
      const node = { id: 'root', type: 'action', title: 'Title', description: '' } as TreeStructure
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('requires solution node title', () => {
      const node = makeSolutionNode({ title: '' })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('requires solution node description', () => {
      const node = makeSolutionNode({ description: '' })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('validates child node types', () => {
      const node = makeDecisionNode({
        children: [{ id: 'c1' } as TreeStructure],
      })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('validates child decision nodes need question', () => {
      const node = makeDecisionNode({
        children: [
          { id: 'c1', type: 'decision', question: '' } as TreeStructure,
          { id: 'c2', type: 'solution', title: 'Done', description: 'Done' } as TreeStructure,
        ],
      })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })

    it('validates child action/solution need title', () => {
      const node = makeDecisionNode({
        children: [
          { id: 'c1', type: 'action', title: '' } as TreeStructure,
          { id: 'c2', type: 'solution', title: 'Done', description: 'Done' } as TreeStructure,
        ],
      })
      const { result } = renderHook(() => useTreeValidation('Tree', null, node))
      expect(result.current.canPublish).toBe(false)
    })
  })

  describe('warnings', () => {
    it('warns when description is empty', () => {
      const { result } = renderHook(() => useTreeValidation('Tree', '', makeSolutionNode()))
      expect(result.current.warnings.some(w => w.field === 'description')).toBe(true)
    })

    it('warns when description is null', () => {
      const { result } = renderHook(() => useTreeValidation('Tree', null, makeSolutionNode()))
      expect(result.current.warnings.some(w => w.field === 'description')).toBe(true)
    })

    it('no description warning when provided', () => {
      const { result } = renderHook(() => useTreeValidation('Tree', 'A description', makeSolutionNode()))
      expect(result.current.warnings.some(w => w.field === 'description')).toBe(false)
    })

    it('warns when decision has fewer than 2 children', () => {
      const node = makeDecisionNode({
        children: [{ id: 'c1', type: 'solution', title: 'X', description: 'Y' } as TreeStructure],
      })
      const { result } = renderHook(() => useTreeValidation('Tree', 'desc', node))
      expect(result.current.warnings.some(w => w.field === 'tree_structure')).toBe(true)
    })
  })

  describe('valid trees', () => {
    it('accepts complete decision tree', () => {
      const { result } = renderHook(() => useTreeValidation('My Tree', 'A tree', makeDecisionNode()))
      expect(result.current.canPublish).toBe(true)
      expect(result.current.errors).toHaveLength(0)
    })

    it('accepts complete solution tree', () => {
      const { result } = renderHook(() => useTreeValidation('My Tree', 'desc', makeSolutionNode()))
      expect(result.current.canPublish).toBe(true)
      expect(result.current.errors).toHaveLength(0)
    })
  })
})
