# diag_actualizare.ps1 - depanare PACK_UPDATE (actualizare ROA) pe serverul unui client.
# Urmareste pasii din COMUN\docs\depanare-pack-update.md: test conexiune, UPD_ISTORIC, UPD_LOG,
# script_master.log/script_master2.log (UTL_FILE pe directorul Oracle DMPDIR), versiuni aplicate
# pe fiecare schema, spatiu tablespace (detaliu + cat mai poate creste + top segmente pe cele
# blocate), spatiu disc pe server (optional, -Disc), jobul UPDATEROA_ZILNIC.
# STRICT READ-ONLY: doar select si UTL_FILE in mod 'R'. Nu apeleaza IncheiereActualizare, nu
# relanseaza actualizarea, nu face DDL/DML. Comenzile de deblocare/marire sunt doar AFISATE ca
# sugestie. Singura exceptie e -Disc: scrie un .ps1 temporar in DMPDIR pe server (prin
# sys.ExecuteScriptOS) ca sa citeasca spatiul liber pe discuri, si il sterge la final.
# Parola implicita (ROMFASTSOFT) e cea de dezvoltare, aceeasi folosita si pe serverele de client.
#
# Utilizare:
#   powershell -File COMUN\utile\diag_actualizare.ps1 -Alias ROA_SIGMA
#   powershell -File COMUN\utile\diag_actualizare.ps1 -Alias ROA_ROMCONSTRUCT -Tail 120
#   powershell -File COMUN\utile\diag_actualizare.ps1 -Alias ROA_SIGMA -User contafin_oracle -Password ...
#   powershell -File COMUN\utile\diag_actualizare.ps1 -Alias ROA_SIGMA -DoarLog   # doar script_master.log
#   powershell -File COMUN\utile\diag_actualizare.ps1 -Alias ROA_SIGMA -Disc     # + spatiu liber pe discurile serverului
param(
    [Parameter(Mandatory=$true)][string]$Alias,
    [string]$User = 'contafin_oracle',
    [string]$Password = 'ROMFASTSOFT',
    [int]$Tail = 60,
    [string]$SqlPlus = 'D:\ROA\instantclient_19_18\sqlplus.exe',
    [switch]$DoarLog,
    [switch]$Disc
)

$ErrorActionPreference = 'Stop'

if (-not (Test-Path $SqlPlus)) {
    Write-Output ('EROARE: nu gasesc sqlplus la ' + $SqlPlus)
    exit 1
}

$env:TNS_ADMIN = Split-Path $SqlPlus -Parent
$ConnStr = $User + '/' + $Password + '@' + $Alias

$TempDir = Join-Path $env:TEMP ('diag_actualizare_' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Force -Path $TempDir | Out-Null

function Remove-TempDir {
    if (Test-Path $TempDir) { Remove-Item -LiteralPath $TempDir -Recurse -Force -ErrorAction SilentlyContinue }
}

function Invoke-Sql {
    param([string]$Sql)
    $sqlFile = Join-Path $TempDir ('q_' + [guid]::NewGuid().ToString('N') + '.sql')
    [System.IO.File]::WriteAllText($sqlFile, $Sql, [System.Text.Encoding]::ASCII)
    try {
        $out = & $SqlPlus -L -S $ConnStr ('@' + $sqlFile) 2>&1
        $code = $LASTEXITCODE
    } catch {
        $out = 'EROARE lansare sqlplus: ' + $_.Exception.Message
        $code = -1
    }
    Remove-Item -LiteralPath $sqlFile -Force -ErrorAction SilentlyContinue
    [PSCustomObject]@{ Text = ($out -join "`n"); Code = $code }
}

function Show-Section {
    param([string]$Title, [string]$Text)
    Write-Output ''
    Write-Output ('===== ' + $Title + ' =====')
    Write-Output $Text
    if ($Text -match 'ORA-00942|ORA-01031') {
        Write-Output '[AVERTISMENT] lipsesc probabil drepturi de acces (ORA-00942/ORA-01031) - pasul de mai sus poate fi incomplet cu acest utilizator.'
    }
}

function Wait-RemoteFile {
    # asteapta aparitia unui fisier scris de sys.ExecuteScriptOS (asincron) - polling, nu instant
    param([string]$Directory, [string]$FileName, [int]$TimeoutSec = 60)
    $deadline = (Get-Date).AddSeconds($TimeoutSec)
    while ((Get-Date) -lt $deadline) {
        $r = Invoke-Sql -Sql @"
set pagesize 0 linesize 100 trimspool on feedback off heading off
select dbms_lob.fileexists(bfilename('$Directory','$FileName')) from dual;
exit
"@
        if ($r.Text -match '1') { return $true }
        Start-Sleep -Seconds 2
    }
    return $false
}

# ---------- 1. Test conexiune ----------
Write-Output '===== 1. TEST CONEXIUNE ====='
Write-Output ('Alias=' + $Alias + '  User=' + $User + '  TNS_ADMIN=' + $env:TNS_ADMIN)
$r1 = Invoke-Sql -Sql @"
set pagesize 0 linesize 250 trimspool on feedback off heading off
select 'CONEXIUNE_OK' from dual;
select 'VERSIUNE DB: ' || banner from v`$version where rownum = 1;
select 'SCHEMA CONECTATA: ' || sys_context('userenv','session_user') || '   DB: ' || sys_context('userenv','db_name') from dual;
exit
"@
Write-Output $r1.Text
if ($r1.Code -ne 0 -or $r1.Text -notmatch 'CONEXIUNE_OK') {
    Write-Output ''
    Write-Output 'EROARE: conexiunea a esuat. Verifica:'
    Write-Output '  - tunelul SSH pe 1521 e deschis?'
    Write-Output ('  - aliasul TNS ' + $Alias + ' exista in ' + $env:TNS_ADMIN + '\tnsnames.ora si tinteste 127.0.0.1?')
    Write-Output '  - user/parola corecte? (implicit contafin_oracle/ROMFASTSOFT)'
    Remove-TempDir
    exit 1
}

# ---------- 2. UPD_ISTORIC ----------
if (-not $DoarLog) {
$r2 = Invoke-Sql -Sql @"
set pagesize 200 linesize 200 trimspool on feedback off
column dataora_start format a19
column dataora_end format a30
column stare_text format a26
select * from (
  select to_char(dataora_start,'yyyy-mm-dd hh24:mi:ss') dataora_start,
         nvl(to_char(dataora_end,'yyyy-mm-dd hh24:mi:ss'), '<<< NEINCHEIATA >>>') dataora_end,
         decode(stare, 0,'0-pornire', 1,'1-descarcare aplicatii', 2,'2-generare scripturi',
                3,'3-aplicare scripturi', 4,'4-incheiat', 'necunoscuta(' || stare || ')') stare_text
    from upd_istoric
   order by dataora_start desc
) where rownum <= 10;
exit
"@
Show-Section -Title '2. UPD_ISTORIC (ultimele 10 rulari)' -Text $r2.Text

# ---------- 3. UPD_LOG (rularea curenta) ----------
$r3 = Invoke-Sql -Sql @"
set pagesize 0 linesize 250 trimspool on feedback off heading off long 32000 longchunksize 32000
select 'AVERTISMENT: UPD_LOG se goleste la fiecare rulare; erorile din etapa 3 (aplicare scripturi in SQL*Plus extern) NU ajung aici - vezi script_master.log mai jos.' from dual;
select '-------------------------------------------' from dual;
select 'SECV ' || secventa || '  SCHEMA=' || nvl(schema,'-') || '  SCRIPT=' || nvl(script,'-') ||
       '  ' || to_char(dataora,'yyyy-mm-dd hh24:mi:ss') || chr(10) ||
       nvl(explicatie,'(fara explicatie)') || chr(10) || '-------------------------------------------'
  from upd_log
 where dataora_start = (select max(dataora_start) from upd_log)
 order by secventa;
exit
"@
Show-Section -Title '3. UPD_LOG (rularea curenta)' -Text $r3.Text
}

# ---------- 4. script_master.log / script_master2.log (UTL_FILE pe DMPDIR) ----------
foreach ($logFile in @('script_master.log', 'script_master2.log')) {
$r4 = Invoke-Sql -Sql @"
set serveroutput on size 1000000
set feedback off
declare
  ln_n    pls_integer := $Tail;
  la_buf  dbms_sql.varchar2a;
  ln_idx  pls_integer := 0;
  ln_cnt  pls_integer := 0;
  lc_line varchar2(32767);
  lf      utl_file.file_type;
  lc_path all_directories.directory_path%type;
begin
  begin
    select directory_path into lc_path from all_directories where directory_name = 'DMPDIR';
  exception when no_data_found then lc_path := '(directorul Oracle DMPDIR nu exista)';
  end;
  dbms_output.put_line('Director DMPDIR -> ' || lc_path || '   fisier: $logFile');
  lf := utl_file.fopen('DMPDIR', '$logFile', 'R', 32767);
  begin
    loop
      utl_file.get_line(lf, lc_line, 32767);
      ln_idx := mod(ln_cnt, ln_n) + 1;
      la_buf(ln_idx) := lc_line;
      ln_cnt := ln_cnt + 1;
    end loop;
  exception when no_data_found then null;
  end;
  utl_file.fclose(lf);
  dbms_output.put_line('total linii citite: ' || ln_cnt || '   (ultimele ' || ln_n || ' afisate mai jos)');
  dbms_output.put_line('-------------------------------------------');
  if ln_cnt <= ln_n then
    for i in 1 .. ln_cnt loop dbms_output.put_line(la_buf(i)); end loop;
  else
    for i in 0 .. ln_n - 1 loop dbms_output.put_line(la_buf(mod(ln_cnt + i, ln_n) + 1)); end loop;
  end if;
exception
  when others then
    if utl_file.is_open(lf) then utl_file.fclose(lf); end if;
    if sqlcode = -29280 then
      dbms_output.put_line('EROARE: directorul Oracle DMPDIR nu exista sau alias gresit (ORA-29280).');
    elsif sqlcode = -29283 then
      dbms_output.put_line('EROARE: fisierul $logFile nu exista in DMPDIR sau nu poate fi citit (ORA-29283). Normal daca actualizarea nu a ajuns inca la etapa 3, sau pentru script_master2.log daca rularea a picat inainte de pasii finali.');
    else
      dbms_output.put_line('EROARE: ' || sqlerrm);
    end if;
end;
/
exit
"@
Show-Section -Title ('4. ' + $logFile) -Text $r4.Text
}

if ($DoarLog) { Remove-TempDir; exit 0 }

# ---------- 5. Versiuni per schema ----------
$rSchemas = Invoke-Sql -Sql @"
set pagesize 0 linesize 200 trimspool on feedback off heading off
select owner from all_tables where table_name = 'VERSIUNE' order by owner;
exit
"@
$schemas = @($rSchemas.Text -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ -match '^[A-Z_][A-Z0-9_]*$' })

if ($schemas.Count -eq 0) {
    Show-Section -Title '5. VERSIUNI PE SCHEMA' -Text ('Nu am gasit nicio schema cu tabela VERSIUNE (all_tables).' + "`n" + $rSchemas.Text)
} else {
    $sb = New-Object System.Text.StringBuilder
    [void]$sb.AppendLine('set pagesize 0 linesize 250 trimspool on feedback off heading off')
    foreach ($sch in $schemas) {
        $prefix = if ($sch -eq 'CONTAFIN_ORACLE') { 'CO' } else { 'FF' }
        [void]$sb.AppendLine(@"
select 'ULTIMA    [$sch] ' || tip_script || '  data=' || to_char(data_script,'yyyy-mm-dd') || '  seq=' || seq_script
  from (select tip_script, data_script, seq_script from $sch.VERSIUNE order by data_script desc, seq_script desc)
 where rownum = 1;
"@)
        [void]$sb.AppendLine(@"
select 'CANDIDAT  [$sch] ' || msg from (
  select msg, ord from (
    select script_name || '  (data=' || to_char(script_date,'yyyy-mm-dd') || '  seq=' || script_seq || ')' msg, 1 ord
      from (
        select d.script_name, d.script_date, d.script_seq
          from upd_database d,
               (select data_script mx_date, seq_script mx_seq from (
                  select data_script, seq_script from $sch.VERSIUNE order by data_script desc, seq_script desc
                ) where rownum = 1) w
         where d.script_name like '$prefix\_%' escape '\'
           and (d.script_date > w.mx_date or (d.script_date = w.mx_date and d.script_seq > w.mx_seq))
         order by d.script_date, d.script_seq
      ) where rownum = 1
    union all
    select '(la zi - niciun script $prefix neaplicat gasit dupa ultima versiune)' msg, 2 ord from dual
  ) order by ord
) where rownum = 1;
"@)
    }
    [void]$sb.AppendLine('exit')
    $r5 = Invoke-Sql -Sql $sb.ToString()
    Show-Section -Title '5. VERSIUNI PE SCHEMA (ultima aplicata / prima neaplicata - candidat)' -Text $r5.Text
}

# ---------- 6. Spatiu tablespace: detaliu pe datafile + cat mai poate creste ----------
$r6 = Invoke-Sql -Sql @"
set pagesize 100 linesize 250 trimspool on feedback off
column tablespace_name format a15
column file_name format a55
column autoext format a4
select f.tablespace_name, f.file_name,
       round(f.bytes/1048576) mb_curent,
       round(f.maxbytes/1048576) mb_max,
       f.autoextensible autoext,
       round(f.increment_by * t.block_size / 1048576) mb_increment
  from dba_data_files f, dba_tablespaces t
 where f.tablespace_name = t.tablespace_name
 order by f.tablespace_name, f.file_name;
column tablespace_name format a15
column stare format a26
with ts_free as (
  select tablespace_name, sum(bytes) free_bytes from dba_free_space group by tablespace_name
), agg as (
  select f.tablespace_name, sum(f.bytes) alocat_bytes, sum(f.maxbytes) max_bytes,
         sum(greatest(f.maxbytes - f.bytes, 0)) creste_bytes
    from dba_data_files f
   group by f.tablespace_name
)
select a.tablespace_name,
       round(a.alocat_bytes/1048576) mb_alocat,
       round(a.max_bytes/1048576) mb_max,
       round(nvl(tf.free_bytes,0)/1048576) mb_liber,
       round((nvl(tf.free_bytes,0) + a.creste_bytes)/1048576) mb_poate_creste,
       case when a.max_bytes > 0 and (nvl(tf.free_bytes,0) + a.creste_bytes) < 1048576
            then 'ATENTIE: MAXBYTES ATINS' end stare
  from agg a, ts_free tf
 where a.tablespace_name = tf.tablespace_name(+)
 order by a.tablespace_name;
exit
"@
Show-Section -Title '6. SPATIU TABLESPACE (detaliu pe datafile + cat mai poate creste)' -Text ('mb_poate_creste = liber curent + (maxbytes - alocat) - spatiul real disponibil inainte de ORA-01653, nu doar liberul de acum.' + "`n`n" + $r6.Text)

# tablespace-urile cu maxbytes efectiv atins - identificate separat, pentru top segmente mai jos
$r6m = Invoke-Sql -Sql @"
set pagesize 0 linesize 100 trimspool on feedback off heading off
with ts_free as (
  select tablespace_name, sum(bytes) free_bytes from dba_free_space group by tablespace_name
), agg as (
  select f.tablespace_name, sum(f.maxbytes) max_bytes, sum(greatest(f.maxbytes - f.bytes, 0)) creste_bytes
    from dba_data_files f
   group by f.tablespace_name
)
select 'TS_ATENTIE|' || a.tablespace_name
  from agg a, ts_free tf
 where a.tablespace_name = tf.tablespace_name(+)
   and a.max_bytes > 0
   and (nvl(tf.free_bytes,0) + a.creste_bytes) < 1048576;
exit
"@
$tsProblema = @($r6m.Text -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_.StartsWith('TS_ATENTIE|') } | ForEach-Object { $_.Substring(11) } | Where-Object { $_ -match '^[A-Z0-9_]+$' })

if ($tsProblema.Count -gt 0) {
    $sbSeg = New-Object System.Text.StringBuilder
    [void]$sbSeg.AppendLine('set pagesize 0 linesize 250 trimspool on feedback off heading off')
    foreach ($ts in $tsProblema) {
        [void]$sbSeg.AppendLine("select 'Tablespace $ts - top 15 segmente:' from dual;")
        [void]$sbSeg.AppendLine(@"
select rpad(owner,20) || rpad(segment_name,35) || rpad(segment_type,18) || round(bytes/1048576) || ' MB'
  from (select owner, segment_name, segment_type, bytes from dba_segments where tablespace_name = '$ts' order by bytes desc)
 where rownum <= 15;
"@)
        if ($ts -eq 'SYSTEM') {
            [void]$sbSeg.AppendLine("select 'NOTA: privilegiile ANY (ex. DROP ANY TABLE/TRUNCATE ANY TABLE) nu se aplica pe obiecte din schema SYS cand O7_DICTIONARY_ACCESSIBILITY=FALSE - curatarea unui tabel din SYS cere conectare SYSDBA, nu contafin_oracle.' from dual;")
        }
    }
    [void]$sbSeg.AppendLine('exit')
    $r6s = Invoke-Sql -Sql $sbSeg.ToString()
    Write-Output ''
    Write-Output ('--- Top segmente pe tablespace-urile marcate ATENTIE (' + ($tsProblema -join ', ') + ') ---')
    Write-Output $r6s.Text
}

# ---------- 7. Spatiu disc pe server (optional, scrie un .ps1 temporar in DMPDIR) ----------
Write-Output ''
Write-Output '===== 7. SPATIU DISC (server) ====='
if (-not $Disc) {
    Write-Output 'Sarit implicit - ruleaza cu -Disc pentru spatiul liber pe discurile fizice ale serverului.'
    Write-Output 'Este singura parte a scriptului care NU e strict read-only: scrie un .ps1 temporar in DMPDIR (prin sys.ExecuteScriptOS) si il sterge la final.'
} else {
    $rPaths = Invoke-Sql -Sql @"
set pagesize 0 linesize 300 trimspool on feedback off heading off
select 'DATAFILE_PATH|' || file_name from dba_data_files order by file_name;
exit
"@
    $datafilePaths = @($rPaths.Text -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_.StartsWith('DATAFILE_PATH|') } | ForEach-Object { $_.Substring(14) })

    $psTemplate = @'
$dOut = 'C:\DMPDIR\diag_disc_out.txt'
Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object {
  $pct = 0
  if ($_.Size -gt 0) { $pct = [math]::Round($_.FreeSpace/$_.Size*100,1) }
  "DISC {0} {1} {2} {3}" -f $_.DeviceID, [math]::Round($_.Size/1GB,2), [math]::Round($_.FreeSpace/1GB,2), $pct
} | Out-File -Encoding ascii $dOut
__DATAFILES__
'@
    $fileLines = foreach ($p in $datafilePaths) {
        $escaped = $p.Replace("'", "''")
        'Get-Item ''' + $escaped + ''' -ErrorAction SilentlyContinue | ForEach-Object { "FISIER {0} {1}" -f $_.FullName, $_.Length } | Out-File -Encoding ascii -Append $dOut'
    }
    $psScript = $psTemplate.Replace('__DATAFILES__', ([string]::Join("`n", $fileLines)))
    $psScriptSql = $psScript.Replace("'", "''")

    $rLaunch = Invoke-Sql -Sql @"
set serveroutput on size 1000000
set feedback off
declare
  lcPS server_info.value%type;
begin
  select value into lcPS from server_info where upper(name) = 'POWERSHELLPATH';
  begin pack_utils_file.filedelete('DMPDIR','diag_disc_out.txt'); exception when others then null; end;
  begin pack_utils_file.filedelete('DMPDIR','diag_disc.ps1'); exception when others then null; end;
  pack_utils_file.clob2fileX('$psScriptSql', 'DMPDIR', 'diag_disc.ps1');
  sys.ExecuteScriptOS(lcPS, 'C:\DMPDIR\diag_disc.ps1');
  dbms_output.put_line('Lansat pe server (' || lcPS || '), astept rezultatul...');
exception when others then
  dbms_output.put_line('EROARE la lansare: ' || sqlerrm);
end;
/
exit
"@
    Write-Output $rLaunch.Text

    if ($rLaunch.Text -notmatch 'EROARE la lansare') {
        $gata = Wait-RemoteFile -Directory 'DMPDIR' -FileName 'diag_disc_out.txt' -TimeoutSec 60
        if (-not $gata) {
            Write-Output 'EROARE: rezultatul nu a aparut in 60s. Posibile cauze: server_info.POWERSHELLPATH gresit, politica de executie PowerShell blocheaza scriptul, sau sys.ExecuteScriptOS nu are drept de executie. Verifica manual C:\DMPDIR\diag_disc.ps1 pe server.'
        } else {
            $rRead = Invoke-Sql -Sql @"
set serveroutput on size 1000000
set feedback off
declare
  lf utl_file.file_type;
  lc_line varchar2(32767);
begin
  lf := utl_file.fopen('DMPDIR','diag_disc_out.txt','R',32767);
  begin
    loop
      utl_file.get_line(lf, lc_line, 32767);
      dbms_output.put_line(lc_line);
    end loop;
  exception when no_data_found then null;
  end;
  utl_file.fclose(lf);
  begin pack_utils_file.filedelete('DMPDIR','diag_disc_out.txt'); exception when others then null; end;
  begin pack_utils_file.filedelete('DMPDIR','diag_disc.ps1'); exception when others then null; end;
exception when others then
  dbms_output.put_line('EROARE citire: ' || sqlerrm);
end;
/
exit
"@
            $discLines = @()
            $fileLinesOut = @()
            foreach ($line in ($rRead.Text -split "`r?`n")) {
                if ($line -match '^DISC\s+(\S+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)') {
                    $discLines += ('  disc {0}: total {1} GB, liber {2} GB ({3}%)' -f $Matches[1], $Matches[2], $Matches[3], $Matches[4])
                } elseif ($line -match '^FISIER\s+(\S+)\s+(\d+)') {
                    $mb = [math]::Round(([double]$Matches[2]) / 1048576, 1)
                    $fileLinesOut += ('  {0}: {1} MB pe disc' -f $Matches[1], $mb)
                } elseif ($line -match '\S') {
                    $discLines += ('  ' + $line)
                }
            }
            Write-Output 'Discuri fixe:'
            Write-Output ($discLines -join "`n")
            Write-Output 'Dimensiune reala pe disc a datafile-urilor:'
            Write-Output ($fileLinesOut -join "`n")
        }
    }
}

# ---------- 8. Job UPDATEROA_ZILNIC ----------
$r8 = Invoke-Sql -Sql @"
set pagesize 100 linesize 250 trimspool on feedback off
column log_date format a20
column additional_info format a90 word_wrapped
select * from (
  select to_char(log_date,'yyyy-mm-dd hh24:mi:ss') log_date, status, additional_info
    from dba_scheduler_job_run_details
   where job_name = 'UPDATEROA_ZILNIC'
   order by log_date desc
) where rownum <= 10;
exit
"@
Show-Section -Title '8. JOB UPDATEROA_ZILNIC (ultimele 10 rulari)' -Text ('AVERTISMENT: additional_info e frecvent falsa - la orice esec se apeleaza EmailLog, iar daca SMTP-ul e picat ridica ORA-20000 care masca eroarea reala. Cauza adevarata e in UPD_LOG / script_master.log de mai sus.' + "`n`n" + $r8.Text)

# ---------- 9. Verdict ----------
$r9 = Invoke-Sql -Sql @"
set serveroutput on size 1000000
set feedback off
declare
  ln_stare      upd_istoric.stare%type;
  ld_end        upd_istoric.dataora_end%type;
  ld_start      upd_istoric.dataora_start%type;
  lc_stare_text varchar2(50);
  lc_line       varchar2(32767);
  lf            utl_file.file_type;
  lc_errs       varchar2(4000);
  ln_errcnt     pls_integer := 0;
  lb_spatiu     boolean := false;
  lc_tspatiu    varchar2(100);
  lc_match      varchar2(200);
  lc_datafile   varchar2(400);
begin
  select stare, dataora_end, dataora_start into ln_stare, ld_end, ld_start
    from (select stare, dataora_end, dataora_start from upd_istoric order by dataora_start desc)
   where rownum = 1;

  lc_stare_text := case ln_stare
    when 0 then '0-pornire' when 1 then '1-descarcare aplicatii' when 2 then '2-generare scripturi'
    when 3 then '3-aplicare scripturi' when 4 then '4-incheiat cu succes'
    else 'necunoscuta(' || ln_stare || ')' end;

  dbms_output.put_line('Ultima rulare: ' || to_char(ld_start,'yyyy-mm-dd hh24:mi:ss') || '  stare=' || lc_stare_text ||
    case when ld_end is null then '  <<< NEINCHEIATA >>>' else '  incheiata ' || to_char(ld_end,'yyyy-mm-dd hh24:mi:ss') end);

  if ld_end is null and ln_stare = 3 then
    dbms_output.put_line('Rularea a ramas la aplicarea scripturilor (etapa 3, SQL*Plus extern). Cauza reala e in script_master.log, NU in UPD_LOG.');
  elsif ld_end is null then
    dbms_output.put_line('Rularea nu s-a incheiat (stare ' || lc_stare_text || ').');
  else
    dbms_output.put_line('Ultima rulare s-a incheiat normal.');
  end if;

  begin
    lf := utl_file.fopen('DMPDIR', 'script_master.log', 'R', 32767);
    begin
      loop
        utl_file.get_line(lf, lc_line, 32767);
        if instr(lc_line,'ORA-06512') = 0 and (instr(upper(lc_line), 'ORA-') > 0 or instr(lc_line, 'ERROR') > 0) then
          ln_errcnt := ln_errcnt + 1;
          lc_errs := lc_errs || chr(10) || lc_line;
          if regexp_like(lc_line, 'ORA-016[0-9][0-9]|ORA-30036') then
            lb_spatiu := true;
            lc_match := regexp_substr(upper(lc_line), 'TABLESPACE [A-Z0-9_]+', 1, 1);
            if lc_match is not null then lc_tspatiu := ltrim(substr(lc_match, 11)); end if;
          end if;
        end if;
      end loop;
    exception when no_data_found then null;
    end;
    utl_file.fclose(lf);
  exception when others then
    if utl_file.is_open(lf) then utl_file.fclose(lf); end if;
  end;

  if ln_errcnt > 0 then
    dbms_output.put_line('script_master.log contine erori (' || ln_errcnt || '):' || lc_errs);
  else
    dbms_output.put_line('Nu s-a gasit "ORA-"/"ERROR" in script_master.log.');
  end if;

  if lb_spatiu then
    dbms_output.put_line('=== PROBLEMA DE SPATIU, NU DE SQL === tablespace implicat: ' || nvl(lc_tspatiu,'necunoscut'));
    if lc_tspatiu is not null then
      begin
        select file_name into lc_datafile
          from (select file_name from dba_data_files where tablespace_name = lc_tspatiu order by file_name)
         where rownum = 1;
        dbms_output.put_line('Sugestie (NU se executa automat): ALTER DATABASE DATAFILE ''' || lc_datafile ||
          ''' AUTOEXTEND ON NEXT 50M MAXSIZE <valoare mai mare>;');
      exception when no_data_found then null;
      end;
    end if;
    dbms_output.put_line('Pe XE limita de 11GB e pe datele utilizator, nu pe SYSTEM - un maxbytes mic pe SYSTEM (sau alt tablespace de sistem) e o setare de instalare, se poate mari.');
  end if;

  dbms_output.put_line('Vezi sectiunea 4 pentru context complet in log, sectiunea 5 pentru scriptul candidat per schema, sectiunea 6 pentru spatiul pe tablespace/segmente.');
  dbms_output.put_line('Daca rularea a ramas blocata (stare < 4 de peste o ora) si problema de mai sus e reparata, deblocarea (NU se executa automat de acest script):');
  dbms_output.put_line('  exec contafin_oracle.pack_update.IncheiereActualizare;');
end;
/
exit
"@
Show-Section -Title '9. VERDICT' -Text $r9.Text
if ($r9.Text -match 'PROBLEMA DE SPATIU' -and -not $Disc) {
    Write-Output 'Sugestie: reruleaza cu -Disc pentru spatiul liber pe discurile fizice ale serverului (poate lipsi spatiu pe disc pentru crestere, nu doar maxbytes).'
}

Remove-TempDir
exit 0
