#!/usr/bin/env python3
from pathlib import Path
import re, sys

ROOT=Path(sys.argv[1] if len(sys.argv)>1 else '/var/www/html/hdi_nuevo')
MODAL=ROOT/'partials/hdi_editar_modal_static.html'
VALID=ROOT/'api/hdi_validar_documento.php'
LIB=ROOT/'api/hdi_lib.php'
REPORTS=ROOT/'reportes.php'
USERS=ROOT/'usuarios.php'
SURVEYS=ROOT/'encuestas.php'

for p in (MODAL,VALID,LIB,REPORTS,USERS,SURVEYS):
    if not p.is_file():
        raise SystemExit('Falta archivo base: '+str(p))

def strip_block(text,start,end):
    return re.sub(re.escape(start)+r'.*?'+re.escape(end)+r'\s*','',text,flags=re.S)

def write(path,text):
    path.write_text(text,encoding='utf-8')

def insert_before_line_matching(text, pattern, block, error):
    m=re.search(pattern,text,flags=re.M)
    if not m:
        raise SystemExit(error)
    return text[:m.start()]+block+text[m.start():]

# -----------------------------------------------------------------------------
# 1) Modal: asignación AOL + correo automático documental.
#    FIX1: anchors tolerantes a espacios/CRLF/atributos extra.
# -----------------------------------------------------------------------------
s=MODAL.read_text(encoding='utf-8-sig')
AS='<!-- HDI_V6_13_ASSIGNMENT_START -->'; AE='<!-- HDI_V6_13_ASSIGNMENT_END -->'
s=strip_block(s,AS,AE)
assignment=r'''<!-- HDI_V6_13_ASSIGNMENT_START -->
                        <div class="col-12 mb-3">
                            <div class="hdi-v613-assignment" id="hdiV613AssignmentBox">
                                <div class="hdi-v613-field-row">
                                    <div class="hdi-v613-field">
                                        <label for="hdiV613AssignmentSelect">Asignación de caso · Integrador AOL</label>
                                        <select id="hdiV613AssignmentSelect"><option value="">Selecciona Integrador AOL...</option></select>
                                    </div>
                                    <button type="button" class="hdi-v613-save-btn" id="hdiV613AssignButton"><i class="fas fa-user-check"></i> Asignar siniestro</button>
                                </div>
                                <div class="hdi-v613-help">Disponible únicamente para Administrador y Supervisor AOL cuando el flujo responsable del siniestro es AOL.</div>
                                <div class="hdi-v613-status" id="hdiV613AssignmentStatus">Sin asignación actual</div>
                            </div>
                        </div>
<!-- HDI_V6_13_ASSIGNMENT_END -->
'''
s=insert_before_line_matching(
    s,
    r'^[^\n]*\bid=["\']gnp_descripcion_estatus["\'][^\n]*(?:\n|$)',
    assignment,
    'No encuentro anchor flexible gnp_descripcion_estatus en modal'
)

ES='<!-- HDI_V6_13_DOCUMENT_EMAIL_START -->'; EE='<!-- HDI_V6_13_DOCUMENT_EMAIL_END -->'
s=strip_block(s,ES,EE)
email=r'''<!-- HDI_V6_13_DOCUMENT_EMAIL_START -->
                <div class="hdi-v613-email-panel mb-3">
                    <div class="hdi-v613-field-row">
                        <div class="hdi-v613-field">
                            <label for="hdiV613DocumentEmail"><i class="fas fa-envelope"></i> Correo para envío automático de documentos validados</label>
                            <input type="email" id="hdiV613DocumentEmail" maxlength="254" placeholder="correo@dominio.com">
                        </div>
                        <button type="button" class="hdi-v613-save-btn" id="hdiV613EmailSave"><i class="fas fa-save"></i> Guardar correo</button>
                    </div>
                    <div class="hdi-v613-help">Al quedar VALIDADO Identificación oficial, Constancia de situación fiscal y Estado de cuenta, los tres documentos se enviarán automáticamente en PDF a esta dirección.</div>
                    <div class="hdi-v613-doc-state" id="hdiV613EmailDocs"></div>
                    <div class="hdi-v613-status" id="hdiV613EmailStatus">Selecciona un expediente para consultar el estado.</div>
                </div>
<!-- HDI_V6_13_DOCUMENT_EMAIL_END -->
'''
s=insert_before_line_matching(
    s,
    r'^[^\n]*\bdata-pt-panel=["\']documentos-requeridos["\'][^\n]*(?:\n|$)',
    email,
    'No encuentro anchor flexible documentos-requeridos en modal'
)
write(MODAL,s)

# -----------------------------------------------------------------------------
# 2) Validación documental: permiso + motor de correo SMTP.
# -----------------------------------------------------------------------------
s=VALID.read_text(encoding='utf-8-sig')
RS='// HDI_V6_13_EMAIL_REQUIRE_START'; RE='// HDI_V6_13_EMAIL_REQUIRE_END'
s=strip_block(s,RS,RE)
needle="require_once __DIR__ . '/hdi_lib.php';"
m=re.search(r"(?m)^\s*"+re.escape(needle)+r"\s*$",s)
if not m:
    raise SystemExit('No encuentro require hdi_lib en validar documento')
reqblock=RS+"\nrequire_once __DIR__ . '/hdi_v613_email_lib.php';\n"+RE
s=s[:m.end()]+"\n"+reqblock+s[m.end():]

# idempotencia de permiso si hubo una instalación previa parcial
s=re.sub(r"(?m)^\s*hdi_rbac_require_permission\('document_validate'\);\s*\n?",'',s)
login=re.search(r"(?m)^\s*gnp_require_login\(\);\s*$",s)
if not login:
    raise SystemExit('No encuentro gnp_require_login en validar documento')
s=s[:login.end()]+"\nhdi_rbac_require_permission('document_validate');"+s[login.end():]

BS='    // HDI_V6_13_EMAIL_AUTO_START'; BE='    // HDI_V6_13_EMAIL_AUTO_END'
s=strip_block(s,BS,BE)
exec_rx=r"(?m)^\s*\$stmt->execute\(\[':validado'=>\$nuevoEstado \? 1 : 0, ':id'=>\$idDocumento\]\);\s*$"
m=re.search(exec_rx,s)
if not m:
    raise SystemExit('No encuentro update validado')
exec_line=m.group(0)
auto="\n"+BS+"\n    $documentEmail = ['status'=>'NO_APLICA'];\n    if ($nuevoEstado) {\n        try {\n            $documentEmail = hdi_v613_try_auto_email($db, (int)($doc[$fk] ?? 0));\n        } catch (Throwable $mailError) {\n            error_log('HDI V6.13 document email: '.$mailError->getMessage());\n            $documentEmail=['status'=>'ERROR','message'=>'No fue posible procesar el correo automático.'];\n        }\n    }\n"+BE
s=s[:m.end()]+auto+s[m.end():]

# Evita duplicar la llave si ya había una instalación parcial.
s=re.sub(r"(?m)^\s*'document_email'\s*=>\s*\$documentEmail,\s*\n?",'',s)
resp=re.search(r"(?ms)(gnp_response\(\[\s*\n\s*'status'\s*=>\s*'success',\s*\n\s*'message'\s*=>\s*\$nuevoEstado \? 'Documento validado correctamente\.' : 'Validación retirada correctamente\.',\s*\n)",s)
if not resp:
    raise SystemExit('No encuentro respuesta validar documento')
s=s[:resp.end()]+"        'document_email'=>$documentEmail,\n"+s[resp.end():]
write(VALID,s)

# -----------------------------------------------------------------------------
# 3) Alcance central de expedientes.
# -----------------------------------------------------------------------------
s=LIB.read_text(encoding='utf-8-sig')
marker="// HDI_V6_13_FINAL_RBAC_REQUIRE\n"
if marker not in s:
    req_re=re.search(r"(?m)^\s*require_once __DIR__ \. '/\.\./config/session\.php';\s*$",s)
    if not req_re:
        raise SystemExit('No encuentro session require en hdi_lib')
    s=s[:req_re.end()]+"\nrequire_once __DIR__ . '/../config/hdi_rbac.php';\n"+marker+s[req_re.end():]

start=s.find('function gnp_fetch_cedula(')
end=s.find('\nfunction gnp_public_error(',start)
if start<0 or end<0:
    raise SystemExit('No encuentro gnp_fetch_cedula completo')
new_fetch=r'''function gnp_fetch_cedula(
    PDO $db,
    int $id,
    bool $includeInactive = false
): ?array {
    $cols = gnp_columns($db, 'gnp_cedulas');

    if (!$cols) {
        return null;
    }

    $idCol = gnp_id_col($cols);
    $where = ["c.`{$idCol}` = :id"];
    $params = [':id'=>$id];

    if (gnp_has_col($cols, 'tipo_tramite')) {
        $where[] = gnp_pdd_type_condition('c');
    }

    if (!$includeInactive && gnp_has_col($cols, 'activo')) {
        $where[] = '(c.activo = 1 OR c.activo IS NULL)';
    }

    // HDI V6.13 FINAL: el portal del asegurado, encuesta pública y procesos CLI
    // conservan su flujo. El alcance RBAC sólo se aplica a sesiones internas.
    if (gnp_is_internal_session()) {
        $key=hdi_rbac_profile_key();
        $hasFlow=gnp_has_col($cols,'perfil_flujo');

        if (in_array($key,['ADMINISTRADOR','SUPERVISOR_AOL','SUPERVISOR_HDI'],true)) {
            // El Excel autoriza el Panel/Formulario a supervisores sin limitar dominio de caso.
        } elseif (!$hasFlow) {
            $where[]='0=1';
        } elseif ($key==='OPERADOR_AOL') {
            $where[]="UPPER(TRIM(COALESCE(c.perfil_flujo,'')))='AOL'";
        } elseif ($key==='INTEGRADOR_AOL') {
            $where[]="UPPER(TRIM(COALESCE(c.perfil_flujo,'')))='AOL'";
            $where[]='EXISTS (SELECT 1 FROM hdi_caso_asignaciones hra WHERE hra.id_registro=c.`'.$idCol.'` AND hra.activo=1 AND hra.id_usuario=:rbac_uid)';
            $params[':rbac_uid']=(int)(gnp_current_user_id() ?? 0);
        } elseif (in_array($key,['INTEGRADOR_HDI','OPERADOR_HDI'],true)) {
            $where[]="UPPER(TRIM(COALESCE(c.perfil_flujo,''))) IN ('HDI','DEMO HDI')";
        } else {
            $where[]='0=1';
        }
    }

    $stmt = $db->prepare(
        'SELECT c.* FROM gnp_cedulas c WHERE '
        . implode(' AND ', $where)
        . ' LIMIT 1'
    );
    $stmt->execute($params);
    $row = $stmt->fetch();

    return $row ? gnp_normalize_cedula_row($row) : null;
}
'''
s=s[:start]+new_fetch+s[end:]
write(LIB,s)

# -----------------------------------------------------------------------------
# 4) Páginas con permisos explícitos del Excel.
# -----------------------------------------------------------------------------
s=REPORTS.read_text(encoding='utf-8-sig')
if "pdd_require_permission_page('dashboard_view');" not in s:
    if 'pdd_require_internal_page();' not in s:
        raise SystemExit('No encuentro guard de reportes')
    s=s.replace('pdd_require_internal_page();',"pdd_require_permission_page('dashboard_view');",1)
write(REPORTS,s)

s=USERS.read_text(encoding='utf-8-sig')
if "pdd_require_permission_page('users_view');" not in s:
    if 'pdd_require_internal_page();' not in s:
        raise SystemExit('No encuentro guard de usuarios')
    s=s.replace('pdd_require_internal_page();',"pdd_require_permission_page('users_view');",1)
s=re.sub(r"perfiles:\[[^\]]*\]", "perfiles:['ADMINISTRADOR','Supervisor AOL','Integrador AOL','Operador AOL','Supervisor HDI','Operador HDI']", s, count=1)
write(USERS,s)

s=SURVEYS.read_text(encoding='utf-8-sig')
s=s.replace('Vista para todos los usuarios internos. Las respuestas son de solo lectura.','Vista para perfiles autorizados. Las respuestas son de solo lectura.')
write(SURVEYS,s)

print('HDI_V613_FIX1_FLEX_ANCHORS_OK=1')
print('PATCH_HDI_V613_FINAL_OK=1')
