<?php
header('Access-Control-Allow-Origin: *');
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL);

include_once __DIR__ . '/dompdf/autoload.inc.php';
set_time_limit(300);

define('TEMP_IMG', __DIR__ . '/img/');
define('PRES_DIR', __DIR__ . '/presentation/');
define('PRES_URL', 'https://spa-bitrix.ru/private-broker/main/create_presentation/presentation/');
define('LOGO_DARK',  __DIR__ . '/img/PB LOGO RUS V2 light black 1.png');
define('LOGO_LIGHT', __DIR__ . '/img/PB LOGO RUS V2 dark 1.png');

writeToLog([
    'php'            => PHP_VERSION,
    'cards'          => isset($_POST['cards']) ? count($_POST['cards']) : '? (json body)',
    'TEMP_IMG_ok'    => is_dir(TEMP_IMG) && is_writable(TEMP_IMG)  ? 'yes' : 'NO',
    'PRES_DIR_ok'    => is_dir(PRES_DIR) && is_writable(PRES_DIR)  ? 'yes' : 'NO',
    'LOGO_DARK_ok'   => file_exists(LOGO_DARK)  ? 'yes' : 'NO',
    'LOGO_LIGHT_ok'  => file_exists(LOGO_LIGHT) ? 'yes' : 'NO',
], 'INIT');


$logo_dark  = file_exists(LOGO_DARK)  ? 'file://' . LOGO_DARK  : '';
$logo_light = file_exists(LOGO_LIGHT) ? 'file://' . LOGO_LIGHT : '';

$f_html      = '';
$last_name   = 'presentation';
$last_square = '0';
$tmp_files   = [];

// Маппинг typeObj (ID раздела Bitrix24) → тип презентации
$type_obj_map = [
    '3108' => 'city',       // Городская недвижимость / Новостройки
    '3110' => 'pb',         // Элитная (основной тип)
    '3112' => 'pb',         // Элитная (доп.)
    '3114' => 'country',    // Загородная
    '3116' => 'commercial', // Коммерция
];

$input = $_POST;
if (empty($input['cards'])) {
    $raw = file_get_contents('php://input');
    if (!empty($raw)) {
        $decoded = json_decode($raw, true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
            $input = $decoded;
        } else {
            writeToLog('json_decode failed: ' . json_last_error_msg(), 'INPUT:ERROR');
        }
    }
}

if (empty($input['cards'])) {
    writeToLog('cards пуст', 'INIT:ERROR');
    echo '';
    exit;
}

foreach ($input['cards'] as $i => $card) {

    writeToLog(['index' => $i, 'title' => $card['title'] ?? ''], "CARD:$i");

    // ── Тип презентации ──────────────────────────────────────────────────────
    $type_obj  = trim($card['typeObj'] ?? '');
    $type      = trim($card['type']    ?? '') ?: ($type_obj_map[$type_obj] ?? 'pb');

    writeToLog(['typeObj' => $type_obj, 'type' => $type], "CARD:$i:TYPE");

    // ── Общие поля ────────────────────────────────────────────────────────────
    $name         = trim($card['title']          ?? '');
    $address_raw  = trim($card['address']        ?? '');
    // Адрес может содержать координаты: "Адрес|lat;lon" — берём только адрес
    $address      = trim(explode('|', $address_raw)[0]);
    $district     = trim($card['district']       ?? ($card['saleTitle'] ?? ''));
    $metro        = trim($card['metro']          ?? '');
    $obj_id       = trim($card['id']             ?? '');
    $pres_type    = trim($card['presType']       ?? 'enable');
    $exclusive    = ($pres_type === 'enable');
    $is_logo      = ($pres_type !== 'disable');
    $price_raw    = intval(preg_replace('/[^0-9]+/', '', $card['fullPrice'] ?? '0'));
    $square       = trim($card['square']         ?? '');
    $rooms        = trim($card['rooms']          ?? '');
    $bedroom      = trim($card['bedroom']        ?? '');
    $bathrooms    = trim($card['bathrooms']      ?? ($card['wc'] ?? ''));
    $floor        = trim($card['floor']          ?? '');
    $total_floors = trim($card['totalFloors']    ?? '');
    $finish       = trim($card['otc']            ?? '');
    $ceiling      = trim($card['heightCeiling']  ?? '');
    $land_sq_raw  = trim($card['landArea']       ?? '');
    $land_sq      = (strtolower($land_sq_raw) === 'null' || $land_sq_raw === '') ? '' : $land_sq_raw;
    $prop_type    = trim($card['propertyType']   ?? ($card['typeAparts'] ?? ($card['detailsResidense'] ?? '')));
    $land_type    = trim($card['landType']       ?? '');
    $type_deal    = trim($card['typeDeal']       ?? 'Продажа');
    $currency_arr = $card['currencyArr']         ?? ', ₽';

    // ── Коммерческие поля ────────────────────────────────────────────────────
    $parking     = trim($card['parking']      ?? '');
    $entrance    = trim($card['entrance']     ?? '');
    $bld_type    = trim($card['buildType']    ?? ($card['typeHouse'] ?? ''));
    $layout      = trim($card['layout']       ?? '');
    $electricity = trim($card['electricity']  ?? '');
    $water       = trim($card['water']        ?? '');
    $heating     = trim($card['heating']      ?? '');
    $security    = trim($card['security']     ?? '');
    $entrances   = trim($card['entrances']    ?? '');
    $usage       = trim($card['usage']        ?? '');

    writeToLog([
        'type'       => $type,
        'name'       => $name,
        'address'    => $address,
        'pres_type'  => $pres_type,
        'price_raw'  => $price_raw,
        'square'     => $square,
        'bedroom'    => $bedroom,
        'bathrooms'  => $bathrooms,
        'land_sq'    => $land_sq,
        'prop_type'  => $prop_type,
        'floor'      => $floor,
        'ceiling'    => $ceiling,
    ], "CARD:$i:FIELDS");

    $mp_raw = $card['mainPhoto'] ?? $card['mainphoto'] ?? '';
    if (is_string($mp_raw)) {
        $decoded = json_decode($mp_raw, true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) $mp_raw = $decoded;
    }
    $cover_url = parse_image_url(is_array($mp_raw) ? ($mp_raw['url'] ?? '') : $mp_raw);

    $lay_raw = $card['layouts'] ?? '';
    if (is_string($lay_raw)) {
        $decoded = json_decode($lay_raw, true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) $lay_raw = $decoded;
    }
    if (is_array($lay_raw) && isset($lay_raw[0])) $lay_raw = $lay_raw[0];
    $map_url = parse_image_url(is_array($lay_raw) ? ($lay_raw['url'] ?? '') : $lay_raw);

    // ── Остальные фото (urlImages) — идут последовательно в слайдах ──────────
    // Каждый элемент может быть: строкой URL или объектом { id, url, ... }
    $extra_urls = [];
    $raw_images = $card['urlImages'] ?? [];
    if (is_array($raw_images)) {
        foreach ($raw_images as $u) {
            $u = is_array($u) ? ($u['url'] ?? '') : $u;
            $u = parse_image_url($u);
            if ($u) $extra_urls[] = $u;
        }
    } else {
        foreach (explode(',;,', (string)$raw_images) as $u) {
            $u = parse_image_url($u);
            if ($u) $extra_urls[] = $u;
        }
    }

    writeToLog([
        'mainphoto'  => $cover_url,
        'layouts'    => $map_url,
        'urlImages'  => $extra_urls,
    ], "CARD:$i:PHOTOS");

    // ── Описание ──────────────────────────────────────────────────────────────
    $text_raw = $card['details'] ?? '';
    // Убираем HTML-теги, декодируем сущности (&nbsp; и др.), нормализуем пробелы
    $text_raw = strip_tags($text_raw);
    $text_raw = html_entity_decode($text_raw, ENT_QUOTES | ENT_HTML5, 'UTF-8');
    $text_raw = str_replace("\xc2\xa0", ' ', $text_raw);          // остаточные nbsp
    $text_raw = preg_replace('/[ \t]+/', ' ', $text_raw);          // множ. пробелы
    $text_raw = preg_replace('/\n{3,}/', "\n\n", $text_raw);       // пустые строки
    $text_raw = trim($text_raw);

    // Авто-размер шрифта по кол-ву символов:
    // Блок текста: ~376px шир. × ~691px выс. при line-height 1.8
    $char_count = mb_strlen($text_raw);
    if      ($char_count <= 500)  $desc_font = '13px';
    elseif  ($char_count <= 900)  $desc_font = '12px';
    elseif  ($char_count <= 1400) $desc_font = '11px';
    elseif  ($char_count <= 2000) $desc_font = '10px';
    else                          $desc_font = '9px';

    // Жёсткий потолок — обрезаем по последней точке
    if ($char_count > 2800) {
        $text_raw = mb_substr($text_raw, 0, 2800);
        $p = mb_strrpos($text_raw, '.');
        if ($p !== false) $text_raw = mb_substr($text_raw, 0, $p + 1);
    }
    $text = nl2br(htmlspecialchars($text_raw, ENT_QUOTES, 'UTF-8'));

    // ── Цена ──────────────────────────────────────────────────────────────────
    $arr      = explode(',', $currency_arr);
    $cur      = ltrim($arr[1] ?? '₽');
    $sq_num   = (float) str_replace([',', ' '], ['.', ''], $square);
    $price_m2 = ($sq_num > 0 && $price_raw > 0) ? round($price_raw / $sq_num) : 0;

    writeToLog([
        'price_raw' => $price_raw,
        'cur'       => $cur,
        'sq_num'    => $sq_num,
        'price_m2'  => $price_m2,
    ], "CARD:$i:CALC");

    // ── Скачиваем фото ────────────────────────────────────────────────────────
    $img_cover = download_single($cover_url, $name . '_' . $i . '_cover', $tmp_files);
    $map_local = download_single($map_url,   $name . '_' . $i . '_map',   $tmp_files);
    $extra     = download_photos($extra_urls, $name, $i, $tmp_files);

    writeToLog([
        'cover'      => $img_cover ? 'OK' : 'FAIL',
        'map'        => $map_local ? 'OK' : 'SKIP',
        'extra'      => count($extra) . '/' . count($extra_urls),
    ], "CARD:$i:DL");

    // Загруженные файлы
    if (!empty($_FILES['files']['tmp_name'][$i])) {
        foreach ($_FILES['files']['tmp_name'][$i] as $k => $tmp) {
            if (empty($tmp)) continue;
            $fname = safe_fname($_FILES['files']['name'][$i][$k]);
            $dest  = TEMP_IMG . $fname;
            if (move_uploaded_file($tmp, $dest)) {
                $extra[]     = 'file://' . $dest;
                $tmp_files[] = $dest;
                writeToLog('OK: ' . $fname, "CARD:$i:UPLOAD");
            } else {
                writeToLog('FAIL: ' . $fname, "CARD:$i:UPLOAD:ERROR");
            }
        }
    }

    // ── Логотип ───────────────────────────────────────────────────────────────
    $ld = $is_logo ? $logo_dark  : '';
    $ll = $is_logo ? $logo_light : '';

    writeToLog(['type' => $type, 'pres_type' => $pres_type], "CARD:$i:SLIDES");

    if ($pres_type === 'photo') {
        // Режим «только фото»
        $all_photos = array_filter(array_merge(
            [$img_cover],
            $map_local ? [$map_local] : [],
            $extra
        ));
        $slides = '';
        foreach ($all_photos as $photo) {
            $slides .= slide_extra($photo, '');
        }
        writeToLog('photo mode: ' . count($all_photos) . ' slides', "CARD:$i:SLIDES");

    } else {
        // ── Обложка ───────────────────────────────────────────────────────────
        $slides = slide_cover($img_cover, $name, $address, $obj_id, $exclusive, $ll);
        writeToLog('slide #1: cover', "CARD:$i:SLIDES");

        // ── Планировка (слайд 2) ──────────────────────────────────────────────
        if (!empty($map_local)) {
            $slides .= slide_plan($map_local, $ld);
            writeToLog('slide #2: plan', "CARD:$i:SLIDES");
        } else {
            writeToLog('slide #2: plan SKIP (layouts пуст)', "CARD:$i:SLIDES");
        }

        // ── Характеристики (слайд 3) — тип-специфичный ───────────────────────
        switch ($type) {
            case 'city':
                $slides .= slide_city_info(
                    $name, $address, $district, $metro,
                    $square, $rooms, $bedroom, $bathrooms,
                    $floor, $total_floors, $finish, $ceiling,
                    $prop_type,
                    $price_raw, $price_m2, $cur, $type_deal,
                    $extra[0] ?? $img_cover, $ld
                );
                writeToLog('slide #3: city_info', "CARD:$i:SLIDES");
                break;

            case 'country':
                $slides .= slide_country_info(
                    $name, $address, $district,
                    $square, $bedroom, $bathrooms,
                    $floor, $finish, $ceiling,
                    $land_sq, $prop_type, $land_type,
                    $price_raw, $price_m2, $cur, $type_deal,
                    $extra[0] ?? $img_cover, $ld
                );
                writeToLog('slide #3: country_info', "CARD:$i:SLIDES");
                break;

            case 'commercial':
                $slides .= slide_commercial_info(
                    $name, $address, $district, $metro,
                    $square, $floor, $total_floors, $finish, $ceiling,
                    $prop_type, $bld_type, $entrance, $layout,
                    $parking, $entrances, $security,
                    $electricity, $water, $heating, $usage,
                    $price_raw, $price_m2, $cur, $type_deal,
                    $extra[0] ?? $img_cover, $ld
                );
                writeToLog('slide #3: commercial_info', "CARD:$i:SLIDES");
                break;

            default: // pb
                $slides .= slide_info(
                    $name, $address, $district,
                    $square, $rooms, $bedroom, $bathrooms,
                    $floor, $total_floors, $finish, $ceiling,
                    $land_sq, $prop_type, $land_type,
                    $price_raw, $price_m2, $cur, $type_deal,
                    $extra[0] ?? $img_cover, $ld
                );
                writeToLog('slide #3: pb_info', "CARD:$i:SLIDES");
        }

        // ── Описание ──────────────────────────────────────────────────────────
        if (!empty($text)) {
            $desc_img = $extra[1] ?? $extra[0] ?? $img_cover;
            $slides .= slide_description($text, $desc_img, $ld, $desc_font);
            writeToLog('slide #4: desc (font=' . $desc_font . ', chars=' . $char_count . ')', "CARD:$i:SLIDES");
        } else {
            writeToLog('slide #4: desc SKIP (текст пуст)', "CARD:$i:SLIDES");
        }

        // ── Доп. фото ─────────────────────────────────────────────────────────
        foreach ($extra as $photo) {
            $slides .= slide_extra($photo, $ll);
        }
        writeToLog('slide extra x' . count($extra), "CARD:$i:SLIDES");

        // ── Финал / Контакты ──────────────────────────────────────────────────
        $broker_name    = trim($card['broker_name']    ?? '');
        $broker_phone   = trim($card['broker_phone']   ?? '');
        $broker_address = trim($card['broker_address'] ?? '');
        $broker_site    = trim($card['broker_site']    ?? '');

        if ($is_logo && ($broker_name || $broker_phone || $broker_site || $broker_address)) {
            $slides .= slide_contacts($address, $obj_id, $broker_name, $broker_phone, $broker_address, $broker_site, $ld);
            writeToLog('slide final: contacts', "CARD:$i:SLIDES");
        } else {
            $slides .= slide_finale($address, $obj_id);
            writeToLog('slide final: finale', "CARD:$i:SLIDES");
        }
    }

    $f_html     .= $slides;
    $last_name   = $name;
    $last_square = $square;

    writeToLog(['html_len' => strlen($slides)], "CARD:$i:DONE");
}

writeToLog('html_total_len=' . strlen($f_html), 'PDF:START');
$result = generate_pdf($f_html, $last_name, $last_square);
writeToLog('result=' . $result, 'PDF:DONE');

echo $result;

foreach ($tmp_files as $f) {
    @unlink($f);
}
writeToLog('deleted=' . count($tmp_files), 'CLEANUP');


// ════════════════════════════════════════════════════════════════════════════
// СЛАЙДЫ
// ════════════════════════════════════════════════════════════════════════════

/**
 * Слайд 1: Обложка — полноэкранное фото + название + адрес + ID.
 */
function slide_cover($img, $name, $address, $obj_id, $exclusive, $logo) {

    $excl = $exclusive
        ? '<p style="position:absolute;top:28px;left:40px;color:#ffffff;
                font-size:14px;font-family:DejaVu Sans,sans-serif;
                letter-spacing:1px;">Эксклюзив</p>'
        : '';

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:70px;height:auto;display:block;">
           </div>'
        : '';

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:1120px;height:791px;display:block;">'
        : '<div style="width:1120px;height:791px;background:#1a1a1a;"></div>';

    $addr_line = $address
        ? '<p style="color:rgba(255,255,255,0.85);font-size:15px;
                font-family:DejaVu Sans,sans-serif;margin-top:6px;">'
          . htmlspecialchars($address, ENT_QUOTES, 'UTF-8') . '</p>'
        : '';

    $id_line = $obj_id
        ? '<p style="color:rgba(255,255,255,0.7);font-size:13px;
                font-family:DejaVu Sans,sans-serif;margin-top:5px;">ID '
          . htmlspecialchars($obj_id) . '</p>'
        : '';

    return '
<div style="width:1120px;height:791px;position:relative;overflow:hidden;
             background:#111111;page-break-after:always;">
    ' . $img_tag . '
    ' . $excl . '
    ' . $logo_tag . '
    <div style="position:absolute;bottom:50px;left:0;width:1120px;text-align:center;">
        <p style="color:#ffffff;font-size:30px;font-family:DejaVu Serif,serif;
                  font-weight:normal;">'
            . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</p>
        ' . $addr_line . '
        ' . $id_line . '
    </div>
</div>';
}


/**
 * Слайд 2: Планировка — белый слайд с заголовком и изображением планировки.
 */
function slide_plan($map, $logo) {

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $map_tag = $map
        ? '<img src="' . $map . '" style="position:absolute;top:100px;left:75px;
               max-width:970px;max-height:620px;width:auto;height:auto;">'
        : '';

    return '
<div style="width:1120px;height:791px;position:relative;overflow:hidden;
             background:#ffffff;page-break-after:always;">
    <div style="position:absolute;top:44px;left:60px;">
        <p style="font-size:36px;font-family:DejaVu Serif,serif;font-weight:bold;
                  color:#1a1a1a;">Планировка</p>
    </div>
    ' . $map_tag . '
    ' . $logo_tag . '
</div>';
}


/**
 * Слайд характеристик — PB (базовый тип):
 * 70% фото слева + 30% панель справа с центрированными параметрами.
 */
function slide_info($name, $address, $district,
                    $square, $rooms, $bedroom, $bathrooms,
                    $floor, $total_floors, $finish, $ceiling,
                    $land_sq, $prop_type, $land_type,
                    $price, $price_m2, $cur, $type_deal,
                    $img, $logo) {

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:720px;height:791px;display:block;object-fit:cover;">'
        : '<div style="width:720px;height:791px;background:#d5d0c9;"></div>';

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $rows = [];
    if ($square)     $rows[] = ['Общая площадь:', $square . ' кв.м.'];
    if ($rooms)      $rows[] = ['Комнат:', $rooms];
    if ($bedroom)    $rows[] = ['Спален:', $bedroom];
    if ($bathrooms)  $rows[] = ['Санузлы:', $bathrooms];
    if ($floor || $total_floors) {
        $ft = $floor . ($total_floors ? ' из ' . $total_floors : '');
        $rows[] = ['Этаж:', $ft];
    }
    if ($finish)     $rows[] = ['Отделка:', $finish];
    if ($ceiling)    $rows[] = ['Высота потолков:', $ceiling . ' м.'];
    if ($land_sq)    $rows[] = ['Участок:', $land_sq . ' сот.'];
    if ($prop_type)  $rows[] = ['Вид недвижимости:', $prop_type];
    if ($land_type)  $rows[] = ['Назначение участка:', $land_type];

    $params_html = '';
    foreach ($rows as $r) {
        $params_html .= '
        <p style="font-size:12px;text-align:center;color:#1a1a1a;margin-bottom:10px;
                  font-family:DejaVu Sans,sans-serif;">
            <b>' . htmlspecialchars($r[0], ENT_QUOTES, 'UTF-8') . '</b>&nbsp;'
            . htmlspecialchars($r[1], ENT_QUOTES, 'UTF-8') . '
        </p>';
    }

    $price_str = $type_deal === 'Аренда'
        ? format_price($price, $cur) . ' / мес.'
        : format_price($price, $cur);

    $addr_html = '
    <div style="text-align:center;margin-bottom:16px;">
        <p style="font-size:8px;color:#888;margin-bottom:4px;
            font-family:DejaVu Sans,sans-serif;">&#9679;</p>
        <p style="font-size:13px;font-weight:bold;color:#1a1a1a;
            font-family:DejaVu Serif,serif;">'
            . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</p>
        ' . ($address
                ? '<p style="font-size:12px;color:#666;margin-top:3px;
                    font-family:DejaVu Sans,sans-serif;">'
                  . htmlspecialchars($address, ENT_QUOTES, 'UTF-8') . '</p>'
                : '') . '
    </div>';

    return '
<div style="width:1120px;height:791px;position:relative;background:#ffffff;page-break-after:always;">
    <div style="position:absolute;top:0;left:0;width:720px;height:791px;overflow:hidden;">
        ' . $img_tag . '
    </div>
    <div style="position:absolute;top:0;left:720px;width:400px;height:791px;
                background:#ffffff;padding:60px 32px 30px 32px;overflow:hidden;">
        ' . $addr_html . '
        ' . $params_html . '
        <div style="border-top:1px solid #cccccc;margin:8px 0 12px;"></div>
        <p style="font-size:18px;font-weight:bold;text-align:center;color:#1a1a1a;
                  font-family:DejaVu Serif,serif;">' . $price_str . '</p>
        ' . ($price_m2 > 0
            ? '<p style="font-size:11px;color:#999;text-align:center;margin-top:4px;
                    font-family:DejaVu Sans,sans-serif;">'
              . format_price($price_m2, $cur) . ' за кв.м.</p>'
            : '') . '
    </div>
    ' . $logo_tag . '
</div>';
}


/**
 * Слайд характеристик — CITY (городская/новостройки):
 * 70% фото слева + 30% панель справа с двухколоночной таблицей параметров.
 * Отличие от PB: параметры выровнены label/value, а не центрированы.
 */
function slide_city_info($name, $address, $district, $metro,
                         $square, $rooms, $bedroom, $bathrooms,
                         $floor, $total_floors, $finish, $ceiling,
                         $prop_type,
                         $price, $price_m2, $cur, $type_deal,
                         $img, $logo) {

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:720px;height:791px;display:block;object-fit:cover;">'
        : '<div style="width:720px;height:791px;background:#d5d0c9;"></div>';

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $rows = [];
    if ($district)    $rows[] = ['Район:', $district];
    if ($metro)       $rows[] = ['Метро:', $metro];
    if ($prop_type)   $rows[] = ['Тип:', $prop_type];
    if ($square)      $rows[] = ['Площадь:', $square . ' кв.м.'];
    if ($rooms)       $rows[] = ['Комнат:', $rooms];
    if ($bedroom)     $rows[] = ['Спален:', $bedroom];
    if ($bathrooms)   $rows[] = ['Санузлов:', $bathrooms];
    if ($floor || $total_floors) {
        $ft = $floor . ($total_floors ? ' / ' . $total_floors : '');
        $rows[] = ['Этаж:', $ft];
    }
    if ($finish)      $rows[] = ['Отделка:', $finish];
    if ($ceiling)     $rows[] = ['Потолки:', $ceiling . ' м.'];

    $params_html = '<table style="width:100%;border-collapse:collapse;margin-bottom:14px;">';
    foreach ($rows as $r) {
        $params_html .= '
        <tr>
            <td style="font-size:11px;color:#888888;padding:4px 6px 4px 0;
                       font-family:DejaVu Sans,sans-serif;vertical-align:top;white-space:nowrap;">'
                . htmlspecialchars($r[0], ENT_QUOTES, 'UTF-8') . '</td>
            <td style="font-size:11px;color:#1a1a1a;padding:4px 0;
                       font-family:DejaVu Sans,sans-serif;font-weight:bold;">'
                . htmlspecialchars($r[1], ENT_QUOTES, 'UTF-8') . '</td>
        </tr>';
    }
    $params_html .= '</table>';

    $price_str = $type_deal === 'Аренда'
        ? format_price($price, $cur) . ' / мес.'
        : format_price($price, $cur);

    return '
<div style="width:1120px;height:791px;position:relative;background:#ffffff;page-break-after:always;">
    <div style="position:absolute;top:0;left:0;width:720px;height:791px;overflow:hidden;">
        ' . $img_tag . '
    </div>
    <div style="position:absolute;top:0;left:720px;width:400px;height:791px;
                background:#ffffff;padding:50px 32px 30px 32px;overflow:hidden;">
        <p style="font-size:14px;font-weight:bold;color:#1a1a1a;margin-bottom:4px;
                  font-family:DejaVu Serif,serif;">'
            . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</p>
        ' . ($address
            ? '<p style="font-size:11px;color:#888;margin-bottom:16px;
                  font-family:DejaVu Sans,sans-serif;">'
              . htmlspecialchars($address, ENT_QUOTES, 'UTF-8') . '</p>'
            : '<div style="margin-bottom:16px;"></div>') . '
        ' . $params_html . '
        <div style="border-top:1px solid #CDC8BD;margin:6px 0 12px;"></div>
        <p style="font-size:18px;font-weight:bold;color:#1a1a1a;
                  font-family:DejaVu Serif,serif;">' . $price_str . '</p>
        ' . ($price_m2 > 0
            ? '<p style="font-size:11px;color:#999;margin-top:4px;
                    font-family:DejaVu Sans,sans-serif;">'
              . format_price($price_m2, $cur) . ' за кв.м.</p>'
            : '') . '
    </div>
    ' . $logo_tag . '
</div>';
}


/**
 * Слайд характеристик — COUNTRY (загородная):
 * 70% фото слева + 30% панель справа.
 * Акцент на участок, тип земли, доп. строения.
 */
function slide_country_info($name, $address, $district,
                            $square, $bedroom, $bathrooms,
                            $floor, $finish, $ceiling,
                            $land_sq, $prop_type, $land_type,
                            $price, $price_m2, $cur, $type_deal,
                            $img, $logo) {

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:720px;height:791px;display:block;object-fit:cover;">'
        : '<div style="width:720px;height:791px;background:#d5d0c9;"></div>';

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $rows = [];
    if ($district)   $rows[] = ['Направление:', $district];
    if ($prop_type)  $rows[] = ['Тип объекта:', $prop_type];
    if ($square)     $rows[] = ['Площадь дома:', $square . ' кв.м.'];
    if ($land_sq)    $rows[] = ['Участок:', $land_sq . ' сот.'];
    if ($land_type)  $rows[] = ['Назначение:', $land_type];
    if ($bedroom)    $rows[] = ['Спален:', $bedroom];
    if ($bathrooms)  $rows[] = ['Санузлов:', $bathrooms];
    if ($floor)      $rows[] = ['Этажей:', $floor];
    if ($finish)     $rows[] = ['Отделка:', $finish];
    if ($ceiling)    $rows[] = ['Высота потолков:', $ceiling . ' м.'];

    $params_html = '<table style="width:100%;border-collapse:collapse;margin-bottom:14px;">';
    foreach ($rows as $r) {
        $params_html .= '
        <tr>
            <td style="font-size:11px;color:#888888;padding:4px 6px 4px 0;
                       font-family:DejaVu Sans,sans-serif;vertical-align:top;white-space:nowrap;">'
                . htmlspecialchars($r[0], ENT_QUOTES, 'UTF-8') . '</td>
            <td style="font-size:11px;color:#1a1a1a;padding:4px 0;
                       font-family:DejaVu Sans,sans-serif;font-weight:bold;">'
                . htmlspecialchars($r[1], ENT_QUOTES, 'UTF-8') . '</td>
        </tr>';
    }
    $params_html .= '</table>';

    $price_str = $type_deal === 'Аренда'
        ? format_price($price, $cur) . ' / мес.'
        : format_price($price, $cur);

    return '
<div style="width:1120px;height:791px;position:relative;background:#ffffff;page-break-after:always;">
    <div style="position:absolute;top:0;left:0;width:720px;height:791px;overflow:hidden;">
        ' . $img_tag . '
    </div>
    <div style="position:absolute;top:0;left:720px;width:400px;height:791px;
                background:#ffffff;padding:50px 32px 30px 32px;overflow:hidden;">
        <p style="font-size:14px;font-weight:bold;color:#1a1a1a;margin-bottom:4px;
                  font-family:DejaVu Serif,serif;">'
            . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</p>
        ' . ($address
            ? '<p style="font-size:11px;color:#888;margin-bottom:16px;
                  font-family:DejaVu Sans,sans-serif;">'
              . htmlspecialchars($address, ENT_QUOTES, 'UTF-8') . '</p>'
            : '<div style="margin-bottom:16px;"></div>') . '
        ' . $params_html . '
        <div style="border-top:1px solid #CDC8BD;margin:6px 0 12px;"></div>
        <p style="font-size:18px;font-weight:bold;color:#1a1a1a;
                  font-family:DejaVu Serif,serif;">' . $price_str . '</p>
        ' . ($price_m2 > 0
            ? '<p style="font-size:11px;color:#999;margin-top:4px;
                    font-family:DejaVu Sans,sans-serif;">'
              . format_price($price_m2, $cur) . ' за кв.м.</p>'
            : '') . '
    </div>
    ' . $logo_tag . '
</div>';
}


/**
 * Слайд характеристик — COMMERCIAL (коммерция):
 * 70% фото слева + 30% панель справа с коммерческими полями (двухколоночная таблица).
 */
function slide_commercial_info($name, $address, $district, $metro,
                               $square, $floor, $total_floors, $finish, $ceiling,
                               $prop_type, $bld_type, $entrance, $layout,
                               $parking, $entrances, $security,
                               $electricity, $water, $heating, $usage,
                               $price, $price_m2, $cur, $type_deal,
                               $img, $logo) {

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:720px;height:791px;display:block;object-fit:cover;">'
        : '<div style="width:720px;height:791px;background:#d5d0c9;"></div>';

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $rows = [];
    if ($prop_type)   $rows[] = ['Назначение:', $prop_type];
    if ($usage)       $rows[] = ['Использование:', $usage];
    if ($square)      $rows[] = ['Площадь:', $square . ' кв.м.'];
    if ($floor || $total_floors) {
        $ft = $floor . ($total_floors ? ' / ' . $total_floors : '');
        $rows[] = ['Этаж:', $ft];
    }
    if ($ceiling)     $rows[] = ['Высота потолков:', $ceiling . ' м.'];
    if ($bld_type)    $rows[] = ['Тип здания:', $bld_type];
    if ($finish)      $rows[] = ['Отделка:', $finish];
    if ($entrance)    $rows[] = ['Вход:', $entrance];
    if ($entrances)   $rows[] = ['Кол-во входов:', $entrances];
    if ($layout)      $rows[] = ['Планировка:', $layout];
    if ($parking)     $rows[] = ['Парковка:', $parking];
    if ($security)    $rows[] = ['Охрана:', $security];
    if ($electricity) $rows[] = ['Электричество:', $electricity . ' кВт'];
    if ($water)       $rows[] = ['Водоснабжение:', $water];
    if ($heating)     $rows[] = ['Отопление:', $heating];
    if ($district)    $rows[] = ['Район:', $district];
    if ($metro)       $rows[] = ['Метро:', $metro];

    $params_html = '<table style="width:100%;border-collapse:collapse;margin-bottom:10px;">';
    foreach ($rows as $r) {
        $params_html .= '
        <tr>
            <td style="font-size:10px;color:#888888;padding:3px 6px 3px 0;
                       font-family:DejaVu Sans,sans-serif;vertical-align:top;white-space:nowrap;">'
                . htmlspecialchars($r[0], ENT_QUOTES, 'UTF-8') . '</td>
            <td style="font-size:10px;color:#1a1a1a;padding:3px 0;
                       font-family:DejaVu Sans,sans-serif;font-weight:bold;">'
                . htmlspecialchars($r[1], ENT_QUOTES, 'UTF-8') . '</td>
        </tr>';
    }
    $params_html .= '</table>';

    $price_str = $type_deal === 'Аренда'
        ? format_price($price, $cur) . ' / мес.'
        : format_price($price, $cur);

    return '
<div style="width:1120px;height:791px;position:relative;background:#ffffff;page-break-after:always;">
    <div style="position:absolute;top:0;left:0;width:720px;height:791px;overflow:hidden;">
        ' . $img_tag . '
    </div>
    <div style="position:absolute;top:0;left:720px;width:400px;height:791px;
                background:#ffffff;padding:44px 28px 26px 28px;overflow:hidden;">
        <p style="font-size:13px;font-weight:bold;color:#1a1a1a;margin-bottom:4px;
                  font-family:DejaVu Serif,serif;">'
            . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</p>
        ' . ($address
            ? '<p style="font-size:10px;color:#888;margin-bottom:14px;
                  font-family:DejaVu Sans,sans-serif;">'
              . htmlspecialchars($address, ENT_QUOTES, 'UTF-8') . '</p>'
            : '<div style="margin-bottom:14px;"></div>') . '
        ' . $params_html . '
        <div style="border-top:1px solid #CDC8BD;margin:6px 0 10px;"></div>
        <p style="font-size:17px;font-weight:bold;color:#1a1a1a;
                  font-family:DejaVu Serif,serif;">' . $price_str . '</p>
        ' . ($price_m2 > 0
            ? '<p style="font-size:10px;color:#999;margin-top:4px;
                    font-family:DejaVu Sans,sans-serif;">'
              . format_price($price_m2, $cur) . ' за кв.м.</p>'
            : '') . '
    </div>
    ' . $logo_tag . '
</div>';
}


/**
 * Слайд описания: 30% текст слева + 70% фото справа.
 * ID убран — он только на обложке и финальном слайде.
 */
function slide_description($text, $img, $logo, $font_size = '11px') {

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:672px;height:791px;display:block;object-fit:cover;">'
        : '<div style="width:672px;height:791px;background:#d5d0c9;"></div>';

    return '
<div style="width:1120px;height:791px;position:relative;background:#ffffff;page-break-after:always;">
    <div style="position:absolute;top:0;left:0;width:448px;height:791px;
                background:#ffffff;overflow:hidden;">
        <div style="position:absolute;top:60px;left:40px;width:368px;">
            <p style="font-size:22px;font-family:DejaVu Serif,serif;font-weight:bold;
                      color:#1a1a1a;margin-bottom:20px;">Описание объекта</p>
            <p style="font-size:' . $font_size . ';line-height:1.8;color:#333333;
                      font-family:DejaVu Sans,sans-serif;
                      word-wrap:break-word;">' . $text . '</p>
        </div>
    </div>
    <div style="position:absolute;top:0;left:448px;width:672px;height:791px;overflow:hidden;">
        ' . $img_tag . '
    </div>
    ' . $logo_tag . '
</div>';
}


/**
 * Доп. фото — полноэкранный фотослайд.
 */
function slide_extra($img, $logo) {

    $logo_tag = $logo
        ? '<div style="position:absolute;top:22px;right:36px;">
               <img src="' . $logo . '" style="width:65px;height:auto;display:block;">
           </div>'
        : '';

    $img_tag = $img
        ? '<img src="' . $img . '" style="width:1120px;height:791px;display:block;">'
        : '<div style="width:1120px;height:791px;background:#222222;"></div>';

    return '
<div style="width:1120px;height:791px;position:relative;overflow:hidden;
             background:#111111;page-break-after:always;">
    ' . $img_tag . '
    ' . $logo_tag . '
</div>';
}


/**
 * Финальный слайд с контактами брокера (когда есть брокер и логотип).
 * ID показывается на этом слайде.
 */
function slide_contacts($address, $obj_id, $broker_name, $broker_phone, $broker_address, $broker_site, $logo) {

    $top_lines = '';
    if ($address)
        $top_lines .= '<p style="font-size:20px;font-family:DejaVu Serif,serif;color:#1a1a1a;
                           margin:0 0 12px 0;">' . htmlspecialchars($address) . '</p>';
    if ($obj_id)
        $top_lines .= '<p style="font-size:20px;font-family:DejaVu Serif,serif;color:#1a1a1a;
                           margin:0 0 24px 0;">ID ' . htmlspecialchars($obj_id) . '</p>';
    $top_lines .= '<p style="font-size:20px;font-family:DejaVu Serif,serif;color:#1a1a1a;
                       margin:0;">Спасибо за доверие!</p>';

    $bot_lines = '';
    if ($broker_site)
        $bot_lines .= '<p style="font-size:16px;font-family:DejaVu Sans,sans-serif;color:#1a1a1a;
                           margin:0 0 10px 0;">' . htmlspecialchars($broker_site) . '</p>';
    if ($broker_address)
        $bot_lines .= '<p style="font-size:16px;font-family:DejaVu Sans,sans-serif;color:#1a1a1a;
                           margin:0 0 10px 0;">' . htmlspecialchars($broker_address) . '</p>';
    if ($broker_name)
        $bot_lines .= '<p style="font-size:16px;font-family:DejaVu Sans,sans-serif;color:#1a1a1a;
                           margin:0 0 10px 0;">' . htmlspecialchars($broker_name) . '</p>';
    if ($broker_phone)
        $bot_lines .= '<p style="font-size:16px;font-family:DejaVu Sans,sans-serif;color:#1a1a1a;
                           margin:0;">' . htmlspecialchars($broker_phone) . '</p>';

    $logo_tag = $logo
        ? '<img src="' . $logo . '" style="position:absolute;top:80px;left:480px;width:160px;height:auto;">'
        : '';

    return '
<div style="width:1120px;height:791px;position:relative;background:#E2DFDB;">
    ' . $logo_tag . '
    <div style="position:absolute;top:290px;left:260px;width:600px;text-align:center;">
        ' . $top_lines . '
    </div>
    <div style="position:absolute;top:478px;left:260px;width:600px;height:1px;background:#1a1a1a;"></div>
    <div style="position:absolute;top:500px;left:260px;width:600px;text-align:center;">
        ' . $bot_lines . '
    </div>
</div>';
}


/**
 * Финальный слайд без брокера (presType=disable или нет данных брокера).
 * ID показывается на этом слайде.
 */
function slide_finale($address, $obj_id) {

    $addr_line = $address
        ? '<p style="font-size:20px;font-family:DejaVu Serif,serif;color:#1a1a1a;
                margin:0 0 20px 0;">' . htmlspecialchars($address) . '</p>'
        : '';

    $id_line = $obj_id
        ? '<p style="font-size:20px;font-family:DejaVu Serif,serif;color:#1a1a1a;
                margin:0 0 20px 0;">ID ' . htmlspecialchars($obj_id) . '</p>'
        : '';

    return '
<div style="width:1120px;height:791px;background:#E2DFDB;overflow:hidden;position:relative;">
    <div style="position:absolute;top:330px;left:0;width:1120px;text-align:center;">
    ' . $addr_line . '
    ' . $id_line . '
    <p style="font-size:20px;font-family:DejaVu Serif,serif;color:#1a1a1a;
              margin:0;">Спасибо за доверие!</p>
    </div>
</div>';
}


// ════════════════════════════════════════════════════════════════════════════
// УТИЛИТЫ
// ════════════════════════════════════════════════════════════════════════════

function generate_pdf($html, $name, $square) {
    $full_html = '<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { background:#ffffff; }
</style>
</head>
<body>' . $html . '</body>
</html>';

    writeToLog('html_len=' . strlen($full_html), 'PDF');
    try {
        $dompdf = new Dompdf\Dompdf();
        $dompdf->set_option('isRemoteEnabled', TRUE);
        $dompdf->set_option('isHtml5ParserEnabled', TRUE);
        $dompdf->set_option('chroot', '/');
        $dompdf->setPaper('A4', 'landscape');

        $dompdf->loadHtml($full_html, 'UTF-8');
        $dompdf->render();

        $pdf     = $dompdf->output();
        $safe    = safe_fname($name . ' - ' . $square . '.pdf');
        $path    = PRES_DIR . $safe;
        $written = file_put_contents($path, $pdf);

        if ($written === false) {
            writeToLog('write FAIL: ' . $path, 'PDF:ERROR');
            return 'ERROR: не удалось сохранить PDF в ' . $path;
        }
        writeToLog(['size' => $written . 'b', 'file' => $safe], 'PDF:OK');
        return PRES_URL . rawurlencode($safe);

    } catch (\Throwable $e) {
        writeToLog($e->getMessage() . ' in ' . basename($e->getFile()) . ':' . $e->getLine(), 'PDF:EXCEPTION');
        return 'ERROR: ' . $e->getMessage();
    }
}

function download_photos($urls, $name, $card_idx, &$tmp_files) {
    $photos = [];
    foreach ($urls as $idx => $url) {
        $url = trim($url);
        if (empty($url)) continue;
        $fname = safe_fname($name . '_' . $card_idx . '_extra_' . $idx . '.jpg');
        $local = TEMP_IMG . $fname;
        $bytes = @file_get_contents($url);
        if ($bytes !== false) {
            file_put_contents($local, $bytes);
            $photos[]    = 'file://' . $local;
            $tmp_files[] = $local;
        } else {
            writeToLog("extra[$idx] FAIL: $url", 'DL:ERROR');
        }
    }
    return $photos;
}

// Вырезает чистый URL из строки вида "https://...,true" или "https://...,false"
function parse_image_url($raw) {
    $raw = trim((string)$raw, " \t\n\r,;");
    if (empty($raw)) return '';
    $raw = preg_replace('/,(true|false)$/i', '', $raw);
    $raw = trim($raw, " ,;");
    return (strpos($raw, 'http') === 0) ? $raw : '';
}

function download_single($url, $base_name, &$tmp_files) {
    if (empty($url)) return '';
    $fname = safe_fname($base_name . '.jpg');
    $local = TEMP_IMG . $fname;
    $ctx   = stream_context_create(['http' => ['timeout' => 20]]);
    $bytes = @file_get_contents($url, false, $ctx);
    if ($bytes === false) {
        writeToLog('FAIL: ' . $url, 'DL:ERROR');
        return '';
    }
    file_put_contents($local, $bytes);
    $tmp_files[] = $local;
    return 'file://' . $local;
}

function format_price($value, $unit = '') {
    if ($value <= 0) return '';
    return number_format($value, 0, ',', ' ') . ($unit ? ' ' . $unit : '');
}

function safe_fname($name) {
    $name = preg_replace('/[\/\\\\:*?"<>|@]/', '-', $name);
    return preg_replace('/\s{2,}/', ' ', trim($name));
}

function writeToLog($data, $title = '')
{
    $log = "\n------------------------\n";
    $log .= date("Y.m.d G:i:s") . "\n";
    $log .= (strlen($title) > 0 ? $title : 'DEBUG') . "\n";
    $log .= print_r($data, 1);
    $log .= "\n------------------------\n";
    file_put_contents(getcwd() . '/addDoc.log', $log, FILE_APPEND);
    return true;
}
