<?php
/**
 * TrabajadorService - Capa de Abstracción para tabla Trabajador
 *
 * RESUELVE CONFLICTO CRÍTICO: Controla acceso a tabla Trabajador
 * - Solo el módulo recursoshumanos puede modificar trabajadores
 * - Auditoría automática de todos los cambios
 * - Integración de datos con atenciones médicas
 */

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/AuditLog.php';

class TrabajadorService {
    private $pdo;
    private $auditLog;

    public function __construct() {
        $this->pdo = getDB();
        $this->auditLog = new AuditLog();
    }

    /**
     * Obtener trabajador por ID
     *
     * @param int $id ID del trabajador
     * @return array|false Datos del trabajador o false si no existe
     */
    public function getTrabajadorById($id) {
        $stmt = $this->pdo->prepare("SELECT * FROM Trabajador WHERE id_trabajador = ?");
        $stmt->execute([$id]);
        return $stmt->fetch();
    }

    /**
     * Obtener trabajador por DNI/CE
     *
     * @param string $dni DNI o CE del trabajador
     * @return array|false Datos del trabajador o false si no existe
     */
    public function getTrabajadorByDNI($dni) {
        $stmt = $this->pdo->prepare("SELECT * FROM Trabajador WHERE dni_ce = ?");
        $stmt->execute([$dni]);
        return $stmt->fetch();
    }

    /**
     * Obtener todos los trabajadores
     *
     * @param array $filtros Filtros opcionales (empresa, area, etc.)
     * @return array Lista de trabajadores
     */
    public function getAllTrabajadores($filtros = []) {
        $where = [];
        $params = [];

        if (!empty($filtros['empresa'])) {
            $where[] = "empresa = ?";
            $params[] = $filtros['empresa'];
        }

        if (!empty($filtros['area'])) {
            $where[] = "area = ?";
            $params[] = $filtros['area'];
        }

        if (!empty($filtros['nombre'])) {
            $where[] = "apellidos_nombres LIKE ?";
            $params[] = "%" . $filtros['nombre'] . "%";
        }

        $sql = "SELECT * FROM Trabajador";
        if (!empty($where)) {
            $sql .= " WHERE " . implode(" AND ", $where);
        }
        $sql .= " ORDER BY apellidos_nombres ASC";

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }

    /**
     * Crear trabajador con auditoría
     *
     * @param array $data Datos del trabajador
     * @param string $usuario Usuario que crea el registro
     * @param string $modulo Módulo origen (debe ser 'recursoshumanos')
     * @return int|false ID del trabajador creado o false si falla
     * @throws Exception Si el módulo no está autorizado
     */
    public function createTrabajador($data, $usuario = 'sistema', $modulo = 'recursoshumanos') {
        // Control de acceso: Solo recursoshumanos puede crear trabajadores
        if ($modulo !== 'recursoshumanos') {
            throw new Exception("Solo el módulo de Recursos Humanos puede crear trabajadores");
        }

        try {
            $sql = "INSERT INTO Trabajador (
                apellidos_nombres, dni_ce, edad, sexo, empresa, area,
                puesto_trabajo, antiguedad_empleo, turno, tipo_contrato,
                experiencia_puesto, horas_jornada
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([
                $data['nombre'] ?? '',
                $data['dni'] ?? '',
                $data['edad'] ?? 0,
                $data['sexo'] ?? '',
                $data['empresa'] ?? '',
                $data['area'] ?? '',
                $data['puesto_trabajo'] ?? '',
                $data['antiguedad_empleo'] ?? 0,
                $data['turno'] ?? '',
                $data['tipo_contrato'] ?? '',
                $data['experiencia_puesto'] ?? 0,
                $data['horas_jornada'] ?? 0
            ]);

            if ($result) {
                $id = $this->pdo->lastInsertId();

                // Registrar en auditoría
                $this->auditLog->log('Trabajador', $id, 'CREATE', null, $data, $usuario, $modulo);

                return $id;
            }

            return false;

        } catch (PDOException $e) {
            error_log("Error al crear trabajador: " . $e->getMessage());
            throw new Exception("Error al crear trabajador: " . $e->getMessage());
        }
    }

    /**
     * Actualizar trabajador con auditoría
     * SOLO permite actualización desde módulo recursoshumanos
     *
     * @param int $id ID del trabajador
     * @param array $data Nuevos datos
     * @param string $usuario Usuario que modifica
     * @param string $modulo Módulo origen (debe ser 'recursoshumanos')
     * @return bool True si se actualizó correctamente
     * @throws Exception Si el módulo no está autorizado
     */
    public function updateTrabajador($id, $data, $usuario = 'sistema', $modulo = 'recursoshumanos') {
        // CONTROL CRÍTICO: Solo recursoshumanos puede actualizar trabajadores
        if ($modulo !== 'recursoshumanos') {
            throw new Exception("Solo el módulo de Recursos Humanos puede modificar datos de trabajadores. Para actualizar información del trabajador, por favor utilice el módulo de Recursos Humanos.");
        }

        try {
            // Obtener datos anteriores para auditoría
            $oldData = $this->getTrabajadorById($id);

            if (!$oldData) {
                throw new Exception("Trabajador no encontrado con ID: $id");
            }

            $sql = "UPDATE Trabajador SET
                apellidos_nombres = ?,
                dni_ce = ?,
                edad = ?,
                sexo = ?,
                empresa = ?,
                area = ?,
                puesto_trabajo = ?,
                antiguedad_empleo = ?,
                turno = ?,
                tipo_contrato = ?,
                experiencia_puesto = ?,
                horas_jornada = ?
            WHERE id_trabajador = ?";

            $stmt = $this->pdo->prepare($sql);
            $result = $stmt->execute([
                $data['nombre'] ?? $oldData['apellidos_nombres'],
                $data['dni'] ?? $oldData['dni_ce'],
                $data['edad'] ?? $oldData['edad'],
                $data['sexo'] ?? $oldData['sexo'],
                $data['empresa'] ?? $oldData['empresa'],
                $data['area'] ?? $oldData['area'],
                $data['puesto_trabajo'] ?? $oldData['puesto_trabajo'],
                $data['antiguedad_empleo'] ?? $oldData['antiguedad_empleo'],
                $data['turno'] ?? $oldData['turno'],
                $data['tipo_contrato'] ?? $oldData['tipo_contrato'],
                $data['experiencia_puesto'] ?? $oldData['experiencia_puesto'],
                $data['horas_jornada'] ?? $oldData['horas_jornada'],
                $id
            ]);

            if ($result) {
                // Registrar cambios en auditoría
                $this->auditLog->log('Trabajador', $id, 'UPDATE', $oldData, $data, $usuario, $modulo);
            }

            return $result;

        } catch (PDOException $e) {
            error_log("Error al actualizar trabajador: " . $e->getMessage());
            throw new Exception("Error al actualizar trabajador: " . $e->getMessage());
        }
    }

    /**
     * Eliminar trabajador (solo si no tiene atenciones médicas)
     *
     * @param int $id ID del trabajador
     * @param string $usuario Usuario que elimina
     * @param string $modulo Módulo origen
     * @return bool True si se eliminó correctamente
     * @throws Exception Si el trabajador tiene atenciones médicas o no está autorizado
     */
    public function deleteTrabajador($id, $usuario = 'sistema', $modulo = 'recursoshumanos') {
        if ($modulo !== 'recursoshumanos') {
            throw new Exception("Solo el módulo de Recursos Humanos puede eliminar trabajadores");
        }

        // Verificar si tiene atenciones médicas
        if ($this->hasAtencionesMedicas($id)) {
            throw new Exception("No se puede eliminar el trabajador porque tiene atenciones médicas registradas. Por favor, elimine primero las atenciones médicas o archive el trabajador.");
        }

        try {
            // Obtener datos para auditoría
            $oldData = $this->getTrabajadorById($id);

            if (!$oldData) {
                throw new Exception("Trabajador no encontrado");
            }

            $stmt = $this->pdo->prepare("DELETE FROM Trabajador WHERE id_trabajador = ?");
            $result = $stmt->execute([$id]);

            if ($result) {
                // Registrar eliminación en auditoría
                $this->auditLog->log('Trabajador', $id, 'DELETE', $oldData, null, $usuario, $modulo);
            }

            return $result;

        } catch (PDOException $e) {
            error_log("Error al eliminar trabajador: " . $e->getMessage());
            throw new Exception("Error al eliminar trabajador: " . $e->getMessage());
        }
    }

    /**
     * Verificar si trabajador tiene atenciones médicas
     *
     * @param int $id ID del trabajador
     * @return bool True si tiene atenciones médicas
     */
    public function hasAtencionesMedicas($id) {
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) FROM Atencion_Medica WHERE id_trabajador = ?"
        );
        $stmt->execute([$id]);
        return $stmt->fetchColumn() > 0;
    }

    /**
     * Obtener historial de atenciones médicas del trabajador
     *
     * @param int $id ID del trabajador
     * @return array Lista de atenciones médicas
     */
    public function getHistorialMedico($id) {
        $sql = "SELECT
            am.id_atencion, am.fecha_atencion, am.hora_atencion,
            am.lugar_atencion, am.tipo_evento, am.diagnostico_cie10,
            am.tratamiento, am.descanso_medico, am.fecha_inicio_descanso,
            am.fecha_final_descanso, am.seguimiento, am.responsable_registro
        FROM Atencion_Medica am
        WHERE am.id_trabajador = ?
        ORDER BY am.fecha_atencion DESC, am.hora_atencion DESC";

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([$id]);
        return $stmt->fetchAll();
    }

    /**
     * Contar atenciones médicas por tipo de evento
     *
     * @param int $id ID del trabajador
     * @return array Array asociativo [tipo_evento => cantidad]
     */
    public function contarAtencionesPorTipo($id) {
        $sql = "SELECT tipo_evento, COUNT(*) as total
        FROM Atencion_Medica
        WHERE id_trabajador = ?
        GROUP BY tipo_evento";

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([$id]);
        return $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
    }

    /**
     * Obtener resumen estadístico del trabajador
     *
     * @param int $id ID del trabajador
     * @return array Resumen con totales y estadísticas
     */
    public function getResumenTrabajador($id) {
        $trabajador = $this->getTrabajadorById($id);

        if (!$trabajador) {
            return null;
        }

        // Total de atenciones
        $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM Atencion_Medica WHERE id_trabajador = ?");
        $stmt->execute([$id]);
        $totalAtenciones = $stmt->fetchColumn();

        // Atenciones por tipo
        $atencionesPorTipo = $this->contarAtencionesPorTipo($id);

        // Descansos médicos activos
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) FROM Atencion_Medica
            WHERE id_trabajador = ?
            AND descanso_medico = 'Si'
            AND fecha_final_descanso >= CURDATE()"
        );
        $stmt->execute([$id]);
        $descansosActivos = $stmt->fetchColumn();

        // Atenciones con seguimiento pendiente
        $stmt = $this->pdo->prepare(
            "SELECT COUNT(*) FROM Atencion_Medica
            WHERE id_trabajador = ?
            AND seguimiento = 'Si'"
        );
        $stmt->execute([$id]);
        $seguimientosPendientes = $stmt->fetchColumn();

        return [
            'trabajador' => $trabajador,
            'total_atenciones' => $totalAtenciones,
            'atenciones_por_tipo' => $atencionesPorTipo,
            'descansos_activos' => $descansosActivos,
            'seguimientos_pendientes' => $seguimientosPendientes
        ];
    }

    /**
     * Buscar trabajadores por nombre o DNI
     *
     * @param string $termino Término de búsqueda
     * @return array Lista de trabajadores que coinciden
     */
    public function buscarTrabajador($termino) {
        $sql = "SELECT * FROM Trabajador
        WHERE apellidos_nombres LIKE ?
        OR dni_ce LIKE ?
        ORDER BY apellidos_nombres ASC
        LIMIT 20";

        $stmt = $this->pdo->prepare($sql);
        $termino = "%$termino%";
        $stmt->execute([$termino, $termino]);
        return $stmt->fetchAll();
    }
}
?>
