(function ($){
'use strict';
function ac_nonce(){ return (window.AC&&AC.nonce)    ? AC.nonce:''; }
function ac_ajax_url(){ return (window.AC&&AC.ajax_url) ? AC.ajax_url:ajaxurl||''; }
function pm_post(action, data, $msg, onSuccess, onFinally){
if($msg) $msg.text('Procesando…').removeClass('is-success is-error').show();
$.post(ac_ajax_url(), $.extend({ action, nonce: ac_nonce() }, data))
.done(function (res){
if(res.success){
if($msg) $msg.text(res.data?.message||'OK').addClass('is-success');
if(onSuccess) onSuccess(res.data);
}else{
const msg=res.data?.message||'Error inesperado.';
if($msg) $msg.text('⚠ ' + msg).addClass('is-error');
}})
.fail(function (xhr){
let msg='Error de conexión.';
try { const d=JSON.parse(xhr.responseText); if(d?.data?.message) msg=d.data.message; } catch (_){}
if(xhr.status===403) msg='Sesión expirada. Recarga la página.';
if(xhr.status===500) msg='Error interno del servidor.';
if($msg) $msg.text('⚠ ' + msg).addClass('is-error');
})
.always(function (){
if(onFinally) onFinally();
});
}
function fmt_eur(n){
return parseFloat(n||0).toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €';
}
function esc(str){
return $('<div>').text(str||'').html();
}
$(document).on('change', '#ac-ext-gen-pass', function (){
$('#ac-ext-pass-manual-wrap').toggle(!this.checked);
if(this.checked) $('#ac-ext-pass-manual').val('');
});
$(document).on('submit', '#ac-ext-crear-cliente-form', function (e){
e.preventDefault();
var $form=$(this);
var $btn=$('#ac-ext-crear-cliente-btn');
var $msg=$('#ac-ext-crear-cliente-msg');
var $card=$('#ac-ext-cliente-creado-card');
var data={};
$form.serializeArray().forEach(function (f){ data[f.name]=f.value; });
data.generar_pass=$('#ac-ext-gen-pass').is(':checked') ? 1:0;
data.enviar_email=$form.find('[name=enviar_email]').is(':checked') ? 1:0;
$btn.prop('disabled', true).text('Creando cuenta…');
$msg.text('').removeClass('is-success is-error');
$card.hide().html('');
pm_post('ac_pm_crear_cliente', data, $msg, function (r){
$msg.text('').removeClass('is-success is-error');
$form[0].reset();
$('#ac-ext-pass-manual-wrap').hide();
var cred_html =
'<div class="ac-pm-ext-cliente-card">' +
'<h3>\u2705 Cuenta creada correctamente</h3>' +
'<p style="font-size:.85rem;color:#374151;margin:0 0 .75rem">' +
'Guarda estas credenciales. La contraseña no se podrá ver de nuevo.' +
'</p>' +
'<div class="ac-pm-ext-cred"><div><strong>Nombre</strong><br>' + esc(r.nombre) + '</div></div>' +
'<div class="ac-pm-ext-cred">' +
'<div><strong>Email</strong><br>' + esc(r.email) + '</div>' +
'<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost ac-ext-copy-cred" data-val="' + esc(r.email) + '">Copiar</button>' +
'</div>' +
'<div class="ac-pm-ext-cred">' +
'<div><strong>Contraseña</strong><br><span style="font-size:1rem;letter-spacing:.08em">' + esc(r.password) + '</span></div>' +
'<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost ac-ext-copy-cred" data-val="' + esc(r.password) + '">Copiar</button>' +
'</div>' +
'<p style="font-size:.75rem;color:#6b7280;margin:.75rem 0 0">' + esc(r.message) + '</p>' +
'</div>';
$card.html(cred_html).slideDown(300);
var nombreOpt=r.nombre + ' (' + r.email + ')';
$('select[name="cliente_id"]').each(function (){
if(!$(this).find('option[value="' + r.id + '"]').length){
$(this).append('<option value="' + r.id + '">' + esc(nombreOpt) + '</option>');
}});
}, function (){ $btn.prop('disabled', false).text('Crear cuenta →'); });
});
$(document).on('click', '.ac-ext-copy-cred', function (){
var val=$(this).data('val');
var $btn=$(this);
navigator.clipboard.writeText(String(val)).then(function (){
$btn.text('\u2713 Copiado');
setTimeout(function (){ $btn.text('Copiar'); }, 2000);
});
});
$(document).on('click', '.ac-ext-toggle-ofertar', function (){
const id=$(this).data('id');
$('#ext-ofertar-' + id).slideToggle(200);
});
$(document).on('click', '.ac-ext-cancel-ofertar', function (){
const id=$(this).data('id');
$('#ext-ofertar-' + id).slideUp(200);
});
$(document).on('submit', '.ac-pm-ext-ofertar-form', function (e){
e.preventDefault();
const $form=$(this);
const $btn=$form.find('[type=submit]');
const id=$form.find('[name=id]').val();
const $msg=$('#ext-pres-msg-' + id);
const data={};
$form.serializeArray().forEach(function (f){ data[f.name]=f.value; });
$btn.prop('disabled', true);
pm_post('ac_pm_ofertar_presupuesto', data, $msg, function (){
$form.closest('.ac-pm-ext-pres-item').fadeOut(400, function (){
$(this).remove();
const remaining=$('.ac-pm-ext-pres-item').length;
if(!remaining){
$('#ac-ext-pres-list').html('<div class="ac-pm-empty">✓ Sin presupuestos pendientes.</div>');
}});
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-ext-rechazar-pres', function (){
const $btn=$(this);
const id=$btn.data('id');
if(!confirm('¿Seguro que quieres rechazar este presupuesto? Se notificará al cliente.')) return;
const $msg=$('#ext-pres-msg-' + id);
$btn.prop('disabled', true);
pm_post('ac_pm_rechazar_presupuesto', { id }, $msg, function (){
$btn.closest('.ac-pm-ext-pres-item').fadeOut(300, function (){ $(this).remove(); });
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('submit', '#ac-ext-nueva-conv-form', function (e){
e.preventDefault();
const $form=$(this);
const $btn=$form.find('[type=submit]');
const $msg=$('#ac-ext-conv-msg');
const data={};
$form.serializeArray().forEach(function (f){ data[f.name]=f.value; });
$btn.prop('disabled', true);
pm_post('ac_pm_nueva_conv', data, $msg, function (r){
$msg.text('✅ Conversación #' + r.conversacion_id + ' creada.').addClass('is-success');
$form[0].reset();
}, function (){ $btn.prop('disabled', false); });
});
function inject_conv_actions(){
const $table=$('#conversaciones table.ac-pm-table tbody');
if(!$table.length) return;
$table.find('tr').each(function (){
const $row=$(this);
if($row.find('.ac-ext-conv-btn-group').length) return;
let conv_id=0;
$row.find('a[href]').each(function (){
const m=$(this).attr('href').match(/[?&]conv(?:ersacion)?[_-]?id=(\d+)/i);
if(m){ conv_id=parseInt(m[1]); return false; }});
if(!conv_id){
const $firstTd=$row.find('td').first();
const m2=($firstTd.attr('data-id')||$firstTd.find('[data-id]').attr('data-id')||'').match(/\d+/);
if(m2) conv_id=parseInt(m2[0]);
}
if(!conv_id) return;
let current_estado=$row.find('.ac-pm-badge, [class*="badge"]').first().attr('class')||'';
current_estado=(current_estado.match(/badge--(\w+)/)||[])[1]||'abierta';
const estados={ abierta: 'Abierta', en_espera: 'En espera', resuelta: 'Resuelta', cerrada: 'Cerrada' };
const options=Object.entries(estados)
.map(([k, l])=> `<option value="${k}" ${k===current_estado ? 'selected':''}>${l}</option>`)
.join('');
const $lastTd=$row.find('td').last();
$lastTd.append(`
<div class="ac-ext-conv-btn-group" data-conv-id="${conv_id}" style="margin-top:.4rem;display:flex;gap:.3rem;align-items:center;flex-wrap:wrap">
<select class="ac-ext-conv-estado-sel" data-id="${conv_id}" style="font-size:.75rem;padding:.2rem .4rem;border:1px solid #e5e3de;border-radius:4px">
${options}
</select>
<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost ac-ext-update-conv" data-id="${conv_id}">Cambiar</button>
<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--red ac-ext-cerrar-conv" data-id="${conv_id}"
${current_estado==='cerrada' ? 'disabled':''}>
Cerrar
</button>
</div>`);
});
}
$(function (){ inject_conv_actions(); });
$(document).on('click', '.ac-ext-update-conv', function (){
const id=$(this).data('id');
const estado=$('.ac-ext-conv-estado-sel[data-id="' + id + '"]').val();
const $btn=$(this);
$btn.prop('disabled', true);
pm_post('ac_pm_update_conv', { id, estado }, null, function (){
const $badge=$btn.closest('tr').find('.ac-pm-badge, [class*="badge"]').first();
const labels={ abierta: 'Abierta', en_espera: 'En espera', resuelta: 'Resuelta', cerrada: 'Cerrada' };
$badge.text(labels[estado]||estado);
$badge.attr('class', ($badge.attr('class')||'').replace(/badge--\w+/, 'badge--' + estado));
if(estado==='cerrada') $btn.closest('.ac-ext-conv-btn-group').find('.ac-ext-cerrar-conv').prop('disabled', true);
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-ext-cerrar-conv', function (){
const id=$(this).data('id');
const $btn=$(this);
if(!confirm('¿Cerrar esta conversación? El cliente no podrá enviar más mensajes.')) return;
$btn.prop('disabled', true);
pm_post('ac_pm_cerrar_conv', { id }, null, function (){
const $badge=$btn.closest('tr').find('.ac-pm-badge, [class*="badge"]').first();
$badge.text('Cerrada').attr('class', ($badge.attr('class')||'').replace(/badge--\w+/, 'badge--cerrada'));
const $sel=$btn.siblings('.ac-ext-conv-estado-sel');
$sel.val('cerrada');
}, function (){ if($btn.prop('disabled')){}});
});
$(document).on('change', '#ac-ext-desc-cliente', function (){
const cliente_id=$(this).val();
if(!cliente_id) return;
load_presupuestos_cliente(cliente_id, $('select[name="presupuesto_id"]', '#ac-ext-descarga-form'));
});
function load_presupuestos_cliente(cliente_id, $sel){
$sel.html('<option value="">Cargando…</option>');
$.post(ac_ajax_url(), {
action: 'ac_pm_get_stats', nonce: ac_nonce(),
}).always(function (){
$sel.html('<option value="">— Sin vincular (opcional) —</option>'
);
});
}
$(document).on('click', '#ac-ext-btn-mis-descargas', function (){
const $panel=$('#ac-ext-descargas-cliente');
const cliente_id=$('#ac-ext-desc-cliente').val();
if($panel.is(':visible')&&!cliente_id){ $panel.slideUp(200); return; }
$panel.slideDown(200);
if(!cliente_id){
$('#ac-ext-descargas-lista').html('<div class="ac-pm-empty">Selecciona un cliente primero.</div>');
return;
}
cargar_descargas_cliente(cliente_id);
});
$(document).on('change', '#ac-ext-desc-cliente', function (){
if($('#ac-ext-descargas-cliente').is(':visible')){
cargar_descargas_cliente($(this).val());
}});
function cargar_descargas_cliente(cliente_id){
if(!cliente_id) return;
const $lista=$('#ac-ext-descargas-lista');
$lista.html('<div class="ac-pm-empty">Cargando…</div>');
pm_post('ac_pm_listar_descargas', { cliente_id }, null, function (rows){
if(!rows||!rows.length){
$lista.html('<div class="ac-pm-empty">No hay descargas para este cliente.</div>');
return;
}
let html='<table class="ac-pm-table"><thead><tr><th>Archivo</th><th>Estado</th><th>Descargas</th><th>Expira</th><th>Acciones</th></tr></thead><tbody>';
rows.forEach(function (d){
const expirada=d.expirada||d.esta_expirada;
const badge=expirada ? 'vencida':'aceptado';
const label=expirada ? 'Expirada':'Activa';
const fecha=d.expira_at ? new Date(d.expira_at).toLocaleString('es-ES', { day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' }):'—';
html +=`<tr id="ext-desc-row-${esc(d.id)}">
<td><strong>${esc(d.nombre_archivo)}</strong>${d.url ? `<br><a href="${esc(d.url)}" target="_blank" rel="noopener" class="ac-pm-link" style="font-size:.75rem">🔗 Enlace</a>`:''}</td>
<td><span class="ac-pm-badge ac-pm-badge--${badge}">${label}</span></td>
<td>${esc(d.descargas)}/${esc(d.max_descargas)}</td>
<td style="font-size:.8rem">${fecha}</td>
<td>
${!expirada ? `<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--red ac-ext-revocar-descarga" data-id="${esc(d.id)}">✕ Revocar</button>`:'<span style="color:#9ca3af;font-size:.8rem">—</span>'}
</td></tr>`;
});
html +='</tbody></table>';
$lista.html(html);
});
}
$(document).on('submit', '#ac-ext-descarga-form', function (e){
e.preventDefault();
const $form=$(this);
const $btn=$('#ac-ext-desc-submit');
const $msg=$('#ac-ext-desc-msg');
const formData=new FormData($form[0]);
formData.append('action', 'ac_pm_crear_descarga');
formData.append('nonce',  ac_nonce());
$btn.prop('disabled', true).text('Subiendo…');
$msg.text('Subiendo archivo…').removeClass('is-success is-error').show();
$.ajax({
url:         ac_ajax_url(),
type:        'POST',
data:        formData,
processData: false,
contentType: false,
success: function (res){
if(res.success){
$msg.text('✅ ' + (res.data?.message||'Enlace creado.')).addClass('is-success');
const url=res.data?.url||'';
if(url){
$msg.append(' <a href="' + url + '" target="_blank" rel="noopener">→ Ver enlace</a>');
}
$form[0].reset();
const cid=$('#ac-ext-desc-cliente').val();
if(cid&&$('#ac-ext-descargas-cliente').is(':visible')) cargar_descargas_cliente(cid);
}else{
$msg.text('⚠ ' + (res.data?.message||'Error al subir.')).addClass('is-error');
}},
error: function (xhr){
let msg='Error de conexión.';
try { const d=JSON.parse(xhr.responseText); if(d?.data?.message) msg=d.data.message; } catch (_){}
$msg.text('⚠ ' + msg).addClass('is-error');
},
complete: function (){
$btn.prop('disabled', false).text('Subir y crear enlace →');
}});
});
$(document).on('click', '.ac-ext-revocar-descarga', function (){
const id=$(this).data('id');
const $btn=$(this);
if(!confirm('¿Revocar este enlace de descarga? El cliente perderá el acceso.')) return;
$btn.prop('disabled', true);
pm_post('ac_pm_revocar_descarga', { id }, null, function (){
$('#ext-desc-row-' + id).fadeOut(300, function (){ $(this).remove(); });
}, function (){ $btn.prop('disabled', false); });
});
function recalcular_factura(){
let base=0;
$('#ac-ext-lineas-tbody .ac-ext-linea-row').each(function (){
const uds=parseFloat($(this).find('.ac-ext-l-uds').val())||0;
const pu=parseFloat($(this).find('.ac-ext-l-pu').val())||0;
const tot=uds * pu;
$(this).find('.ac-ext-l-total').text(fmt_eur(tot));
base +=tot;
});
const iva_pct=parseFloat($('#ac-ext-fac-iva').val())||0;
const iva_imp=base * iva_pct / 100;
const total=base + iva_imp;
$('#ac-ext-fac-base').text(fmt_eur(base));
$('#ac-ext-fac-ivaval').text(fmt_eur(iva_imp));
$('#ac-ext-fac-total').text(fmt_eur(total));
}
$(document).on('input change', '.ac-ext-l-uds, .ac-ext-l-pu, #ac-ext-fac-iva', recalcular_factura);
$(document).on('click', '#ac-ext-add-linea', function (){
const $row=$('<tr class="ac-ext-linea-row">' +
'<td><input type="text" class="ac-ext-l-desc" placeholder="Descripción…"></td>' +
'<td><input type="number" class="ac-ext-l-uds" value="1" min="0.01" step="0.01"></td>' +
'<td><input type="number" class="ac-ext-l-pu" value="0" min="0" step="0.01"></td>' +
'<td class="ac-ext-l-total">0,00 €</td>' +
'<td><button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--red ac-ext-del-linea">✕</button></td>' +
'</tr>');
$('#ac-ext-lineas-tbody').append($row);
recalcular_factura();
});
$(document).on('click', '.ac-ext-del-linea', function (){
if($('#ac-ext-lineas-tbody .ac-ext-linea-row').length <=1) return;
$(this).closest('tr').remove();
recalcular_factura();
});
$(document).on('change', '#ac-ext-fac-cliente', function (){
const cliente_id=$(this).val();
const $sel=$('#ac-ext-fac-presupuesto');
$sel.html('<option value="">— Cargando… —</option>');
if(!cliente_id){
$sel.html('<option value="">— Sin vincular —</option>');
return;
}
pm_post('ac_get_historial', { cliente_id }, null, function (data){
$sel.html('<option value="">— Sin vincular (introduce ID manualmente si lo sabes) —</option>');
});
});
$(document).on('submit', '#ac-ext-factura-form', function (e){
e.preventDefault();
const $form=$(this);
const $btn=$form.find('[type=submit]');
const $msg=$('#ac-ext-fac-msg');
const lineas=[];
$('#ac-ext-lineas-tbody .ac-ext-linea-row').each(function (){
lineas.push({
descripcion:     $(this).find('.ac-ext-l-desc').val(),
unidades:        parseFloat($(this).find('.ac-ext-l-uds').val())||1,
precio_unitario: parseFloat($(this).find('.ac-ext-l-pu').val())||0,
});
});
const data={};
$form.serializeArray().forEach(function (f){ data[f.name]=f.value; });
data.lineas=JSON.stringify(lineas);
$btn.prop('disabled', true);
pm_post('ac_crear_factura', data, $msg, function (r){
$msg.text('✅ Factura ' + (r.ref||'') + ' creada. Total: ' + fmt_eur(r.total)).addClass('is-success');
$form[0].reset();
recalcular_factura();
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-ext-update-factura', function (){
const id=$(this).data('id');
const estado=$('.ac-ext-fac-estado-sel[data-id="' + id + '"]').val();
const $btn=$(this);
$btn.prop('disabled', true);
pm_post('ac_update_factura', { id, estado }, null, function (){
const labels={ borrador: 'Borrador', emitida: 'Emitida', pagada: 'Pagada', vencida: 'Vencida', cancelada: 'Cancelada' };
const $badge=$btn.closest('tr').find('.ac-pm-badge');
$badge.text(labels[estado]||estado)
.attr('class', 'ac-pm-badge ac-pm-badge--' + estado);
$btn.text('✓ OK').addClass('ac-pm-btn--green');
setTimeout(function (){ $btn.text('Actualizar').removeClass('ac-pm-btn--green'); }, 2000);
}, function (){ $btn.prop('disabled', false); });
});
var _plantillas_cache=null;
function render_plantillas(grupos){
const $wrap=$('#ac-ext-plantillas-wrap');
if(!grupos||!grupos.length){
$wrap.html('<div class="ac-pm-empty">No hay plantillas disponibles.</div>');
return;
}
let html='';
grupos.forEach(function (g){
html +='<div style="margin-bottom:1.25rem">';
html +='<h3 class="ac-pm-ext-subtitle">' + esc(g.label) + '</h3>';
(g.items||[]).forEach(function (p){
html +=`<div class="ac-pm-ext-plt-item" id="ext-plt-item-${p.id}">
<div style="flex:1">
<strong>${esc(p.nombre)}</strong>
<div class="ac-pm-ext-plt-body">${esc(p.cuerpo.length > 150 ? p.cuerpo.substr(0, 150) + '…':p.cuerpo)}</div>
</div>
<div style="display:flex;gap:.3rem;flex-shrink:0">
<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost ac-ext-usar-plantilla"
data-texto="${esc(p.cuerpo)}">Usar</button>
<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost ac-ext-editar-plantilla"
data-id="${p.id}" data-nombre="${esc(p.nombre)}"
data-cuerpo="${esc(p.cuerpo)}" data-categoria="${esc(g.categoria)}">✏</button>
<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--red ac-ext-del-plantilla"
data-id="${p.id}">✕</button>
</div></div>`;
});
html +='</div>';
});
$wrap.html(html);
}
$(document).on('click', '#ac-ext-btn-load-plantillas', function (){
if(_plantillas_cache){ render_plantillas(_plantillas_cache); return; }
const $btn=$(this);
$btn.prop('disabled', true).text('Cargando…');
pm_post('ac_pm_get_plantillas', {}, null, function (r){
_plantillas_cache=r.grupos;
render_plantillas(r.grupos);
}, function (){ $btn.prop('disabled', false).text('Cargar plantillas'); });
});
$(document).on('click', '.ac-ext-usar-plantilla', function (){
const texto=$(this).data('texto');
const $textarea=$('[name="cuerpo"]:visible, #ac-chat-input:visible, .ac-msg-input:visible').first();
if($textarea.length){
$textarea.val(texto).trigger('input').focus();
}else{
navigator.clipboard.writeText(texto).then(function (){
alert('Texto de la plantilla copiado al portapapeles.');
});
}});
$(document).on('click', '.ac-ext-editar-plantilla', function (){
const $btn=$(this);
const details=document.querySelector('.ac-pm-ext-details');
if(details) details.open=true;
$('#ac-ext-plt-id').val($btn.data('id'));
$('#ac-ext-plt-nombre').val($btn.data('nombre'));
$('#ac-ext-plt-cat').val($btn.data('categoria'));
$('#ac-ext-plt-cuerpo').val($btn.data('cuerpo'));
$('html, body').animate({
scrollTop: $('#ac-ext-plantilla-form').offset().top - 100
}, 300);
});
$(document).on('click', '#ac-ext-plt-reset', function (){
$('#ac-ext-plantilla-form')[0].reset();
$('#ac-ext-plt-id').val('0');
});
$(document).on('submit', '#ac-ext-plantilla-form', function (e){
e.preventDefault();
const $form=$(this);
const $btn=$form.find('[type=submit]');
const $msg=$('#ac-ext-plt-msg');
const data={};
$form.serializeArray().forEach(function (f){ data[f.name]=f.value; });
$btn.prop('disabled', true);
pm_post('ac_pm_save_plantilla', data, $msg, function (){
$form[0].reset();
$('#ac-ext-plt-id').val('0');
_plantillas_cache=null;
$msg.text('✅ Plantilla guardada.').addClass('is-success');
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-ext-del-plantilla', function (){
const id=$(this).data('id');
const $btn=$(this);
if(!confirm('¿Eliminar esta plantilla definitivamente?')) return;
$btn.prop('disabled', true);
pm_post('ac_pm_delete_plantilla', { id }, null, function (){
$('#ext-plt-item-' + id).fadeOut(300, function (){ $(this).remove(); });
_plantillas_cache=null;
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-ext-regen-contrato', function (){
const id=$(this).data('id');
const $btn=$(this);
const $msg=$('#ext-firma-msg-' + id);
$btn.prop('disabled', true);
pm_post('ac_pm_regenerar_contrato_pdf', { id }, $msg, function (){
$msg.text('✅ PDF regenerado.').addClass('is-success');
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-ext-reenviar-contrato', function (){
const id=$(this).data('id');
const $btn=$(this);
const $msg=$('#ext-firma-msg-' + id);
if(!confirm('¿Reenviar el email del contrato al cliente?')) return;
$btn.prop('disabled', true);
pm_post('ac_pm_reenviar_contrato_email', { id }, $msg, function (r){
$msg.text('✅ ' + (r.message||'Email reenviado.')).addClass('is-success');
$('#ext-firma-row-' + id).find('.ac-pm-badge').text('✓ Sí').attr('class', 'ac-pm-badge ac-pm-badge--aceptado');
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '#ac-ext-btn-exportar', function (){
const tipo=$('#ac-ext-export-tipo').val();
const desde=$('#ac-ext-export-desde').val();
const hasta=$('#ac-ext-export-hasta').val();
const $btn=$(this);
const $msg=$('#ac-ext-export-msg');
$btn.prop('disabled', true).text('Generando…');
$msg.text('Generando CSV…').removeClass('is-success is-error').show();
$.post(ac_ajax_url(), {
action: 'ac_pm_exportar_csv',
nonce:  ac_nonce(),
tipo,
desde,
hasta,
})
.done(function (res){
if(res.success){
const csv=res.data?.csv||'';
const fname=res.data?.filename||(tipo + '_export.csv');
const blob=new Blob([csv], { type: 'text/csv;charset=utf-8;' });
const url=URL.createObjectURL(blob);
const a=document.createElement('a');
a.href=url;
a.download=fname;
a.click();
URL.revokeObjectURL(url);
$msg.text('✅ CSV descargado.').addClass('is-success');
}else{
$msg.text('⚠ ' + (res.data?.message||'Error al exportar.')).addClass('is-error');
}})
.fail(function (xhr){
if(xhr.status===200){
const blob=new Blob([xhr.responseText], { type: 'text/csv;charset=utf-8;' });
const url=URL.createObjectURL(blob);
const a=document.createElement('a');
a.href=url;
a.download=tipo + '_' + desde + '_' + hasta + '.csv';
a.click();
URL.revokeObjectURL(url);
$msg.text('✅ Descarga iniciada.').addClass('is-success');
}else{
$msg.text('⚠ Error al exportar. Inténtalo de nuevo.').addClass('is-error');
}})
.always(function (){
$btn.prop('disabled', false).text('⬇ Descargar CSV');
});
});
$(document).on('click', '#ac-ext-btn-load-cliente', function (){
const cliente_id=$('#ac-ext-vista-cliente-sel').val();
if(!cliente_id){ alert('Selecciona un cliente.'); return; }
const $btn=$(this);
const $data=$('#ac-ext-cliente-data');
$btn.prop('disabled', true).text('Cargando…');
$data.hide();
const $hist=$('#ac-ext-historial-cliente');
$hist.html('<div class="ac-pm-empty">Cargando historial…</div>');
pm_post('ac_get_historial', { cliente_id }, null, function (data){
if(!data){ $hist.html('<div class="ac-pm-empty">Sin datos.</div>'); return; }
const pares=data.pares_linguisticos&&Object.keys(data.pares_linguisticos).length
? Object.entries(data.pares_linguisticos)
.map(([par, n])=> `<div style="display:flex;justify-content:space-between;padding:.4rem 0;border-bottom:1px solid #f5f0e8;font-size:.875rem"><span style="font-family:monospace;font-weight:700;color:#c9842a">${par}</span><span style="color:#9ca3af">${n} encargo${n > 1 ? 's':''}</span></div>`)
.join('')
: '<p style="color:#9ca3af;font-size:.8rem">Sin datos de pares lingüísticos.</p>';
$hist.html(`
<div style="display:grid;grid-template-columns:repeat(2,1fr);gap:.75rem;margin-bottom:1rem">
${[
['Presupuestos totales', data.presupuestos_total, '#D4A853'],
['Encargos aceptados', data.presupuestos_aceptados, '#22C55E'],
['Facturación total', '€ ' + parseFloat(data.importe_total||0).toLocaleString('es-ES', { minimumFractionDigits: 2 }), '#6366F1'],
['Total pagado', '€ ' + parseFloat(data.importe_pagado||0).toLocaleString('es-ES', { minimumFractionDigits: 2 }), '#0D9488'],
['Conversaciones', data.conversaciones_total, '#0EA5E9'],
['Par favorito', data.par_favorito||'—', '#9CA3AF'],
].map(([label, val, color])=>
`<div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:.75rem 1rem;border-top:3px solid ${color}">
<div style="font-size:1.3rem;font-weight:900;color:#111">${val}</div>
<div style="font-size:.65rem;font-weight:700;color:#9ca3af;text-transform:uppercase;letter-spacing:.06em;margin-top:3px">${label}</div>
</div>`
).join('')}
</div>
${data.pares_linguisticos&&Object.keys(data.pares_linguisticos).length ? `
<div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:.75rem 1rem">
<h4 style="font-size:.7rem;text-transform:uppercase;letter-spacing:.1em;color:#9ca3af;margin-bottom:.5rem">Pares lingüísticos utilizados</h4>
${pares}
</div>`:pares}
`);
});
pm_post('ac_get_preferencias', { cliente_id }, null, function (prefs){
if(!prefs) return;
$('#ac-ext-pref-cliente-id').val(cliente_id);
['idioma_origen', 'idioma_destino', 'variante_regional', 'estilo',
'terminologia', 'glosario', 'notas_adicionales'].forEach(function (k){
const val=prefs[k];
if(val!==undefined&&val!==null){
const $el=$('#ac-ext-pref-' + k.replace(/_/g, '-').replace('idioma-origen', 'orig').replace('idioma-destino', 'dest').replace('variante-regional', 'variante').replace('notas-adicionales', 'notas'));
if(!$el.length){
$('[name="' + k + '"]', '#ac-ext-pref-cliente-form').val(val);
}else{
$el.val(val);
}}
});
});
$data.slideDown(200);
$btn.prop('disabled', false).text('Cargar →');
});
$(document).on('submit', '#ac-ext-pref-cliente-form', function (e){
e.preventDefault();
const $form=$(this);
const $btn=$form.find('[type=submit]');
const $msg=$('#ac-ext-pref-msg');
const data={};
$form.serializeArray().forEach(function (f){ data[f.name]=f.value; });
$btn.prop('disabled', true);
pm_post('ac_pm_update_preferencias_cliente', data, $msg, function (){
$msg.text('✅ Preferencias guardadas para el cliente.').addClass('is-success');
setTimeout(function (){ $msg.text(''); }, 3000);
}, function (){ $btn.prop('disabled', false); });
});
$(document).on('click', '.ac-pm-entrega-toggle', function (){
var id=$(this).data('id');
var $panel=$('#ac-entrega-panel-' + id);
var open=$panel.is(':visible');
$panel.slideToggle(200);
$(this).toggleClass('is-open', !open);
});
$(document).on('click', '.ac-pm-entrega-submit', function (){
var $btn=$(this);
var proyecto_id=$btn.data('proyecto-id');
var cliente_id=$btn.data('cliente-id');
var pres_id=$btn.data('presupuesto-id')||0;
var $wrap=$btn.closest('.ac-pm-entrega-inner');
var $file=$wrap.find('.ac-pm-entrega-file');
var $nombre=$wrap.find('.ac-pm-entrega-nombre');
var $horas=$wrap.find('.ac-pm-entrega-horas');
var $maxd=$wrap.find('.ac-pm-entrega-maxdesc');
var $msg=$('#ac-entrega-msg-' + proyecto_id);
var $result=$('#ac-entrega-result-' + proyecto_id);
if(!$file[0].files||!$file[0].files[0]){
$msg.text('\u26a0 Selecciona un archivo primero.').addClass('is-error').removeClass('is-success');
return;
}
if(!cliente_id){
$msg.text('\u26a0 Este proyecto no tiene cliente asignado.').addClass('is-error').removeClass('is-success');
return;
}
var formData=new FormData();
formData.append('action',         'ac_pm_crear_descarga');
formData.append('nonce',          ac_nonce());
formData.append('archivo',        $file[0].files[0]);
formData.append('cliente_id',     cliente_id);
formData.append('nombre_archivo', $nombre.val()||$file[0].files[0].name);
formData.append('horas_expira',   $horas.val()||72);
formData.append('max_descargas',  $maxd.val()||5);
if(pres_id) formData.append('presupuesto_id', pres_id);
$btn.prop('disabled', true).text('Subiendo\u2026');
$msg.text('Subiendo archivo y generando enlace\u2026').removeClass('is-success is-error');
$result.hide().html('');
$.ajax({
url:         ac_ajax_url(),
type:        'POST',
data:        formData,
processData: false,
contentType: false,
success: function (res){
if(res.success){
var url=res.data.url||'';
$msg.text('\u2705 Enlace creado. Cliente notificado.').addClass('is-success').removeClass('is-error');
$result.html('<div class="ac-pm-entrega-result-card">' +
'<strong>\ud83d\udd17 Enlace de descarga generado</strong>' +
'<div class="ac-pm-entrega-url-row">' +
'<span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + esc(url) + '</span>' +
'<button type="button" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost ac-pm-copy-entrega-url" data-url="' + esc(url) + '">Copiar</button>' +
'<a href="' + esc(url) + '" target="_blank" rel="noopener" class="ac-pm-btn ac-pm-btn--sm ac-pm-btn--ghost">Abrir</a>' +
'</div>' +
'<p style="font-size:.72rem;color:#6b7280;margin:.5rem 0 0">' +
'El cliente ha recibido una notificaci\u00f3n en su portal.' +
'</p>' +
'</div>'
).slideDown(250);
$file.val('');
$nombre.val('');
}else{
$msg.text('\u26a0 ' + (res.data&&res.data.message ? res.data.message:'Error al subir.')).addClass('is-error').removeClass('is-success');
}},
error: function (xhr){
var msg='Error de conexi\u00f3n.';
try { var d=JSON.parse(xhr.responseText); if(d&&d.data&&d.data.message) msg=d.data.message; } catch(_){}
if(xhr.status===403) msg='Sesi\u00f3n expirada. Recarga la p\u00e1gina.';
$msg.text('\u26a0 ' + msg).addClass('is-error').removeClass('is-success');
},
complete: function (){
$btn.prop('disabled', false).text('\ud83d\udce4 Subir y enviar enlace al cliente');
}});
});
$(document).on('click', '.ac-pm-copy-entrega-url', function (){
var url=$(this).data('url');
var $btn=$(this);
navigator.clipboard.writeText(url).then(function (){
$btn.text('\u2713 Copiado');
setTimeout(function (){ $btn.text('Copiar'); }, 2000);
});
});
$(function (){
recalcular_factura();
$('a[href^="#ext-"]').on('click', function (e){
const target=$($(this).attr('href'));
if(target.length){
e.preventDefault();
$('html, body').animate({ scrollTop: target.offset().top - 80 }, 400);
}});
const $operativa=$('#operativa .ac-pm-list');
if($operativa.length){
const nuevos=[
['Crear cliente', 'Alta de nueva cuenta de cliente con credenciales.', '#ext-crear-cliente'],
['Presupuestos', 'Gestión completa: ofertar, rechazar y descargar PDF.', '#ext-presupuestos'],
['Nueva conversación', 'Abrir conversación con cualquier cliente asignado.', '#ext-nueva-conv'],
['Descargas seguras', 'Subir archivos y crear enlaces seguros de entrega.', '#ext-crear-descarga'],
['Nueva factura', 'Crear y gestionar facturas con líneas de detalle.', '#ext-nueva-factura'],
['Plantillas', 'Gestionar y usar plantillas de mensajes.', '#ext-plantillas'],
['Exportar CSV', 'Exportar datos de presupuestos, facturas o clientes.', '#ext-exportar'],
['Vista de cliente', 'Consultar historial y preferencias de un cliente concreto.', '#ext-vista-cliente'],
];
nuevos.forEach(function (m){
const already=$operativa.find('a[href="' + m[2] + '"]').length;
if(!already){
$operativa.append(`
<div class="ac-pm-item">
<div class="ac-pm-item__title">
<span>${m[0]}</span>
<a class="ac-pm-link" href="${m[2]}">Abrir</a>
</div>
<div class="ac-pm-item__meta">${m[1]}</div>
</div>`);
}});
}});
})(jQuery);