import { Router, Response, NextFunction } from 'express'
import { v4 as uuidv4 } from 'uuid'
import { body, validationResult } from 'express-validator'
import bcrypt from 'bcrypt'
import { db } from '../config/database'
import { authenticate, authorize, AuthRequest } from '../middleware/auth'
import { requirePermission, requireEditPermission } from '../middleware/roleAuth'
import { Employee, LanguageSkill, Skill, UserRole, EmployeeUnitRole } from '@skillmate/shared'
import { syncService } from '../services/syncService'
import { FieldEncryption } from '../services/encryption'

const router = Router()

// Helper function to map old proficiency to new level
function mapProficiencyToLevel(proficiency: string): 'basic' | 'fluent' | 'native' | 'business' {
  const mapping: Record<string, 'basic' | 'fluent' | 'native' | 'business'> = {
    'A1': 'basic',
    'A2': 'basic',
    'B1': 'business',
    'B2': 'business',
    'C1': 'fluent',
    'C2': 'fluent',
    'Muttersprache': 'native',
    'native': 'native',
    'fluent': 'fluent',
    'advanced': 'business',
    'intermediate': 'business',
    'basic': 'basic'
  }
  return mapping[proficiency] || 'basic'
}

// Get all employees
router.get('/', authenticate, requirePermission('employees:read'), async (req: AuthRequest, res, next) => {
  try {
    const employees = db.prepare(`
      SELECT id, first_name, last_name, employee_number, photo, position, official_title,
             department, email, phone, mobile, office, availability,
             clearance_level, clearance_valid_until, clearance_issued_date,
             created_at, updated_at, created_by, updated_by
      FROM employees
      ORDER BY last_name, first_name
    `).all()

    const employeesWithDetails = employees.map((emp: any) => {
      // Get skills
      const skills = db.prepare(`
        SELECT s.id, s.name, s.category, es.level, es.verified, es.verified_by, es.verified_date
        FROM employee_skills es
        JOIN skills s ON es.skill_id = s.id
        WHERE es.employee_id = ?
      `).all(emp.id)

      // Get languages
      const languages = db.prepare(`
        SELECT language, proficiency, certified, certificate_type, is_native, can_interpret
        FROM language_skills
        WHERE employee_id = ?
      `).all(emp.id)

      // Get specializations
      const specializations = db.prepare(`
        SELECT name FROM specializations WHERE employee_id = ?
      `).all(emp.id).map((s: any) => s.name)

      const employee: Employee = {
        id: emp.id,
        firstName: emp.first_name,
        lastName: emp.last_name,
        employeeNumber: emp.employee_number,
        photo: emp.photo,
        position: emp.position,
        officialTitle: emp.official_title || undefined,
        department: emp.department,
        email: emp.email,
        phone: emp.phone,
        mobile: emp.mobile,
        office: emp.office,
        availability: emp.availability,
        skills: skills.map((s: any) => ({
          id: s.id,
          name: s.name,
          category: s.category,
          level: s.level,
          verified: Boolean(s.verified),
          verifiedBy: s.verified_by,
          verifiedDate: s.verified_date ? new Date(s.verified_date) : undefined
        })),
        languages: languages.map((l: any) => ({
          code: l.language,  // Map language to code for new interface
          level: mapProficiencyToLevel(l.proficiency)  // Map old proficiency to new level
        })),
        clearance: emp.clearance_level ? {
          level: emp.clearance_level,
          validUntil: new Date(emp.clearance_valid_until),
          issuedDate: new Date(emp.clearance_issued_date)
        } : undefined,
        specializations,
        createdAt: new Date(emp.created_at),
        updatedAt: new Date(emp.updated_at),
        createdBy: emp.created_by,
        updatedBy: emp.updated_by
      }

      return employee
    })

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

// Get employee by ID
router.get('/:id', authenticate, requirePermission('employees:read'), async (req: AuthRequest, res, next) => {
  try {
    const { id } = req.params

    const emp = db.prepare(`
      SELECT id, first_name, last_name, employee_number, photo, position, official_title,
             department, email, phone, mobile, office, availability,
             clearance_level, clearance_valid_until, clearance_issued_date,
             created_at, updated_at, created_by, updated_by
      FROM employees
      WHERE id = ?
    `).get(id) as any

    if (!emp) {
      return res.status(404).json({ 
        success: false, 
        error: { message: 'Employee not found' } 
      })
    }

    // Get skills
    const skills = db.prepare(`
      SELECT s.id, s.name, s.category, es.level, es.verified, es.verified_by, es.verified_date
      FROM employee_skills es
      JOIN skills s ON es.skill_id = s.id
      WHERE es.employee_id = ?
    `).all(emp.id)

    // Get languages
    const languages = db.prepare(`
      SELECT language, proficiency, certified, certificate_type, is_native, can_interpret
      FROM language_skills
      WHERE employee_id = ?
    `).all(emp.id)

    // Get specializations
    const specializations = db.prepare(`
      SELECT name FROM specializations WHERE employee_id = ?
    `).all(emp.id).map((s: any) => s.name)

    const employee: Employee = {
      id: emp.id,
      firstName: emp.first_name,
      lastName: emp.last_name,
      employeeNumber: emp.employee_number,
      photo: emp.photo,
      position: emp.position,
      officialTitle: emp.official_title || undefined,
      department: emp.department,
      email: emp.email,
      phone: emp.phone,
      mobile: emp.mobile,
      office: emp.office,
      availability: emp.availability,
      skills: skills.map((s: any) => ({
        id: s.id,
        name: s.name,
        category: s.category,
        level: s.level,
        verified: Boolean(s.verified),
        verifiedBy: s.verified_by,
        verifiedDate: s.verified_date ? new Date(s.verified_date) : undefined
      })),
      languages: languages.map((l: any) => ({
        code: l.language,  // Map language to code for new interface
        level: mapProficiencyToLevel(l.proficiency)  // Map old proficiency to new level
      })),
      clearance: emp.clearance_level ? {
        level: emp.clearance_level,
        validUntil: new Date(emp.clearance_valid_until),
        issuedDate: new Date(emp.clearance_issued_date)
      } : undefined,
      specializations,
      createdAt: new Date(emp.created_at),
      updatedAt: new Date(emp.updated_at),
      createdBy: emp.created_by,
      updatedBy: emp.updated_by
    }

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

// Create employee (admin/poweruser only)
router.post('/', 
  authenticate,
  requirePermission('employees:create'),
  [
    body('firstName').notEmpty().trim(),
    body('lastName').notEmpty().trim(),
    body('officialTitle').optional().trim(),
    body('email').isEmail(),
    body('department').notEmpty().trim(),
    body('organizationUnitId').optional({ checkFalsy: true }).isUUID(),
    body('organizationRole').optional({ checkFalsy: true }).isIn(['leiter', 'stellvertreter', 'mitarbeiter', 'beauftragter'])
  ],
  async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      const errors = validationResult(req)
      if (!errors.isEmpty()) {
        return res.status(400).json({ 
          success: false, 
          error: { message: 'Invalid input', details: errors.array() } 
        })
      }

      const employeeId = uuidv4()
      const now = new Date().toISOString()

      const {
        firstName, lastName, employeeNumber, photo, position, officialTitle,
        department, email, phone, mobile, office, availability,
        clearance, skills, languages, specializations,
        userRole, createUser, organizationUnitId, organizationRole
      } = req.body

      if (organizationRole && !organizationUnitId) {
        return res.status(400).json({
          success: false,
          error: { message: 'Organization role requires unit selection' }
        })
      }

      let resolvedDepartment = department
      let resolvedUnitId: string | null = null
      let resolvedUnitRole: EmployeeUnitRole = 'mitarbeiter'

      if (organizationUnitId) {
        const unitRow = db.prepare('SELECT id, name FROM organizational_units WHERE id = ? AND is_active = 1').get(organizationUnitId) as { id: string; name: string } | undefined
        if (!unitRow) {
          return res.status(404).json({ success: false, error: { message: 'Organization unit not found' } })
        }
        resolvedUnitId = unitRow.id
        resolvedDepartment = unitRow.name
        if (organizationRole) {
          resolvedUnitRole = organizationRole as EmployeeUnitRole
        }
      }

      // Insert employee with default values for missing fields
      db.prepare(`
        INSERT INTO employees (
          id, first_name, last_name, employee_number, photo, position, official_title,
          department, email, phone, mobile, office, availability, primary_unit_id,
          clearance_level, clearance_valid_until, clearance_issued_date,
          created_at, updated_at, created_by
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      `).run(
        employeeId,
        firstName,
        lastName,
        employeeNumber || null,
        photo || null,
        position || 'Teammitglied',  // Default position
        officialTitle || null,
        resolvedDepartment,
        email,
        phone || 'Nicht angegeben',  // Default phone
        mobile || null,
        office || null,
        availability || 'available',  // Default availability
        resolvedUnitId,
        clearance?.level || null,
        clearance?.validUntil || null,
        clearance?.issuedDate || null,
        now, now, req.user!.id
      )

      // Insert skills
      if (skills && skills.length > 0) {
        const insertSkill = db.prepare(`
          INSERT INTO employee_skills (employee_id, skill_id, level, verified, verified_by, verified_date)
          VALUES (?, ?, ?, ?, ?, ?)
        `)

        for (const skill of skills) {
          insertSkill.run(
            employeeId,
            skill.id,
            skill.level || null,
            skill.verified ? 1 : 0,
            skill.verifiedBy || null,
            skill.verifiedDate || null
          )
        }
      }

      // Insert languages
      if (languages && languages.length > 0) {
        const insertLang = db.prepare(`
          INSERT INTO language_skills (
            id, employee_id, language, proficiency, certified, 
            certificate_type, is_native, can_interpret
          ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        `)

        for (const lang of languages) {
          insertLang.run(
            uuidv4(),
            employeeId,
            lang.language,
            lang.proficiency,
            lang.certified ? 1 : 0,
            lang.certificateType || null,
            lang.isNative ? 1 : 0,
            lang.canInterpret ? 1 : 0
          )
        }
      }

      // Insert specializations
      if (specializations && specializations.length > 0) {
        const insertSpec = db.prepare(`
          INSERT INTO specializations (id, employee_id, name)
          VALUES (?, ?, ?)
        `)

        for (const spec of specializations) {
          insertSpec.run(uuidv4(), employeeId, spec)
        }
      }

      // Queue sync for new employee
      const newEmployee = {
        id: employeeId,
        firstName,
        lastName,
        employeeNumber: employeeNumber || null,
        photo: photo || null,
        position: position || 'Teammitglied',
        department: resolvedDepartment,
        email,
        phone: phone || 'Nicht angegeben',
        mobile: mobile || null,
        office: office || null,
        availability: availability || 'available',
        clearance,
        skills: skills || [],
        languages: languages || [],
        specializations: specializations || [],
        primaryUnitId: resolvedUnitId,
        unitRole: resolvedUnitId ? resolvedUnitRole : undefined,
        createdAt: now,
        updatedAt: now,
        createdBy: req.user!.id
      }

      // Create user account if requested
      let userId = null
      let temporaryPassword = null
      if (createUser && userRole) {
        try {
          userId = uuidv4()
          // Generate a secure temporary password
          temporaryPassword = `TempPass${Math.random().toString(36).slice(-8)}!@#`
          const hashedPassword = await bcrypt.hash(temporaryPassword, 10)
          
          // Encrypt email for user table storage
          const encryptedEmail = FieldEncryption.encrypt(email)
          
          db.prepare(`
            INSERT INTO users (id, username, email, password, role, employee_id, is_active, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
          `).run(
            userId, email, encryptedEmail, hashedPassword, userRole, employeeId, 1, now, now
          )
          
          console.log(`User created for employee ${firstName} ${lastName} with role ${userRole}`)
        } catch (userError) {
          console.error('Error creating user account:', userError)
          // Continue without failing the employee creation
          temporaryPassword = null
        }
      }

      if (resolvedUnitId) {
        const assignmentId = uuidv4()
        db.prepare(`
          INSERT INTO employee_unit_assignments (
            id, employee_id, unit_id, role, start_date, end_date,
            is_primary, created_at, updated_at
          ) VALUES (?, ?, ?, ?, ?, NULL, 1, ?, ?)
        `).run(
          assignmentId,
          employeeId,
          resolvedUnitId,
          resolvedUnitRole,
          now,
          now,
          now
        )
      }

      await syncService.queueSync('employees', 'create', newEmployee)

      res.status(201).json({ 
        success: true, 
        data: { 
          id: employeeId,
          userId: userId,
          temporaryPassword: temporaryPassword,
          primaryUnitId: resolvedUnitId,
          unitRole: resolvedUnitId ? resolvedUnitRole : undefined
        },
        message: `Employee created successfully${createUser ? ' with user account' : ''}` 
      })
    } catch (error) {
      next(error)
    }
  }
)

// Update employee (admin/poweruser only)
router.put('/:id',
  authenticate,
  requireEditPermission(req => req.params.id),
  [
    body('firstName').notEmpty().trim(),
    body('lastName').notEmpty().trim(),
    body('position').notEmpty().trim(),
    body('officialTitle').optional().trim(),
    body('department').notEmpty().trim(),
    body('email').isEmail(),
    body('phone').notEmpty().trim(),
    body('availability').isIn(['available', 'parttime', 'unavailable', 'busy', 'away', 'vacation', 'sick', 'training', 'operation'])
  ],
  async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      const errors = validationResult(req)
      if (!errors.isEmpty()) {
        return res.status(400).json({ 
          success: false, 
          error: { message: 'Invalid input', details: errors.array() } 
        })
      }

      const { id } = req.params
      const now = new Date().toISOString()

      const {
        firstName, lastName, position, officialTitle, department, email, phone, 
        mobile, office, availability, clearance, skills, languages, specializations
      } = req.body

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

      // Update employee
      db.prepare(`
        UPDATE employees SET
          first_name = ?, last_name = ?, position = ?, official_title = ?, department = ?,
          email = ?, phone = ?, mobile = ?, office = ?, availability = ?,
          clearance_level = ?, clearance_valid_until = ?, clearance_issued_date = ?,
          updated_at = ?, updated_by = ?
        WHERE id = ?
      `).run(
        firstName, lastName, position, officialTitle || null, department,
        email, phone, mobile || null, office || null, availability,
        clearance?.level || null, clearance?.validUntil || null, clearance?.issuedDate || null,
        now, req.user!.id, id
      )

      // Update skills
      if (skills !== undefined) {
        // Delete existing skills
        db.prepare('DELETE FROM employee_skills WHERE employee_id = ?').run(id)
        
        // Insert new skills
        if (skills.length > 0) {
          const insertSkill = db.prepare(`
            INSERT INTO employee_skills (employee_id, skill_id, level, verified, verified_by, verified_date)
            VALUES (?, ?, ?, ?, ?, ?)
          `)

          for (const skill of skills) {
            insertSkill.run(
              id,
              skill.id,
              skill.level || null,
              skill.verified ? 1 : 0,
              skill.verifiedBy || null,
              skill.verifiedDate || null
            )
          }
        }
      }

      // Queue sync for updated employee
      const updatedEmployee = {
        id,
        firstName,
        lastName,
        position,
        officialTitle: officialTitle || null,
        department,
        email,
        phone,
        mobile: mobile || null,
        office: office || null,
        availability,
        clearance,
        skills,
        languages,
        specializations,
        updatedAt: now,
        updatedBy: req.user!.id
      }
      
      await syncService.queueSync('employees', 'update', updatedEmployee)

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

// Delete employee (admin only)
router.delete('/:id',
  authenticate,
  requirePermission('employees:delete'),
  async (req: AuthRequest, res: Response, next: NextFunction) => {
    try {
      const { id } = req.params

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

      // Delete employee and related data
      db.prepare('DELETE FROM employee_skills WHERE employee_id = ?').run(id)
      db.prepare('DELETE FROM language_skills WHERE employee_id = ?').run(id)
      db.prepare('DELETE FROM specializations WHERE employee_id = ?').run(id)
      db.prepare('DELETE FROM employees WHERE id = ?').run(id)

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

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

// Search employees by skills
router.post('/search', authenticate, requirePermission('employees:read'), async (req: AuthRequest, res, next) => {
  try {
    const { skills, category } = req.body

    let query = `
      SELECT DISTINCT e.id, e.first_name, e.last_name, e.employee_number, 
             e.position, e.department, e.availability
      FROM employees e
      JOIN employee_skills es ON e.id = es.employee_id
      JOIN skills s ON es.skill_id = s.id
      WHERE 1=1
    `

    const params: any[] = []

    if (skills && skills.length > 0) {
      const placeholders = skills.map(() => '?').join(',')
      query += ` AND s.name IN (${placeholders})`
      params.push(...skills)
    }

    if (category) {
      query += ` AND s.category = ?`
      params.push(category)
    }

    query += ` ORDER BY e.last_name, e.first_name`

    const results = db.prepare(query).all(...params)

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

export default router
