const db = require('../config/db'); const crypto = require('crypto'); class HerramientaSet { static async findAll(companyId) { const [sets] = await db.query( `SELECT hs.*, COUNT(hsi.id) as total_herramientas, COALESCE(SUM(hsi.cantidad), 0) as total_items FROM herramientas_sets hs LEFT JOIN herramientas_set_items hsi ON hs.id = hsi.set_id WHERE hs.company_id = ? GROUP BY hs.id ORDER BY hs.id DESC`, [companyId] ); for (const s of sets) { s.herramientas = await this.getItems(s.id); } return sets; } static async findById(id, companyId) { const [rows] = await db.query( 'SELECT * FROM herramientas_sets WHERE id = ? AND company_id = ?', [id, companyId] ); if (!rows[0]) return null; const set = rows[0]; if (!set.qr_token) { set.qr_token = crypto.randomBytes(12).toString('hex'); await db.query('UPDATE herramientas_sets SET qr_token = ? WHERE id = ?', [set.qr_token, set.id]); } set.herramientas = await this.getItems(set.id); return set; } static async findByToken(token) { if (!token) return null; const [rows] = await db.query( `SELECT hs.*, c.name as company_name, c.plan as company_plan FROM herramientas_sets hs INNER JOIN companies c ON hs.company_id = c.id WHERE hs.qr_token = ?`, [token] ); if (!rows[0]) return null; const set = rows[0]; set.herramientas = await this.getItems(set.id); // Obtener asignación activa de custodia si existe const [custodia] = await db.query( `SELECT tha.*, u.nombre as tecnico_nombre, u.email as tecnico_email, tv.titulo as visita_titulo, tv.ticket_id, t.asunto as ticket_asunto FROM tecnico_herramientas_asignaciones tha INNER JOIN users u ON tha.tecnico_id = u.id LEFT JOIN ticket_visitas tv ON tha.ticket_visita_id = tv.id LEFT JOIN tickets t ON tv.ticket_id = t.id WHERE tha.set_id = ? AND tha.estado = 'asignado' ORDER BY tha.id DESC LIMIT 1`, [set.id] ); set.custodia = custodia[0] || null; return set; } static async getItems(setId) { const [items] = await db.query( `SELECT h.*, hsi.cantidad FROM herramientas_set_items hsi INNER JOIN herramientas h ON hsi.herramienta_id = h.id WHERE hsi.set_id = ? ORDER BY h.nombre ASC`, [setId] ); return items; } static async create(data, itemIds = []) { const { company_id, nombre, codigo = null, descripcion = null, categoria = 'general', foto_url = null, qr_token = null, is_active = 1 } = data; const finalQrToken = qr_token || crypto.randomBytes(12).toString('hex'); const [res] = await db.query( `INSERT INTO herramientas_sets (company_id, nombre, codigo, qr_token, descripcion, categoria, foto_url, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [company_id, nombre, codigo, finalQrToken, descripcion, categoria, foto_url, is_active] ); const setId = res.insertId; if (Array.isArray(itemIds) && itemIds.length > 0) { const values = itemIds.map(hId => [setId, parseInt(hId), 1]); await db.query( 'INSERT INTO herramientas_set_items (set_id, herramienta_id, cantidad) VALUES ?', [values] ); } return setId; } static async update(id, companyId, data, itemIds = null) { const fields = []; const values = []; const allowed = ['nombre', 'codigo', 'descripcion', 'categoria', 'foto_url', 'is_active']; for (const [key, val] of Object.entries(data)) { if (allowed.includes(key)) { fields.push(`${key} = ?`); values.push(val); } } if (fields.length > 0) { values.push(id, companyId); await db.query(`UPDATE herramientas_sets SET ${fields.join(', ')} WHERE id = ? AND company_id = ?`, values); } if (Array.isArray(itemIds)) { await db.query('DELETE FROM herramientas_set_items WHERE set_id = ?', [id]); if (itemIds.length > 0) { const valuesItems = itemIds.map(hId => [id, parseInt(hId), 1]); await db.query( 'INSERT INTO herramientas_set_items (set_id, herramienta_id, cantidad) VALUES ?', [valuesItems] ); } } } static async delete(id, companyId) { await db.query('DELETE FROM herramientas_sets WHERE id = ? AND company_id = ?', [id, companyId]); } } module.exports = HerramientaSet;