<?php
/**
 * خواننده ساده و بدون وابستگی فایل‌های XLSX
 * برای هاست‌های اشتراکی که دسترسی به Composer ندارند نوشته شده است.
 * فقط داده‌های متنی/عددی سلول‌ها را می‌خواند (بدون فرمول، بدون فرمت‌بندی).
 * نیازمند اکستنشن‌های استاندارد PHP: zip, simplexml, dom
 */

function xlsx_col_letters_to_index($letters) {
    $letters = strtoupper($letters);
    $index = 0;
    for ($i = 0; $i < strlen($letters); $i++) {
        $index = $index * 26 + (ord($letters[$i]) - ord('A') + 1);
    }
    return $index - 1; // صفر-پایه
}

/**
 * خواندن یک فایل xlsx و برگرداندن آرایه‌ای از شیت‌ها
 * هر شیت: آرایه‌ای از سطرها، هر سطر: آرایه انجمنی [ستون صفر-پایه => مقدار متنی]
 *
 * @return array|null در صورت خطا null برمی‌گرداند
 */
function xlsx_read_workbook($filepath) {
    if (!class_exists('ZipArchive')) {
        throw new Exception('اکستنشن zip در PHP این هاست فعال نیست. لطفاً با پشتیبانی هاست تماس بگیرید.');
    }

    $zip = new ZipArchive();
    if ($zip->open($filepath) !== true) {
        throw new Exception('فایل اکسل قابل باز شدن نیست. مطمئن شوید فرمت آن xlsx است.');
    }

    // -------- workbook.xml : ترتیب و نام شیت‌ها + rId --------
    $workbookXml = $zip->getFromName('xl/workbook.xml');
    if ($workbookXml === false) {
        $zip->close();
        throw new Exception('ساختار فایل اکسل نامعتبر است (workbook.xml یافت نشد).');
    }
    $wbXmlObj = simplexml_load_string($workbookXml);
    $wbXmlObj->registerXPathNamespace('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');

    $sheetsMeta = []; // [name => rId]
    foreach ($wbXmlObj->sheets->sheet as $sheet) {
        $attrs = $sheet->attributes();
        $rAttrs = $sheet->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
        $name = (string)$attrs['name'];
        $rid = (string)$rAttrs['id'];
        $sheetsMeta[] = ['name' => $name, 'rid' => $rid];
    }

    // -------- rels : rId => مسیر فایل شیت --------
    $relsXml = $zip->getFromName('xl/_rels/workbook.xml.rels');
    $ridToTarget = [];
    if ($relsXml !== false) {
        $relsObj = simplexml_load_string($relsXml);
        foreach ($relsObj->Relationship as $rel) {
            $ridToTarget[(string)$rel['Id']] = (string)$rel['Target'];
        }
    }

    // -------- shared strings --------
    $sharedStrings = [];
    $sharedXml = $zip->getFromName('xl/sharedStrings.xml');
    if ($sharedXml !== false) {
        $sharedObj = simplexml_load_string($sharedXml);
        foreach ($sharedObj->si as $si) {
            $sharedStrings[] = xlsx_extract_si_text($si);
        }
    }

    $result = [];

    foreach ($sheetsMeta as $meta) {
        $target = $ridToTarget[$meta['rid']] ?? null;
        if (!$target) continue;

        // نرمال‌سازی مسیر (ممکن است با / شروع شود یا نسبت به پوشه xl/ باشد)
        if (strpos($target, '/') === 0) {
            $entryPath = ltrim($target, '/');
        } else {
            $entryPath = 'xl/' . preg_replace('#^\.?/?#', '', $target);
        }

        $sheetXml = $zip->getFromName($entryPath);
        if ($sheetXml === false) continue;

        $sheetObj = simplexml_load_string($sheetXml);
        $rows = [];

        if (isset($sheetObj->sheetData->row)) {
            foreach ($sheetObj->sheetData->row as $row) {
                $rowData = [];
                foreach ($row->c as $c) {
                    $ref = (string)$c['r'];
                    preg_match('/^([A-Z]+)/', $ref, $m);
                    $colIndex = isset($m[1]) ? xlsx_col_letters_to_index($m[1]) : count($rowData);
                    $type = (string)$c['t'];

                    $value = '';
                    if ($type === 's') {
                        $vIndex = (int)$c->v;
                        $value = $sharedStrings[$vIndex] ?? '';
                    } elseif ($type === 'inlineStr') {
                        $value = isset($c->is) ? xlsx_extract_si_text($c->is) : '';
                    } elseif ($type === 'str' || $type === 'b' || $type === '') {
                        $value = isset($c->v) ? (string)$c->v : '';
                    } else {
                        $value = isset($c->v) ? (string)$c->v : '';
                    }

                    $rowData[$colIndex] = $value;
                }
                if (!empty($rowData)) {
                    $rows[] = $rowData;
                }
            }
        }

        $result[$meta['name']] = $rows;
    }

    $zip->close();
    return $result;
}

function xlsx_extract_si_text($si) {
    // اگر متن مستقیم <t> دارد
    if (isset($si->t)) {
        return (string)$si->t;
    }
    // اگر متن به‌صورت چند بخشی (rich text runs) است
    if (isset($si->r)) {
        $text = '';
        foreach ($si->r as $run) {
            $text .= (string)$run->t;
        }
        return $text;
    }
    return '';
}

/** دریافت مقدار یک سلول از سطر با اندیس صفر-پایه، با مقدار پیش‌فرض خالی */
function xlsx_cell($rowData, $index) {
    return isset($rowData[$index]) ? trim($rowData[$index]) : '';
}
