import { Router } from 'express'
import { v4 as uuidv4 } from 'uuid'
import { db } from '../config/database'
import { authenticate, authorize, AuthRequest } from '../middleware/auth'
import { DEFAULT_SKILLS } from '@skillmate/shared'
import { syncService } from '../services/syncService'

const router = Router()

// Get all skills
router.get('/', authenticate, async (req: AuthRequest, res, next) => {
  try {
    const skills = db.prepare(`
      SELECT id, name, category, description, expires_after
      FROM skills
      ORDER BY category, name
    `).all()

    res.json({ success: true, data: skills })
  } catch (error) {
    next(error)
  }
})

// Get skills hierarchy (categories -> subcategories -> skills)
router.get('/hierarchy', authenticate, async (req: AuthRequest, res, next) => {
  try {
    // Ensure vocabulary table exists (defensive)
    db.exec(`
      CREATE TABLE IF NOT EXISTS controlled_vocabulary (
        id TEXT PRIMARY KEY,
        category TEXT NOT NULL,
        value TEXT NOT NULL,
        description TEXT,
        is_active INTEGER DEFAULT 1,
        created_at TEXT NOT NULL,
        UNIQUE(category, value)
      );
    `)

    let cats = [] as any[]
    let subs = [] as any[]
    try {
      cats = db.prepare(`
        SELECT value AS id, COALESCE(description, value) AS name
        FROM controlled_vocabulary
        WHERE category = 'skill_category'
        ORDER BY id
      `).all() as any[]

      subs = db.prepare(`
        SELECT value AS key, COALESCE(description, value) AS name
        FROM controlled_vocabulary
        WHERE category = 'skill_subcategory'
        ORDER BY key
      `).all() as any[]
    } catch {}

    const subByCat: Record<string, { id: string; name: string }[]> = {}
    for (const s of subs) {
      const [catId, subId] = String(s.key).split('.')
      if (!catId || !subId) continue
      if (!subByCat[catId]) subByCat[catId] = []
      subByCat[catId].push({ id: subId, name: s.name })
    }

    const skills = db.prepare(`
      SELECT id, name, category, description FROM skills
    `).all() as any[]
    const byKey: Record<string, { id: string; name: string; description?: string | null }[]> = {}
    for (const s of skills) {
      const key = s.category
      if (!key) continue
      if (!byKey[key]) byKey[key] = []
      byKey[key].push({ id: s.id, name: s.name, description: s.description || null })
    }

    let hierarchy = cats.map(cat => ({
      id: cat.id,
      name: cat.name,
      subcategories: (subByCat[cat.id] || []).map(sc => ({
        id: sc.id,
        name: sc.name,
        skills: byKey[`${cat.id}.${sc.id}`] || []
      }))
    }))

    // Fallback: if vocabulary is empty, derive from existing skills
    if (hierarchy.length === 0) {
      const seenCats = new Map<string, { id: string; name: string; subs: Map<string, { id: string; name: string; skills: any[] }> }>()
      for (const s of skills) {
        const [catId, subId] = String(s.category || '').split('.')
        if (!catId || !subId) continue
        if (!seenCats.has(catId)) seenCats.set(catId, { id: catId, name: catId, subs: new Map() })
        const cat = seenCats.get(catId)!
        if (!cat.subs.has(subId)) cat.subs.set(subId, { id: subId, name: subId, skills: [] })
        cat.subs.get(subId)!.skills.push({ id: s.id, name: s.name, description: s.description || null })
      }
      hierarchy = Array.from(seenCats.values()).map(c => ({
        id: c.id,
        name: c.name,
        subcategories: Array.from(c.subs.values())
      }))
    }

    res.json({ success: true, data: hierarchy })
  } catch (error) {
    next(error)
  }
})

// Initialize default skills (admin only)
router.post('/initialize', 
  authenticate, 
  authorize('admin'),
  async (req: AuthRequest, res, next) => {
    try {
      const insertSkill = db.prepare(`
        INSERT OR IGNORE INTO skills (id, name, category, description, expires_after)
        VALUES (?, ?, ?, ?, ?)
      `)

      let count = 0
      for (const [category, skills] of Object.entries(DEFAULT_SKILLS)) {
        for (const skillName of skills) {
          const result = insertSkill.run(
            uuidv4(),
            skillName,
            category,
            null,
            category === 'certificates' ? 36 : null // 3 years for certificates
          )
          if (result.changes > 0) count++
        }
      }

      res.json({ 
        success: true, 
        message: `${count} skills initialized successfully` 
      })
    } catch (error) {
      next(error)
    }
  }
)

// Create custom skill (admin/poweruser only)
router.post('/', 
  authenticate, 
  authorize('admin', 'superuser'),
  async (req: AuthRequest, res, next) => {
    try {
      const { id, name, category, description, expiresAfter } = req.body

      // Optional custom id to keep stable
      let skillId = id && typeof id === 'string' && id.length > 0 ? id : uuidv4()
      const exists = db.prepare('SELECT id FROM skills WHERE id = ?').get(skillId)
      if (exists) {
        return res.status(409).json({ success: false, error: { message: 'Skill ID already exists' } })
      }

      // Validate category refers to existing subcategory
      if (!category || String(category).indexOf('.') === -1) {
        return res.status(400).json({ success: false, error: { message: 'Category must be catId.subId' } })
      }
      const subExists = db
        .prepare('SELECT 1 FROM controlled_vocabulary WHERE category = ? AND value = ?')
        .get('skill_subcategory', category)
      if (!subExists) {
        return res.status(400).json({ success: false, error: { message: 'Unknown subcategory' } })
      }
      db.prepare(`
        INSERT INTO skills (id, name, category, description, expires_after)
        VALUES (?, ?, ?, ?, ?)
      `).run(
        skillId,
        name,
        category,
        description || null,
        expiresAfter || null
      )

      // Queue sync for new skill
      const newSkill = {
        id: skillId,
        name,
        category,
        description: description || null,
        expiresAfter: expiresAfter || null
      }
      
      await syncService.queueSync('skills', 'create', newSkill)

      res.status(201).json({ 
        success: true, 
        data: { id: skillId },
        message: 'Skill created successfully' 
      })
    } catch (error) {
      next(error)
    }
  }
)

// Update skill (admin only)
router.put('/:id',
  authenticate,
  authorize('admin'),
  async (req: AuthRequest, res, next) => {
    try {
      const { id } = req.params
      const { name, category, description } = req.body

      // Check if skill exists
      const existing = db.prepare('SELECT id FROM skills WHERE id = ?').get(id)
      if (!existing) {
        return res.status(404).json({ 
          success: false, 
          error: { message: 'Skill not found' } 
        })
      }

      // Validate new category if provided
      if (category) {
        if (String(category).indexOf('.') === -1) {
          return res.status(400).json({ success: false, error: { message: 'Category must be catId.subId' } })
        }
        const subExists = db
          .prepare('SELECT 1 FROM controlled_vocabulary WHERE category = ? AND value = ?')
          .get('skill_subcategory', category)
        if (!subExists) {
          return res.status(400).json({ success: false, error: { message: 'Unknown subcategory' } })
        }
      }

      // Update skill (partial)
      db.prepare(`
        UPDATE skills SET 
          name = COALESCE(?, name), 
          category = COALESCE(?, category), 
          description = COALESCE(?, description)
        WHERE id = ?
      `).run(name || null, category || null, (description ?? null), id)

      // Queue sync for updated skill
      const updatedSkill = {
        id,
        name,
        category,
        description: description || null
      }
      
  await syncService.queueSync('skills', 'update', updatedSkill)

      res.json({ 
        success: true, 
        message: 'Skill updated successfully' 
      })
    } catch (error) {
      next(error)
    }
  }
)

// Delete skill (admin only)
router.delete('/:id',
  authenticate,
  authorize('admin'),
  async (req: AuthRequest, res, next) => {
    try {
      const { id } = req.params
      const existing = db.prepare('SELECT id FROM skills WHERE id = ?').get(id)
      if (!existing) {
        return res.status(404).json({ success: false, error: { message: 'Skill not found' } })
      }
      db.prepare('DELETE FROM employee_skills WHERE skill_id = ?').run(id)
      db.prepare('DELETE FROM skills WHERE id = ?').run(id)
      await syncService.queueSync('skills', 'delete', { id })
      res.json({ success: true, message: 'Skill deleted successfully' })
    } catch (error) { next(error) }
  }
)

// Category management
router.post('/categories', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { id, name } = req.body
    if (!id || !name) return res.status(400).json({ success: false, error: { message: 'id and name required' } })
    const now = new Date().toISOString()
    const exists = db.prepare('SELECT id FROM controlled_vocabulary WHERE category = ? AND value = ?').get('skill_category', id)
    if (exists) return res.status(409).json({ success: false, error: { message: 'Category already exists' } })
    db.prepare('INSERT INTO controlled_vocabulary (id, category, value, description, is_active, created_at) VALUES (?, ?, ?, ?, ?, ?)')
      .run(uuidv4(), 'skill_category', id, name, 1, now)
    res.status(201).json({ success: true, message: 'Category created' })
  } catch (error) { next(error) }
})

router.put('/categories/:catId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId } = req.params
    const { name } = req.body
    if (!name) return res.status(400).json({ success: false, error: { message: 'name required' } })
    const updated = db.prepare('UPDATE controlled_vocabulary SET description = ? WHERE category = ? AND value = ?')
      .run(name, 'skill_category', catId)
    if (updated.changes === 0) return res.status(404).json({ success: false, error: { message: 'Category not found' } })
    res.json({ success: true, message: 'Category updated' })
  } catch (error) { next(error) }
})

router.delete('/categories/:catId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId } = req.params
    const tx = db.transaction(() => {
      const subs = db.prepare('SELECT value FROM controlled_vocabulary WHERE category = ? AND value LIKE ?').all('skill_subcategory', `${catId}.%`) as any[]
      for (const s of subs) {
        db.prepare('DELETE FROM employee_skills WHERE skill_id IN (SELECT id FROM skills WHERE category = ?)').run(s.value)
        db.prepare('DELETE FROM skills WHERE category = ?').run(s.value)
      }
      db.prepare('DELETE FROM controlled_vocabulary WHERE category = ? AND value LIKE ?').run('skill_subcategory', `${catId}.%`)
      const del = db.prepare('DELETE FROM controlled_vocabulary WHERE category = ? AND value = ?').run('skill_category', catId)
      return del.changes
    })
    const changes = tx()
    if (!changes) return res.status(404).json({ success: false, error: { message: 'Category not found' } })
    res.json({ success: true, message: 'Category deleted' })
  } catch (error) { next(error) }
})

// Subcategory management
router.post('/categories/:catId/subcategories', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId } = req.params
    const { id, name } = req.body
    if (!id || !name) return res.status(400).json({ success: false, error: { message: 'id and name required' } })
    const cat = db.prepare('SELECT 1 FROM controlled_vocabulary WHERE category = ? AND value = ?').get('skill_category', catId)
    if (!cat) return res.status(400).json({ success: false, error: { message: 'Category does not exist' } })
    const key = `${catId}.${id}`
    const exists = db.prepare('SELECT id FROM controlled_vocabulary WHERE category = ? AND value = ?').get('skill_subcategory', key)
    if (exists) return res.status(409).json({ success: false, error: { message: 'Subcategory already exists' } })
    const now = new Date().toISOString()
    db.prepare('INSERT INTO controlled_vocabulary (id, category, value, description, is_active, created_at) VALUES (?, ?, ?, ?, ?, ?)')
      .run(uuidv4(), 'skill_subcategory', key, name, 1, now)
    res.status(201).json({ success: true, message: 'Subcategory created' })
  } catch (error) { next(error) }
})

router.put('/categories/:catId/subcategories/:subId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId, subId } = req.params
    const { name } = req.body
    if (!name) return res.status(400).json({ success: false, error: { message: 'name required' } })
    const key = `${catId}.${subId}`
    const updated = db.prepare('UPDATE controlled_vocabulary SET description = ? WHERE category = ? AND value = ?')
      .run(name, 'skill_subcategory', key)
    if (updated.changes === 0) return res.status(404).json({ success: false, error: { message: 'Subcategory not found' } })
    res.json({ success: true, message: 'Subcategory updated' })
  } catch (error) { next(error) }
})

router.delete('/categories/:catId/subcategories/:subId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId, subId } = req.params
    const key = `${catId}.${subId}`
    const tx = db.transaction(() => {
      db.prepare('DELETE FROM employee_skills WHERE skill_id IN (SELECT id FROM skills WHERE category = ?)').run(key)
      db.prepare('DELETE FROM skills WHERE category = ?').run(key)
      const del = db.prepare('DELETE FROM controlled_vocabulary WHERE category = ? AND value = ?').run('skill_subcategory', key)
      return del.changes
    })
    const changes = tx()
    if (!changes) return res.status(404).json({ success: false, error: { message: 'Subcategory not found' } })
    res.json({ success: true, message: 'Subcategory deleted' })
  } catch (error) { next(error) }
})

// Delete skill (admin only)
router.delete('/:id',
  authenticate,
  authorize('admin'),
  async (req: AuthRequest, res, next) => {
    try {
      const { id } = req.params

      // Check if skill exists
      const existing = db.prepare('SELECT id FROM skills WHERE id = ?').get(id)
      if (!existing) {
        return res.status(404).json({ 
          success: false, 
          error: { message: 'Skill not found' } 
        })
      }

      // Delete skill and related data
      db.prepare('DELETE FROM employee_skills WHERE skill_id = ?').run(id)
      db.prepare('DELETE FROM skills WHERE id = ?').run(id)

      // Queue sync for deleted skill
      await syncService.queueSync('skills', 'delete', { id })

      res.json({ 
        success: true, 
        message: 'Skill deleted successfully' 
      })
    } catch (error) {
      next(error)
    }
  }
)

// Category management
router.post('/categories', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { id, name } = req.body
    if (!id || !name) return res.status(400).json({ success: false, error: { message: 'id and name required' } })
    const now = new Date().toISOString()
    const exists = db.prepare('SELECT id FROM controlled_vocabulary WHERE category = ? AND value = ?')
      .get('skill_category', id)
    if (exists) return res.status(409).json({ success: false, error: { message: 'Category already exists' } })
    db.prepare('INSERT INTO controlled_vocabulary (id, category, value, description, is_active, created_at) VALUES (?, ?, ?, ?, ?, ?)')
      .run(uuidv4(), 'skill_category', id, name, 1, now)
    res.status(201).json({ success: true, message: 'Category created' })
  } catch (error) { next(error) }
})

router.put('/categories/:catId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId } = req.params
    const { name } = req.body
    if (!name) return res.status(400).json({ success: false, error: { message: 'name required' } })
    const updated = db.prepare('UPDATE controlled_vocabulary SET description = ? WHERE category = ? AND value = ?')
      .run(name, 'skill_category', catId)
    if (updated.changes === 0) return res.status(404).json({ success: false, error: { message: 'Category not found' } })
    res.json({ success: true, message: 'Category updated' })
  } catch (error) { next(error) }
})

router.delete('/categories/:catId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId } = req.params
    const tx = db.transaction(() => {
      // Delete skills under all subcategories
      const subs = db.prepare('SELECT value FROM controlled_vocabulary WHERE category = ? AND value LIKE ?').all('skill_subcategory', `${catId}.%`) as any[]
      for (const s of subs) {
        db.prepare('DELETE FROM employee_skills WHERE skill_id IN (SELECT id FROM skills WHERE category = ?)').run(s.value)
        db.prepare('DELETE FROM skills WHERE category = ?').run(s.value)
      }
      db.prepare('DELETE FROM controlled_vocabulary WHERE category = ? AND value LIKE ?').run('skill_subcategory', `${catId}.%`)
      const del = db.prepare('DELETE FROM controlled_vocabulary WHERE category = ? AND value = ?').run('skill_category', catId)
      return del.changes
    })
    const changes = tx()
    if (!changes) return res.status(404).json({ success: false, error: { message: 'Category not found' } })
    res.json({ success: true, message: 'Category deleted' })
  } catch (error) { next(error) }
})

// Subcategory management
router.post('/categories/:catId/subcategories', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId } = req.params
    const { id, name } = req.body
    if (!id || !name) return res.status(400).json({ success: false, error: { message: 'id and name required' } })
    const cat = db.prepare('SELECT 1 FROM controlled_vocabulary WHERE category = ? AND value = ?').get('skill_category', catId)
    if (!cat) return res.status(400).json({ success: false, error: { message: 'Category does not exist' } })
    const key = `${catId}.${id}`
    const exists = db.prepare('SELECT id FROM controlled_vocabulary WHERE category = ? AND value = ?')
      .get('skill_subcategory', key)
    if (exists) return res.status(409).json({ success: false, error: { message: 'Subcategory already exists' } })
    const now = new Date().toISOString()
    db.prepare('INSERT INTO controlled_vocabulary (id, category, value, description, is_active, created_at) VALUES (?, ?, ?, ?, ?, ?)')
      .run(uuidv4(), 'skill_subcategory', key, name, 1, now)
    res.status(201).json({ success: true, message: 'Subcategory created' })
  } catch (error) { next(error) }
})

router.put('/categories/:catId/subcategories/:subId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId, subId } = req.params
    const { name } = req.body
    if (!name) return res.status(400).json({ success: false, error: { message: 'name required' } })
    const key = `${catId}.${subId}`
    const updated = db.prepare('UPDATE controlled_vocabulary SET description = ? WHERE category = ? AND value = ?')
      .run(name, 'skill_subcategory', key)
    if (updated.changes === 0) return res.status(404).json({ success: false, error: { message: 'Subcategory not found' } })
    res.json({ success: true, message: 'Subcategory updated' })
  } catch (error) { next(error) }
})

router.delete('/categories/:catId/subcategories/:subId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
  try {
    const { catId, subId } = req.params
    const key = `${catId}.${subId}`
    const tx = db.transaction(() => {
      db.prepare('DELETE FROM employee_skills WHERE skill_id IN (SELECT id FROM skills WHERE category = ?)').run(key)
      db.prepare('DELETE FROM skills WHERE category = ?').run(key)
      const del = db.prepare('DELETE FROM controlled_vocabulary WHERE category = ? AND value = ?').run('skill_subcategory', key)
      return del.changes
    })
    const changes = tx()
    if (!changes) return res.status(404).json({ success: false, error: { message: 'Subcategory not found' } })
    res.json({ success: true, message: 'Subcategory deleted' })
  } catch (error) { next(error) }
})

export default router
