<?php

if (!function_exists('enrep_log_context_value')) {
    function enrep_log_context_value(array $source, array $keys): ?string
    {
        foreach ($keys as $key) {
            if (isset($source[$key]) && !is_array($source[$key]) && trim((string)$source[$key]) !== '') {
                return trim((string)$source[$key]);
            }
        }

        return null;
    }
}

if (!function_exists('enrep_log_context_int')) {
    function enrep_log_context_int(array $source, array $keys): ?int
    {
        $value = enrep_log_context_value($source, $keys);
        if ($value === null || !is_numeric($value)) {
            return null;
        }

        return (int)$value;
    }
}

if (!function_exists('enrep_log')) {
    function enrep_log(string $category, string $action, string $message, array $context = []): void
    {
        if (empty($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
            return;
        }

        $category = substr(trim($category), 0, 80);
        $action = substr(trim($action), 0, 80);
        $message = trim($message);

        if ($category === '' || $action === '' || $message === '') {
            return;
        }

        $request = $_REQUEST ?? [];
        $actorType = substr((string)($_SESSION['usertype'] ?? ''), 0, 45);
        $actorId = (int)($_SESSION['userid'] ?? 0);
        $actorName = substr((string)($_SESSION['user'] ?? ''), 0, 150);
        $entityType = substr((string)($context['entity_type'] ?? $category), 0, 80);
        $entityId = substr((string)($context['entity_id'] ?? enrep_log_context_value($request, ['id', 'repnumber', 'wsnumber', 'lwsnumber', 'clientnumber', 'locnumber', 'itemnumber']) ?? ''), 0, 80);
        $clientnumber = isset($context['clientnumber']) ? (int)$context['clientnumber'] : enrep_log_context_int($request, ['clientnumber', 'client', 'company']);
        $locnumber = isset($context['locnumber']) ? (int)$context['locnumber'] : enrep_log_context_int($request, ['locnumber', 'location', 'site']);
        $itemnumber = isset($context['itemnumber']) ? (int)$context['itemnumber'] : enrep_log_context_int($request, ['itemnumber', 'item']);
        $subject = substr((string)($context['subject'] ?? enrep_log_context_value($request, ['subject', 'title', 'name']) ?? ''), 0, 255);
        $createdAt = time();
        $ipAddress = substr((string)($_SERVER['REMOTE_ADDR'] ?? ''), 0, 45);
        $userAgent = substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 255);

        unset($context['entity_type'], $context['entity_id'], $context['clientnumber'], $context['locnumber'], $context['itemnumber'], $context['subject']);
        $contextJson = json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        if ($contextJson === false) {
            $contextJson = '{}';
        }

        $stmt = $GLOBALS['con']->prepare(
            "INSERT INTO `log` (`category`,`action`,`actor_type`,`actor_id`,`actor_name`,`entity_type`,`entity_id`,`clientnumber`,`locnumber`,`itemnumber`,`subject`,`message`,`context_json`,`ip_address`,`user_agent`,`created_at`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
        );

        if (!$stmt) {
            return;
        }

        $stmt->bind_param(
            'sssisssiiisssssi',
            $category,
            $action,
            $actorType,
            $actorId,
            $actorName,
            $entityType,
            $entityId,
            $clientnumber,
            $locnumber,
            $itemnumber,
            $subject,
            $message,
            $contextJson,
            $ipAddress,
            $userAgent,
            $createdAt
        );
        $stmt->execute();
        $stmt->close();
    }
}

if (!function_exists('enrep_log_email')) {
    function enrep_log_email(string $action, string $subject, array $recipients, array $attachments = [], string $message = '', array $context = []): void
    {
        $recipients = array_values(array_unique(array_filter(array_map('strval', $recipients))));
        $normalisedAttachments = [];
        foreach ($attachments as $attachment) {
            if (is_array($attachment)) {
                $file = trim((string)($attachment['file'] ?? $attachment['filename'] ?? ''));
                if ($file === '') {
                    continue;
                }

                $source = trim((string)($attachment['source'] ?? ''));
                $normalisedAttachments[] = [
                    'file' => $file,
                    'source' => $source,
                    'path' => trim((string)($attachment['path'] ?? trim($source . '/' . $file, '/'))),
                    'type' => trim((string)($attachment['type'] ?? pathinfo($file, PATHINFO_EXTENSION))),
                    'label' => trim((string)($attachment['label'] ?? $file)),
                    'reportnumber' => isset($attachment['reportnumber']) ? (int)$attachment['reportnumber'] : null,
                    'itemnumber' => isset($attachment['itemnumber']) ? (int)$attachment['itemnumber'] : null,
                    'form' => isset($attachment['form']) ? (int)$attachment['form'] : null,
                    'surveyor' => isset($attachment['surveyor']) ? (int)$attachment['surveyor'] : null,
                    'contents' => is_array($attachment['contents'] ?? null) ? $attachment['contents'] : [],
                ];
                continue;
            }

            $file = trim((string)$attachment);
            if ($file !== '') {
                $normalisedAttachments[] = [
                    'file' => $file,
                    'source' => '',
                    'path' => $file,
                    'type' => pathinfo($file, PATHINFO_EXTENSION),
                    'label' => $file,
                    'reportnumber' => null,
                    'itemnumber' => null,
                    'form' => null,
                    'surveyor' => null,
                    'contents' => [],
                ];
            }
        }

        $summary = $message !== '' ? $message : 'Email ' . $action . ' to ' . implode(', ', $recipients);
        if ($subject !== '') {
            $summary .= ' with subject "' . $subject . '"';
        }
        if (!empty($normalisedAttachments)) {
            $summary .= ' and ' . count($normalisedAttachments) . ' attachment(s)';
        }

        $context['subject'] = $subject;
        $context['recipients'] = $recipients;
        $context['attachments'] = $normalisedAttachments;

        enrep_log('email', $action, $summary, $context);
    }
}

if (!function_exists('enrep_log_request_completion')) {
    function enrep_log_request_completion(string $category, string $requestKey, array $actions): void
    {
        $request = $_REQUEST ?? [];
        $action = isset($request[$requestKey]) && !is_array($request[$requestKey]) ? (string)$request[$requestKey] : '';
        if ($action === '' || !isset($actions[$action])) {
            return;
        }

        register_shutdown_function(function () use ($category, $action, $actions, $request) {
            if (function_exists('http_response_code') && http_response_code() >= 400) {
                return;
            }

            $details = $actions[$action];
            $logAction = is_array($details) ? (string)($details['action'] ?? $action) : $action;
            $message = is_array($details) ? (string)($details['message'] ?? '') : (string)$details;
            if ($message === '') {
                $message = ucfirst(str_replace(['_', '-'], ' ', $logAction)) . ' in ' . $category;
            }

            $context = [
                'request_action' => $action,
                'entity_type' => is_array($details) ? (string)($details['entity_type'] ?? $category) : $category,
                'entity_id' => enrep_log_context_value($request, ['id', 'repnumber', 'wsnumber', 'lwsnumber', 'clientnumber', 'locnumber', 'itemnumber']),
                'clientnumber' => enrep_log_context_int($request, ['clientnumber', 'client', 'company']),
                'locnumber' => enrep_log_context_int($request, ['locnumber', 'location', 'site']),
                'itemnumber' => enrep_log_context_int($request, ['itemnumber', 'item']),
                'subject' => enrep_log_context_value($request, ['subject', 'title', 'name', 'desc']),
            ];

            enrep_log($category, $logAction, $message, $context);
        });
    }
}
