<?php
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/nextcloud.php';

function get_local_contracts_root_from_path($nc_path) {
    $raw = trim((string)$nc_path);
    if ($raw === '') {
        return '';
    }
    if (strpos($raw, '/') === 0 && !preg_match('/^[A-Za-z]:\//', $raw)) {
        return '';
    }
    if (strpos($raw, '/') !== false && strpos($raw, '\\') === false && !preg_match('/^[A-Za-z]:/', $raw)) {
        return '';
    }
    if (strcasecmp($raw, 'CONTRATOS') === 0) {
        $fallback = trim((string)NC_CONTRACTS_PATH_DEFAULT);
        if ($fallback !== '' && strcasecmp($fallback, 'CONTRATOS') !== 0) {
            return get_local_contracts_root_from_path($fallback);
        }
        return '';
    }

    $raw = str_replace('/', '\\', $raw);
    if (strpos($raw, '\\') === 0 && strpos($raw, '\\\\') !== 0) {
        $userProfile = (string)(getenv('USERPROFILE') ?: '');
        $systemDrive = (string)(getenv('SystemDrive') ?: 'C:');
        $systemDrive = rtrim($systemDrive, "\\/"); 
        $userName = $userProfile !== '' ? basename(str_replace('\\', '/', $userProfile)) : '';
        $withoutLead = ltrim($raw, "\\/");

        if (stripos($withoutLead, 'Users\\') === 0) {
            $raw = $systemDrive . '\\' . $withoutLead;
        } elseif ($userName !== '' && stripos($withoutLead, $userName . '\\') === 0) {
            $raw = $systemDrive . '\\Users\\' . $withoutLead;
        }
    }

    $normalized = preg_replace('#[\\/]+#', DIRECTORY_SEPARATOR, $raw);
    if (!is_string($normalized) || $normalized === '') {
        $normalized = $raw;
    }

    $parts = preg_split('#[\\\\/]+#', $normalized);
    if (!is_array($parts) || empty($parts)) {
        return '';
    }

    $rebuilt = [];
    foreach ($parts as $index => $part) {
        if ($part === '' && $index !== 0) {
            continue;
        }
        $rebuilt[] = $part;
        if (strcasecmp($part, 'CONTRATOS') === 0) {
            break;
        }
    }

    $joined = implode(DIRECTORY_SEPARATOR, $rebuilt);
    if (preg_match('/^[A-Za-z]:$/', $joined)) {
        $joined .= DIRECTORY_SEPARATOR;
    }

    return rtrim($joined, "\\/");
}

function scan_local_contracts_pdfs($contractsRoot, $remoteRoot = 'CONTRATOS', $maxFiles = 5000) {
    $contractsRoot = rtrim((string)$contractsRoot, "\\/");
    $remoteRoot = trim(str_replace('\\', '/', (string)$remoteRoot), '/');
    if ($remoteRoot === '') {
        $remoteRoot = 'CONTRATOS';
    }
    if ($contractsRoot === '' || !is_dir($contractsRoot)) {
        return [];
    }

    $results = [];
    $filesCount = 0;

    try {
        $dirIterator = new RecursiveDirectoryIterator($contractsRoot, FilesystemIterator::SKIP_DOTS);
        $iterator = new RecursiveIteratorIterator($dirIterator);
        foreach ($iterator as $fileInfo) {
            if (!$fileInfo instanceof SplFileInfo) {
                continue;
            }
            if (!$fileInfo->isFile()) {
                continue;
            }
            $basename = $fileInfo->getBasename();
            if ($basename === '' || strpos($basename, '.') === 0 || strpos($basename, '~') === 0 || strpos($basename, '_') === 0) {
                continue;
            }
            if (strtolower($fileInfo->getExtension()) !== 'pdf') {
                continue;
            }

            $fullPath = $fileInfo->getPathname();
            $relative = substr($fullPath, strlen($contractsRoot));
            $relative = ltrim(str_replace('\\', '/', (string)$relative), '/');
            $remotePath = $relative !== '' ? ($remoteRoot . '/' . $relative) : ($remoteRoot . '/' . $basename);
            $unitFolder = basename(dirname($remotePath));

            $results[] = [
                'name' => $basename,
                'remote_path' => $remotePath,
                'href' => $fullPath,
                'size' => (int)$fileInfo->getSize(),
                'mtime' => (int)$fileInfo->getMTime(),
                'unit_folder' => $unitFolder,
                'source' => 'local',
            ];

            $filesCount++;
            if ($filesCount >= $maxFiles) {
                break;
            }
        }
    } catch (Throwable $e) {
        return [];
    }

    return $results;
}

/**
 * Resolve a pasta remota raiz do Nextcloud para a listagem de contratos.
 */
function get_nextcloud_remote_root($nc_path) {
    $normalizedPath = trim(str_replace('\\', '/', (string)$nc_path));
    $normalizedPath = trim($normalizedPath, '/');

    if ($normalizedPath === '') {
        return 'CONTRATOS';
    }

    $isAbsolutePath = preg_match('/^[A-Za-z]:\//', $normalizedPath) || strpos($normalizedPath, '//') === 0 || strpos($normalizedPath, '/') === 0;
    if ($isAbsolutePath) {
        return defined('NC_REMOTE_ROOT_DEFAULT') ? (string)NC_REMOTE_ROOT_DEFAULT : 'CONTRATOS';
    }

    return $normalizedPath;
}

/**
 * Busca arquivos no Nextcloud remoto via WebDAV que não estão vinculados a nenhum contrato no sistema
 */
function get_orphaned_nextcloud_files($force_refresh = false, &$debug = null) {
    $pdo = get_db_connection();
    
    // Buscar caminho configurado no banco ou usar o padrão
    $stmtPath = $pdo->prepare("SELECT setting_value FROM system_settings WHERE setting_key = 'nc_path'");
    $stmtPath->execute();
    $nc_path = $stmtPath->fetchColumn() ?: NC_CONTRACTS_PATH_DEFAULT;

    $orphaned_files = [];

    // --- LÓGICA DE CACHE PARA NEXTCLOUD REMOTO ---
    $cache_time = 600; // Aumentado para 10 minutos para não forçar o servidor
    $remoteFiles = null;
    $remoteRoot = get_nextcloud_remote_root($nc_path);
    $localRoot = get_local_contracts_root_from_path($nc_path);
    $remoteRootCandidates = [];
    try {
        if ($remoteRoot === 'CONTRATOS') {
            $ncProbe = new Nextcloud();
            $candidates = ['CONTRATOS', 'CSC/CONTRATOS', 'CONTRATOS (2)'];
            foreach ($candidates as $candidate) {
                $info = $ncProbe->listImmediateEntries($candidate);
                $remoteRootCandidates[] = [
                    'candidate' => $candidate,
                    'http_code' => $info['http_code'] ?? null,
                    'entry_count' => isset($info['entries']) && is_array($info['entries']) ? count($info['entries']) : 0,
                ];
                if (($info['http_code'] ?? 0) === 207 && !empty($info['entries'])) {
                    $remoteRoot = $candidate;
                    break;
                }
            }
        }
    } catch (Throwable $e) {
        $remoteRootCandidates[] = [
            'candidate' => 'CSC/CONTRATOS',
            'http_code' => null,
            'entry_count' => null,
            'error' => $e->getMessage(),
        ];
    }
    $cache_key = 'nc_files_cache_' . substr(sha1(strtolower($remoteRoot)), 0, 12) . '.json';
    $cache_file = __DIR__ . '/../backups/' . $cache_key;
    $debug = [
        'nc_path_setting' => (string)$nc_path,
        'remote_root' => $remoteRoot,
        'remote_root_candidates' => $remoteRootCandidates,
        'remote_total' => 0,
        'remote_samples' => [],
        'db_samples' => [],
        'local_root' => $localRoot,
        'local_total' => 0,
        'local_samples' => [],
        'root_directories' => [],
        'remote_root_entries' => [],
        'remote_root_http_code' => null,
        'webdav_user' => null,
        'remote_tree_entries' => [],
        'extension_counts' => [],
        'webdav_attempts' => [],
        'cache_file' => basename($cache_file),
        'cache_used' => false,
        'cache_age_seconds' => null,
    ];

    if ($force_refresh && file_exists($cache_file)) {
        @unlink($cache_file);
    }

    if (!$force_refresh && file_exists($cache_file) && (time() - filemtime($cache_file) < $cache_time)) {
        $debug['cache_age_seconds'] = time() - filemtime($cache_file);
        $cacheData = json_decode(file_get_contents($cache_file), true);
        if (isset($cacheData['files']) && is_array($cacheData['files'])) {
            $remoteFiles = $cacheData['files'];
        } else {
            $remoteFiles = $cacheData;
        }

        if (!is_array($remoteFiles)) {
            $remoteFiles = null;
        } else {
            if (empty($remoteFiles)) {
                $remoteFiles = null;
            } else {
                $debug['cache_used'] = true;
            }
        }
    }

    $localFiles = [];
    if ($localRoot !== '' && is_dir($localRoot)) {
        $localFiles = scan_local_contracts_pdfs($localRoot, $remoteRoot, 7000);
        $debug['local_total'] = count($localFiles);
        $debug['local_samples'] = array_slice(array_map(function($lf) {
            return $lf['remote_path'] ?? ($lf['href'] ?? '');
        }, $localFiles), 0, 8);
    }

    // --- ESCANEAR NEXTCLOUD REMOTO (WebDAV) ---
    if ($remoteFiles === null) {
        try {
            $nc = new Nextcloud();
            $resolvedRootInfo = $nc->listImmediateEntries($remoteRoot);
            $resolvedRemoteRoot = trim((string)($resolvedRootInfo['path'] ?? $remoteRoot), '/');
            $debug['remote_root_resolved'] = $resolvedRemoteRoot;
            if ($resolvedRemoteRoot !== '' && $resolvedRemoteRoot !== $remoteRoot) {
                $remoteRoot = $resolvedRemoteRoot;
                $debug['remote_root'] = $remoteRoot;
            }

            $probeCandidates = [];
            $probeCandidates[] = $remoteRoot;
            $probeCandidates[] = 'CONTRATOS';
            $probeCandidates[] = 'CONTRATOS (2)';
            $probeCandidates[] = 'CSC/CONTRATOS';
            foreach ($nc->listRootDirectories() as $dir) {
                $candidatePath = trim((string)($dir['relative_path'] ?? ''), '/');
                $candidateName = (string)($dir['name'] ?? '');
                $haystack = $candidateName !== '' ? $candidateName : $candidatePath;
                if ($candidatePath !== '' && stripos($haystack, 'CONTRATOS') !== false) {
                    $probeCandidates[] = $candidatePath;
                }
            }
            $probeCandidates = array_values(array_unique(array_filter(array_map(function($c) {
                return trim((string)$c, '/');
            }, $probeCandidates), 'strlen')));

            $probeResults = [];
            $bestCandidate = $remoteRoot;
            $bestCount = -1;
            foreach ($probeCandidates as $candidate) {
                try {
                    $probeFiles = $nc->listFiles($candidate, true, 25, 150);
                    $count = is_array($probeFiles) ? count($probeFiles) : 0;
                    $probeResults[] = [
                        'candidate' => $candidate,
                        'file_count' => $count,
                    ];
                    if ($count > $bestCount) {
                        $bestCount = $count;
                        $bestCandidate = $candidate;
                    }
                } catch (Throwable $e) {
                    $probeResults[] = [
                        'candidate' => $candidate,
                        'file_count' => null,
                        'error' => $e->getMessage(),
                    ];
                }
            }
            $debug['remote_root_probe_results'] = array_slice($probeResults, 0, 25);

            if ($bestCount > 0 && $bestCandidate !== '' && $bestCandidate !== $remoteRoot) {
                $remoteRoot = $bestCandidate;
                $debug['remote_root'] = $remoteRoot;
            }

            $remoteFiles = $nc->listFiles($remoteRoot, true, 50000, 20000);
            $debug['webdav_user'] = $nc->getActiveWebdavUser();
            $debug['webdav_attempts'] = array_slice($nc->getPropfindAttempts(), 0, 20);
            if (!empty($remoteFiles)) {
                $extensionCounts = [];
                foreach ($remoteFiles as $remoteFile) {
                    $ext = strtolower(pathinfo((string)($remoteFile['name'] ?? ''), PATHINFO_EXTENSION));
                    $ext = $ext !== '' ? $ext : '[sem_extensao]';
                    $extensionCounts[$ext] = ($extensionCounts[$ext] ?? 0) + 1;
                }
                arsort($extensionCounts);
                $debug['extension_counts'] = array_slice($extensionCounts, 0, 15, true);
            }
            if (empty($remoteFiles)) {
                $debug['root_directories'] = array_slice($nc->listRootDirectories(), 0, 10);
                $rootEntriesInfo = $nc->listImmediateEntries($remoteRoot);
                $debug['remote_root_http_code'] = $rootEntriesInfo['http_code'] ?? null;
                $debug['webdav_user'] = $rootEntriesInfo['webdav_user'] ?? $debug['webdav_user'];
                $debug['webdav_attempts'] = array_slice($nc->getPropfindAttempts(), 0, 20);
                $debug['remote_root_entries'] = array_slice($rootEntriesInfo['entries'] ?? [], 0, 15);
                $visitedEntries = [];
                $debug['remote_tree_entries'] = array_slice($nc->listEntriesRecursive($remoteRoot, 50, $visitedEntries), 0, 50);
                $debug['webdav_attempts'] = array_slice($nc->getPropfindAttempts(), 0, 20);
            }

            // Salvar no cache
            if (!is_dir(dirname($cache_file))) @mkdir(dirname($cache_file), 0777, true);
            file_put_contents($cache_file, json_encode([
                'remote_root' => $remoteRoot,
                'generated_at' => date('c'),
                'files' => $remoteFiles
            ]));
        } catch (Exception $e) {
            $fallbackFromCache = false;
            if (!$force_refresh && file_exists($cache_file)) {
                $cacheData = json_decode(file_get_contents($cache_file), true);
                if (isset($cacheData['files']) && is_array($cacheData['files'])) {
                    $remoteFiles = $cacheData['files'];
                } else {
                    $remoteFiles = $cacheData;
                }

                if (is_array($remoteFiles) && !empty($remoteFiles)) {
                    $fallbackFromCache = true;
                    $debug['cache_used'] = true;
                    $debug['cache_age_seconds'] = time() - filemtime($cache_file);
                }
            }

            if (!$fallbackFromCache) {
                throw new Exception('Nao foi possivel atualizar a lista do servidor: ' . $e->getMessage());
            }
        }
    }

    // 1. Obter todos os caminhos de arquivos registrados no banco (contratos e histórico)
    $stmt1 = $pdo->query("SELECT DISTINCT file_path FROM contracts WHERE file_path IS NOT NULL AND file_path != ''");
    $db_files = $stmt1->fetchAll(PDO::FETCH_COLUMN);

    $stmt2 = $pdo->query("SELECT DISTINCT file_path FROM contract_files WHERE file_path IS NOT NULL AND file_path != ''");
    $history_files = $stmt2->fetchAll(PDO::FETCH_COLUMN);

    $all_db_files = array_unique(array_merge($db_files, $history_files));
    $db_remote_paths = [];
    $db_legacy_basenames = [];

    foreach ($all_db_files as $file_path) {
        $normalized = strtolower(trim(str_replace('\\', '/', (string)$file_path)));
        if ($normalized === '') {
            continue;
        }

        if (strpos($normalized, '/') !== false) {
            $db_remote_paths[$normalized] = true;
        } else {
            $db_legacy_basenames[basename($normalized)] = true;
        }
    }

    $debug['db_samples'] = array_slice(array_values(array_unique($all_db_files)), 0, 5);

    if (is_array($remoteFiles)) {
        $debug['remote_total'] = count($remoteFiles);
        $debug['remote_samples'] = array_slice(array_map(function($rf) {
            return $rf['remote_path'] ?? ($rf['href'] ?? '');
        }, $remoteFiles), 0, 8);
    }

    $scanFiles = [];
    if (!empty($localFiles)) {
        $scanFiles = $localFiles;
    }
    if (is_array($remoteFiles) && !empty($remoteFiles)) {
        foreach ($remoteFiles as $rf) {
            if (!is_array($rf)) {
                continue;
            }
            $rf['source'] = $rf['source'] ?? 'remote';
            $scanFiles[] = $rf;
        }
    }

    if (!empty($scanFiles)) {
        foreach ($scanFiles as $rf) {
            $filename = $rf['name'];
            
            // Ignorar arquivos ocultos ou temporários no remoto também
            if (strpos($filename, '.') === 0 || strpos($filename, '~') === 0 || strpos($filename, '_') === 0) continue;
            
            $clean_filename = strtolower(trim($filename));
            $normalized_remote_path = strtolower(trim(str_replace('\\', '/', (string)($rf['remote_path'] ?? ''))));
            
            $is_linked = false;
            if ($normalized_remote_path !== '' && isset($db_remote_paths[$normalized_remote_path])) {
                $is_linked = true;
            } elseif (($normalized_remote_path === '' || strpos($normalized_remote_path, '/') === false) && isset($db_legacy_basenames[$clean_filename])) {
                $is_linked = true;
            }

            if (!$is_linked && !isset($orphaned_files[$normalized_remote_path ?: $clean_filename])) {
                $orphaned_key = $normalized_remote_path ?: $clean_filename;
                $unit_folder = trim((string)($rf['unit_folder'] ?? ''));
                if ($unit_folder === '' && $normalized_remote_path !== '' && strpos($normalized_remote_path, '/') !== false) {
                    $parts = explode('/', $normalized_remote_path);
                    if (count($parts) >= 2) {
                        $unit_folder = $parts[count($parts) - 2];
                    }
                }

                $orphaned_files[$orphaned_key] = [
                    'name' => $filename,
                    'path' => $rf['remote_path'],
                    'full_path' => $rf['href'],
                    'unit_folder' => $unit_folder,
                    'size' => $rf['size'],
                    'mtime' => $rf['mtime'],
                    'source' => $rf['source'] ?? 'remote'
                ];
            }
        }
    }

    return array_values($orphaned_files);
}
