<?php
class ControllerEntegrasyonCiceksepeti extends Controller
{
    private $markalar = array(
        "arzum", "SerenityHaven", "MİR", "ellc", "teknotrust", "MEDITERIAN", "NIDAGE",
        "Mir Eğitim ve Yazılım", "LENOVO", "Elenberg", "woodhub", "HiTech", "nikadu",
        "knittingtr", "knitpro", "easytekno", "Rose", "dede", "sunplus", "MAGBOX",
        "Globex", "Skytech", "NEXT NEXTSTAR", "Astra", "FANTOM", "Tois Baby", "ALDEBA",
        "Star", "Dede Oyuncak", "LETS GO BABY", "Mikado", "Maxword", "TCL", "DailyTech",
        "Samsung", "DailyLink", "Vestel", "Urban Sound", "Jopus", "Jameson", "Bestway",
        "arçelik", "inFace", "beko", "Stilevs", "Bosch", "Profilo", "Electrolux",
        "Siemens", "Nilfisk", "Karcher", "Intex", "grundig", "phillips", "arnica",
        "hutt", "altus", "wiami", "npo", "onvo", "singer", "rubenis", "ALTUNAY",
        "king", "Uğur", "tulip", "lykke", "babyliss"
    );

    // Normalize edilmiş (trim + strtolower) marka isimleri
    private $normalizedMarkalar = array();
    private $lastPageFile = DIR_IMAGE . 'cs_last_page.txt';
    private $totalPages=0;

    // “Marka uyumsuz” ürünler
    private $brandMismatch   = array();

    // “Güncellenmeyen” ürünler arasında product_url'de bulunan ve bulunmayan olarak ayrılmış diziler
    private $updatableOutdated   = array();
    private $missingProductUrl   = array();

    private $user_info  = null;
    private $api_info   = null;

    public function __construct($registry)
    {
        parent::__construct($registry);
        $this->reg = $registry;

        // Marka listesini normalize edelim (baş/son boşlukları temizle + UTF-8 strtolower)
        foreach ($this->markalar as $m) {
            $key = mb_strtolower(trim($m), 'UTF-8');
            if ($key !== '') {
                $this->normalizedMarkalar[$key] = true;
            }
        }
    }

    public function index()
    {
        if(!STATUS){
            return;
        }
        $this->load->model("entegrasyon/addproduct");
        $this->load->model("catalog/product_finder");
        // Hata raporlama (geliştirme aşamasında açık olabilir)
        error_reporting(E_ALL);
        ini_set('display_errors', 1);
        if (file_exists($this->lastPageFile)) {
            $lastPage = (int)file_get_contents($this->lastPageFile);
        } else {
            // Dosya yoksa 0 kabul et
            $lastPage = 1;
        }

        // -------------------------
        // 1) “Bir sonraki” sayfa numarasını hesapla
        // -------------------------
        $nextPage = $lastPage;

        // -------------------------
        // 2) Hata raporlama (geliştirme aşamasında açık olabilir)
        // -------------------------
        error_reporting(E_ALL);
        ini_set('display_errors', 1);
        // ---------------------------------------------------------------------
        // 1) “Şu an” ve “7 gün önce” zamanlarını milisaniye cinsinden hesaplayalım
        // ---------------------------------------------------------------------
        $currentMs   = time() * 1000;
        $sevenDaysMs = 7 * 24 * 60 * 60 * 1000;
        $thresholdMs = $currentMs - $sevenDaysMs;

        // ---------------------------------------------------------------------
        // 2) Gerekli modeli bir kez yüklüyoruz
        // ---------------------------------------------------------------------
        $this->load->model('tool/entegrasyon_api');

        // ---------------------------------------------------------------------
        // 3) Kullanıcı bilgilerini çekelim (SQL enjeksiyonunu önlemek için escape)
        // ---------------------------------------------------------------------
        $this->user_info = $this->db
            ->query(
                "SELECT * FROM `oc_user_database` ud 
                 LEFT JOIN `oc_user` u 
                   ON (ud.database_id = u.user_database_id) 
                 WHERE ud.name = '" . $this->db->escape(USERNAME) . "'"
            )
            ->row;

        // ---------------------------------------------------------------------
        // 4) Marketplace sınıfını oluşturup registry’e ekleyelim
        // ---------------------------------------------------------------------
        $marketplace = "cs";
        $className   = "Marketplace\\$marketplace";
        $this->reg->set($marketplace, new $className($this->reg));

        // ---------------------------------------------------------------------
        // 5) API bilgilerini alalım
        // ---------------------------------------------------------------------
        $this->api_info = $this->model_tool_entegrasyon_api
            ->getEntegrasyonApiInfo($marketplace, $this->user_info['database_id']);

        // ---------------------------------------------------------------------
        // 6) Trendyol’dan ürünleri çekelim (örnek: 100 kayıt, sayfa 102)
        // ---------------------------------------------------------------------
        $productFilter = array(
            'itemcount' => LIMIT,
            'page'      => $nextPage
        );
        $apiResult = $this->getProducts($productFilter, true, false);








        if(isset($apiResult['result']['totalCount'])){

            $this->totalPages=round($apiResult['result']['totalCount']/LIMIT);

        }else {


            file_put_contents($this->lastPageFile, 1);
        }

        // ---------------------------------------------------------------------
        // 7) Dönen içerik varsa kontrol edip “farklı marka” ve “güncellenmeyen” listelerini dolduralım
        // ---------------------------------------------------------------------
        if (
            isset($apiResult['result']['products']) &&
            is_array($apiResult['result']['products'])
        ) {
            foreach ($apiResult['result']['products'] as $product) {

                $barcode=$product['stockCode'];

                // c) product_url tablosunda barkoda göre sorgu
                $query = $this->db->query(
                    "SELECT * FROM `product_url` WHERE `barcode` = '" . $barcode . "'"
                );

                if ($query->num_rows) {
                    // Ürün product_url tablosunda mevcut → güncellenebilir
                    $this->updatableOutdated[] = array(
                        'id' => $query->row['id'],
                        'barcode' => $barcode,
                        'market_id' => $product['productCode'],
                        'price' =>$product['salesPrice'],
                        'url' => $query->row['url'],

                    );
                } else {
                    // product_url tablosunda yok → eksik olarak kaydet
                    $this->missingProductUrl[] = array(
                        'barcode'          => $barcode,
                        'market_id'        =>$product['productCode']

                    );
                }
            }
        }





        // ---------------------------------------------------------------------
        // 8) “updatableOutdated” ürünlerin URL’lerini alıp toplu güncelleme yapalım
        // ---------------------------------------------------------------------
        $cs_update_list = array();
        $url_list       = array();

        foreach ($this->updatableOutdated as $item) {
            $url_list[] = $item;
        }





        // Çok fazla URL varsa paralel istek sayısını ayarlamak için
        $bulkResults = $this->model_entegrasyon_addproduct->getProductsBulkWithRetry($url_list, 5, 2);





        foreach ($bulkResults as $index => $cs_product_info) {

            if ($cs_product_info) {


                $item = $this->updatableOutdated[$index]; // aynı sıra korunmalı

                if ($cs_product_info['httpcode'] == 200) {
                    $status = $cs_product_info['has_stock'] ? QUANTITY : 0;

                    // product_url tablosunu güncelle

                    $this->db->query(
                        "UPDATE `product_url` 
                     SET `status` = '" . $status . "',
                         `title` = '" . $this->db->escape($cs_product_info['title']) . "',
                         `image` = '" . $this->db->escape($cs_product_info['image']) . "',
                         `update_cycle` = `update_cycle` + 1,
                         `orginal_price` = '" . (float)$cs_product_info['price'] . "',
                         `httpcode` = '" . $cs_product_info['httpcode'] . "',
                         `last_update_date` = NOW()
                     WHERE `stock_code` like '" . (int)$cs_product_info['barcode'] . "'"
                    );

                    // Fiyat hesaplama ve satılabilirlik
                    $calculatedPrice = $this->calculate_price($cs_product_info['price']);
                    if ($calculatedPrice > MAX_PRICE) {
                        $quantity = 0;
                    } else {
                        $quantity = $cs_product_info['has_stock'] ? QUANTITY : 0;
                    }

                    if (!$cs_product_info['barcode']) {
                        print_r($cs_product_info);

                    }
                    $cs_update_list[] = array(
                        'barcode' => $cs_product_info['barcode'],
                        'stock_code' => $cs_product_info['barcode'],
                        'orginal_price' => $cs_product_info['price'],
                        'salePrice' => $calculatedPrice,
                        'is_missing' => false,
                        'listPrice' => $calculatedPrice,
                        'quantity' => $quantity,
                    );
                } else if ($cs_product_info['httpcode'] == 429) {


                    $this->db->query(
                        "UPDATE `product_url` 
                     SET  `httpcode` = '" . $cs_product_info['httpcode'] . "',
                         `last_update_date` = NOW()
                     WHERE `stock_code` like '" . (int)$cs_product_info['barcode'] . "'");

                }
            }

            // ---------------------------------------------------------------------
            // 9) Çıktıyı oluşturup print_r ile gösterelim, ardından geri dönelim
            // ---------------------------------------------------------------------
            $output = array(
                'brand_mismatch' => $this->brandMismatch,
                'updatable_outdated' => $this->updatableOutdated,
                'missing_product_url' => $this->missingProductUrl
            );


            foreach ($this->brandMismatch as $brandMismatch) {
                $cs_update_list[] = array(
                    'barcode' => $brandMismatch['barcode'],
                    'salePrice' => 0,
                    'listPrice' => 0,
                    'quantity' => 0
                );
            }


            foreach ($this->missingProductUrl as $brandMismatch) {

                $barcode = str_replace($this->prefix_list, '', $brandMismatch['barcode']);

                $result = $this->model_entegrasyon_addproduct->fetchTrendyolProductViaApi($barcode);

                if ($result) {

                    $this->db->query("INSERT INTO `product_url` SET user_id='" . $this->user_info['user_id'] . "', `stock_code`='" . $this->db->escape($brandMismatch['barcode']) . "', `barcode`='" . $this->db->escape($brandMismatch['barcode']) . "', `url`='" . $result['link'] . "', `sale_price` ='" . $result['price'] . "', cs=1 ");
                    $calculatedPrice = $this->model_entegrasyon_addproduct->calculate_price($result['price']);
                    $quantity = QUANTITY;
                    $cs_update_list[] = array(
                        'barcode' => $brandMismatch['barcode'],
                        'stock_code' => $brandMismatch['barcode'],
                        'orginal_price' => $result['price'],
                        'salePrice' => $calculatedPrice,
                        'listPrice' => $calculatedPrice,
                        'is_missing' => true,
                        'quantity' => $quantity,
                    );


                } else {

                    $cs_update_list[] = array(
                        'barcode' => $brandMismatch['barcode'],
                        'stock_code' => $brandMismatch['barcode'],
                        'salePrice' => 0,
                        'listPrice' => 0,
                        'quantity' => 0
                    );

                }

            }
        }


        $api_info = $this->model_tool_entegrasyon_api->getEntegrasyonApiInfo($marketplace, $this->user_info['database_id']);
        $result = $this->{$marketplace}->update_fast($cs_update_list, $api_info);

        print_r($result);

        $writePage = $nextPage + 1;
        // Eğer bir sonraki > toplam sayfa sayısı, 1 yazarız
        if (isset($this->totalPages) && $writePage > $this->totalPages) {
            $writePage = 1;
        }


        file_put_contents($this->lastPageFile, $writePage);
        // print_r($result);


        //print_r($output);

        // JSON olarak da döndürebilirsiniz:
        /*
        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($output));
        */
    }

    /**
     * Her seferinde tek bir URL’i cURL ile çekip parse eden metot.
     */
    public function get_product($url)
    {
        sleep(2);
        $fullUrl = "https://www.trendyol.com" . $url;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $fullUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

        $content  = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode == 404) {
            return [
                'has_stock' => 0,
                'httpcode'  => $httpCode,
                'barcode'   => 'ghghg',
                'status'    => true,
                'price'     => 0
            ];
        }

        if ($httpCode != 200) {
            return [
                'has_stock' => 0,
                'httpcode'  => $httpCode,
                'barcode'   => '',
                'status'    => true,
                'price'     => 0
            ];
        }

        preg_match('#<script type="application/javascript">(.*?)</script>#si', $content, $attr);

        if (isset($attr[1])) {
            preg_match('/"hasStock":(true|false)/', $attr[1], $hasStockMatch);
            $hasStock = $hasStockMatch[1] ?? 'Bulunamadı';

            preg_match('/"barcode":"([^"]+)"/', $attr[1], $barcodeMatch);
            $barcode = $barcodeMatch[1] ?? 'Bulunamadı';

            preg_match('/"sellingPrice":\{"text":"[^"]+","value":([0-9.]+)\}/', $attr[1], $sellingPriceMatch);
            $sellingPrice = $sellingPriceMatch[1] ?? 'Bulunamadı';

            preg_match('/"nameWithProductCode":"([^"]+)"/', $attr[1], $nameMatch);
            $productName = $nameMatch[1] ?? 'Bulunamadı';

            preg_match('/"images":\["([^"]+)"/', $attr[1], $imageMatch);
            $firstImage = $imageMatch[1] ?? 'Bulunamadı';

            return [
                'has_stock' => ($hasStock === "true") ? 1 : 0,
                'httpcode'  => $httpCode,
                'barcode'   => $barcode,
                'status'    => true,
                'title'     => $productName,
                'image'     => $firstImage,
                'price'     => $sellingPrice
            ];
        } else {
            return [
                'has_stock' => 0,
                'httpcode'  => $httpCode,
                'barcode'   => '',
                'status'    => false,
                'price'     => 0
            ];
        }
    }

    /**
     * Çok sayıda URL’i paralel ve retry mantığıyla çeken metot.
     *
     * @param array $urls             // Relatif path’ler (örn. "/urun-p-12345")
     * @param int   $maxConcurrency   // Aynı anda açılacak maksimum bağlantı
     * @param int   $maxRetries       // 429 durumunda en çok kaç defa retry yapılsın
     * @return array                  // [index => parse edilmiş sonuç]
     */
    public function getProductsBulkWithRetry(array $urls, int $maxConcurrency = 5, int $maxRetries = 2)
    {
        $allResults = [];
        $chunks     = array_chunk($urls, $maxConcurrency);

        foreach ($chunks as $chunkIndex => $chunk) {
            $remaining     = $chunk;
            $triesLeft     = array_fill(0, count($chunk), $maxRetries);
            $chunkResults  = array_fill(0, count($chunk), null);

            while (!empty($remaining)) {
                $multiHandle   = curl_multi_init();
                $curlHandles   = [];
                $mapIndexToUrl = [];

                foreach ($remaining as $relIndex => $path) {
                    $fullUrl = "https://www.trendyol.com" . $path;

                    $ch = curl_init();
                    curl_setopt($ch, CURLOPT_URL, $fullUrl);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)');
                    curl_setopt($ch, CURLOPT_TIMEOUT, 10);

                    curl_multi_add_handle($multiHandle, $ch);
                    $curlHandles[$relIndex] = $ch;
                    $mapIndexToUrl[$relIndex] = $relIndex;
                }

                $active = null;
                do {
                    $mrc = curl_multi_exec($multiHandle, $active);
                    if ($active && $mrc === CURLM_OK) {
                        curl_multi_select($multiHandle);
                    }
                } while ($active && $mrc === CURLM_OK);

                foreach ($curlHandles as $relIndex => $ch) {
                    $content  = curl_multi_getcontent($ch);
                    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                    $globalIndex = $relIndex;

                    if ($httpCode == 429 && $triesLeft[$globalIndex] > 0) {
                        $triesLeft[$globalIndex]--;
                        $remaining[$globalIndex] = $chunk[$globalIndex];
                    } else {
                        if ($httpCode == 200) {
                            preg_match('#<script type="application/javascript">(.*?)</script>#si', $content, $attr);
                            if (isset($attr[1])) {
                                preg_match('/"hasStock":(true|false)/', $attr[1], $hasStockMatch);
                                $hasStock = $hasStockMatch[1] ?? 'true';

                                preg_match('/"barcode":"([^"]+)"/', $attr[1], $barcodeMatch);
                                $barcode = $barcodeMatch[1] ?? '';

                                preg_match('/"sellingPrice":\{"text":"[^"]+","value":([0-9.]+)\}/', $attr[1], $sellingPriceMatch);
                                $sellingPrice = $sellingPriceMatch[1] ?? 0;

                                preg_match('/"nameWithProductCode":"([^"]+)"/', $attr[1], $nameMatch);
                                $productName = $nameMatch[1] ?? '';

                                preg_match('/"images":\["([^"]+)"/', $attr[1], $imageMatch);
                                $firstImage = $imageMatch[1] ?? '';

                                $chunkResults[$globalIndex] = [
                                    'has_stock' => ($hasStock === "true") ? 1 : 0,
                                    'httpcode'  => $httpCode,
                                    'barcode'   => $barcode,
                                    'status'    => true,
                                    'title'     => $productName,
                                    'image'     => $firstImage,
                                    'price'     => $sellingPrice
                                ];
                            } else {
                                $chunkResults[$globalIndex] = [
                                    'has_stock' => 0,
                                    'httpcode'  => 200,
                                    'barcode'   => '',
                                    'status'    => false,
                                    'price'     => 0
                                ];
                            }
                        } elseif ($httpCode == 404) {
                            $chunkResults[$globalIndex] = [
                                'has_stock' => 0,
                                'httpcode'  => 404,
                                'barcode'   => 'NotFound',
                                'status'    => true,
                                'price'     => 0
                            ];
                        } else {
                            $chunkResults[$globalIndex] = [
                                'has_stock' => 0,
                                'httpcode'  => $httpCode,
                                'barcode'   => '',
                                'status'    => ($httpCode == 429 ? false : true),
                                'price'     => 0
                            ];
                        }
                        unset($remaining[$globalIndex]);
                    }

                    curl_multi_remove_handle($multiHandle, $ch);
                    curl_close($ch);
                }

                curl_multi_close($multiHandle);

                if (!empty($remaining)) {
                    sleep(2);
                }
            }

            foreach ($chunkResults as $i => $res) {
                $allResults[$chunkIndex * $maxConcurrency + $i] = $res;
            }

            sleep(1);
        }

        ksort($allResults);
        return $allResults;
    }

    /**
     * Trendyol’dan ürünleri çekmek için yardımcı metot.
     *
     * @param array   $data          ['itemcount' => int, 'page' => int]
     * @param boolean $onlyApproved  Sadece onaylı ürünleri mi çekelim?
     * @param boolean $debug         Debug modu (ileride kullanılabilir)
     * @return array                 API’den dönen ham cevap
     */
    public function getProducts($data = array(), $onlyApproved = true, $debug = false)
    {
        $this->load->model('entegrasyon/general');

        $itemcount = isset($data['itemcount']) ? (int)$data['itemcount'] : 100;
        $page      = isset($data['page']) ? (int)$data['page'] : 1;

        $post_data = array(
            'request_data' => array(
                'itemcount' => $itemcount,
                'page'      => $page,
                'approved'  => $onlyApproved,
                'on_sale'   => false
            )
        );

        return $this->cs->get_products(
            $post_data['request_data'],
            $this->api_info
        );
    }

    /**
     * Başka yerlerde (gerektiğinde) marka kontrolü yapacak yardımcı metot.
     *
     * @param string $brand  Kontrol edilecek marka ismi
     * @return bool          Eğer normalize edilmiş listede varsa true döner.
     */
    private function checkBrand($brand)
    {
        $key = mb_strtolower(trim($brand), 'UTF-8');
        return isset($this->normalizedMarkalar[$key]);
    }

    /**
     * Fiyat hesaplama metodu.
     */
    private function calculate_price($ty_price)
    {
        if (!is_numeric($ty_price)) {
            $ty_price = 0;
        }

        $multipliers = [
            [100, 9],
            [200, 8],
            [300, 7],
            [400, 6],
            [500, 5],
            [1000, 4],
            [2000, 3.5],
            [3000, 3.3],
            [5000, 3.0],
            [8000, 2.8],
        ];

        foreach ($multipliers as [$threshold, $multiplier]) {
            if ($ty_price < $threshold) {
                return number_format((float)$ty_price * $multiplier, 0, '', '');
            }
        }

        return number_format((float)$ty_price * 2.4, 0, '', '');
    }
}
