<?php

namespace App\Services;

use App\Repositories\CreatorRepository;
use App\Support\IdFormatter;
use App\Support\Uuid;
use App\Utils\AuditLog;
use App\Utils\StringHelper;
use Illuminate\Support\Facades\Cache;

class CreatorService extends BaseService
{
    protected $repository;

    const METRICS_CACHE_TTL = 60;
    const METRICS_CACHE_KEY = 'creator_metrics_v2:';

    public function __construct()
    {
        $this->repository = new CreatorRepository();
    }

    /**
     * Lấy danh sách Creator với pagination
     */
    public function getListWithPaginate(?string $orgHex, int $perPage = 15)
    {
        return $this->repository->paginateByOrganization($orgHex, $perPage);
    }

    /**
     * Lấy dữ liệu bảng Creator có filter/sort/paginate.
     * Chuyển đổi filter classification (Nano/Micro/Macro) thành followers range.
     */
    public function getListForTable(?string $orgHex, array $filters = [], int $perPage = 10)
    {
        // Chuyển classification filter thành followers range
        $classification = $filters['classification'] ?? '';
        if ($classification !== '') {
            unset($filters['classification']);
            switch ($classification) {
                case 'nano':
                    $filters['followers_min'] = max((int)($filters['followers_min'] ?? 0), 1000);
                    $filters['followers_max'] = min((int)($filters['followers_max'] ?? 9999), 9999);
                    break;
                case 'micro':
                    $filters['followers_min'] = max((int)($filters['followers_min'] ?? 0), 10000);
                    $filters['followers_max'] = min((int)($filters['followers_max'] ?? 99999), 99999);
                    break;
                case 'macro':
                    $filters['followers_min'] = max((int)($filters['followers_min'] ?? 0), 100000);
                    break;
            }
        }

        return $this->repository->paginateFilteredByOrganization($orgHex, $filters, $perPage);
    }

    /**
     * Lấy metrics cho dashboard Creator (có cache).
     * Cache được clear khi có thay đổi (create/update/delete/import).
     */
    public function getMetrics(?string $orgHex): array
    {
        if (!$orgHex) return [];

        $cacheKey = self::METRICS_CACHE_KEY . $orgHex;

        return Cache::remember($cacheKey, self::METRICS_CACHE_TTL, function () use ($orgHex) {
            return $this->repository->getMetricsByOrganization($orgHex);
        });
    }

    /**
     * Clear metrics cache (gọi khi có thay đổi dữ liệu)
     */
    public function clearMetricsCache(?string $orgHex): void
    {
        if ($orgHex) {
            Cache::forget(self::METRICS_CACHE_KEY . $orgHex);
        }
    }

    /**
     * Tạo Creator mới
     */
    public function createCreator(array $data, ?string $orgHex)
    {
        $data = $this->prepareCreateData($data, $orgHex);
        $creator = $this->repository->create($data);

        // Clear metrics cache
        $this->clearMetricsCache($orgHex);

        $details = '';
        if (!empty($creator->creator_name)) {
            $details .= 'Tên KOC: ' . $creator->creator_name . "\n";
        }
        if (!empty($creator->tiktok_link)) {
            $details .= 'Link TikTok: ' . substr($creator->tiktok_link, 0, 80) . "\n";
        }
        if (!empty($creator->contact_phone)) {
            $details .= 'Điện thoại: ' . $creator->contact_phone . "\n";
        }
        if (!empty($creator->followers)) {
            $details .= 'Followers: ' . number_format($creator->followers, 0, '.', '.') . "\n";
        }
        AuditLog::log('create_koc', 'koc', $creator->hex_id ?? $creator->id, $creator->creator_name ?? 'Unknown', $details ?: null, AuditLog::detectTabFromReferer('koc'));

        return $creator;
    }

    /**
     * Cập nhật Creator
     * @param string $source Nguồn thao tác (null: thủ công, 'sync_tiktok': đồng bộ TikTok)
     */
    public function updateCreator(string $id, array $data, ?string $orgHex, ?string $source = null)
    {
        $old = $this->repository->getByIdInOrganization($id, $orgHex);
        if (!$old) {
            return false;
        }

        $updated = $this->repository->updateInOrganization($id, $data, $orgHex);

        if ($updated) {
            $this->clearMetricsCache($orgHex);

            $fieldLabels = [
                'creator_name' => 'Tên KOC', 'tiktok_link' => 'Link TikTok',
                'tiktok_cid' => 'CID TikTok',
                'instagram_link' => 'Link Instagram', 'facebook_link' => 'Link Facebook',
                'contact_phone' => 'Điện thoại', 'contact_email' => 'Email',
                'contact_zalo' => 'Zalo', 'followers' => 'Followers',
                'gmv' => 'GMV', 'items' => 'Items', 'average_views' => 'View TB',
                'address' => 'Địa chỉ', 'notes' => 'Ghi chú',
                'audience' => 'Tệp khách hàng', 'advantages' => 'Lợi thế',
                'content' => 'Nội dung',
            ];
            $details = $this->buildAuditDiff($data, $old, $fieldLabels);
            if ($source === 'sync_tiktok') {
                $details = '[Đồng bộ TikTok] ' . trim($details);
            }
            if (trim($details)) {
                AuditLog::log('update_koc', 'koc', IdFormatter::formatModelId($old), $old->creator_name ?? 'Unknown', trim($details), AuditLog::detectTabFromReferer('koc'));
            }
        }

        return $updated;
    }

    /**
     * Cập nhật TikTok CID cho Creator
     */
    public function updateTikTokCid(string $id, string $cid, ?string $orgHex)
    {
        $creator = $this->repository->getByIdInOrganization($id, $orgHex);
        if (!$creator) {
            return false;
        }

        $updated = $this->repository->updateInOrganization($id, ['tiktok_cid' => $cid], $orgHex);
        if ($updated) {
            $details = 'TikTok CID: ' . $cid;
            AuditLog::log('update_koc', 'koc', IdFormatter::formatModelId($creator), $creator->creator_name ?? 'Unknown', $details, AuditLog::detectTabFromReferer('koc'));
        }
        return $updated;
    }

    /**
     * Xóa Creator
     */
    public function deleteCreator(string $id, ?string $orgHex)
    {
        $deleted = $this->repository->deleteInOrganization($id, $orgHex);
        if ($deleted) {
            $this->clearMetricsCache($orgHex);
        }
        return $deleted;
    }

    /**
     * Xóa hàng loạt Creator
     */
    public function bulkDeleteCreators(array $ids, ?string $orgHex): array
    {
        $deleted = 0;
        $errors = [];
        $creators = [];

        foreach ($ids as $id) {
            $creator = $this->repository->getByIdInOrganization($id, $orgHex);
            if (!$creator) {
                $errors[] = 'Không tìm thấy KOC ID: ' . $id;
                continue;
            }
            $creators[] = $creator;
        }

        if (!empty($creators)) {
            $creatorIds = array_map(function ($c) { return $c->hex_id; }, $creators);
            $count = $this->repository->deleteMultipleInOrganization($creatorIds, $orgHex);
            if ($count > 0) {
                foreach ($creators as $creator) {
                    $this->logDeleteCreator($creator);
                }
                $deleted = $count;
                $this->clearMetricsCache($orgHex);
            }
        }

        return compact('deleted', 'errors');
    }

    /**
     * Ghi audit log khi xóa Creator (gọi từ Controller sau khi fetch dữ liệu cũ)
     */
    public function logDeleteCreator($creator): void
    {
        $creatorName = $creator->creator_name ?? 'Unknown';
        AuditLog::log('delete_koc', 'koc', IdFormatter::formatModelId($creator), $creatorName, 'Đã xóa KOC: ' . $creatorName, AuditLog::detectTabFromReferer('koc'));
    }

    /**
     * Lấy Creator theo ID trong organization
     */
    public function getCreatorById(string $id, ?string $orgHex)
    {
        return $this->repository->getByIdInOrganization($id, $orgHex);
    }

    /**
     * Tìm Creator theo tên
     */
    public function searchCreatorByName(string $name, ?string $orgHex)
    {
        return $this->repository->searchByName($name, $orgHex);
    }

    /**
     * Chuẩn hóa tên trường từ header CSV sang tên trường trong DB
     */
    private function normalizeFieldName(string $header): string
    {
        $normalized = strtolower(trim($header));
        // Loại bỏ dấu tiếng Việt để chuẩn hóa header
        $normalized = strtr($normalized, [
            'à' => 'a', 'á' => 'a', 'ạ' => 'a', 'ả' => 'a', 'ã' => 'a',
            'â' => 'a', 'ầ' => 'a', 'ấ' => 'a', 'ậ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a',
            'ă' => 'a', 'ằ' => 'a', 'ắ' => 'a', 'ặ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a',
            'è' => 'e', 'é' => 'e', 'ẹ' => 'e', 'ẻ' => 'e', 'ẽ' => 'e',
            'ê' => 'e', 'ề' => 'e', 'ế' => 'e', 'ệ' => 'e', 'ể' => 'e', 'ễ' => 'e',
            'ì' => 'i', 'í' => 'i', 'ị' => 'i', 'ỉ' => 'i', 'ĩ' => 'i',
            'ò' => 'o', 'ó' => 'o', 'ọ' => 'o', 'ỏ' => 'o', 'õ' => 'o',
            'ô' => 'o', 'ồ' => 'o', 'ố' => 'o', 'ộ' => 'o', 'ổ' => 'o', 'ỗ' => 'o',
            'ơ' => 'o', 'ờ' => 'o', 'ớ' => 'o', 'ợ' => 'o', 'ở' => 'o', 'ỡ' => 'o',
            'ù' => 'u', 'ú' => 'u', 'ụ' => 'u', 'ủ' => 'u', 'ũ' => 'u',
            'ư' => 'u', 'ừ' => 'u', 'ứ' => 'u', 'ự' => 'u', 'ử' => 'u', 'ữ' => 'u',
            'ỳ' => 'y', 'ý' => 'y', 'ỵ' => 'y', 'ỷ' => 'y', 'ỹ' => 'y',
            'đ' => 'd',
        ]);
        $normalized = preg_replace('/[^a-z0-9]+/i', '_', $normalized);
        $normalized = preg_replace('/_+/', '_', $normalized);
        $normalized = trim($normalized, '_');

        $map = [
            'ten_creator' => 'creator_name',
            'ten_koc' => 'creator_name',
            'ten_kol' => 'creator_name',
            'ten' => 'creator_name',
            'creator' => 'creator_name',
            'creator_name' => 'creator_name',
            'koc_name' => 'creator_name',
            'kol' => 'creator_name',
            'name' => 'creator_name',
            'ten_kol_koc' => 'creator_name',
            'tiktok' => 'tiktok_link',
            'tiktok_url' => 'tiktok_link',
            'tiktok_link' => 'tiktok_link',
            'link_tiktok' => 'tiktok_link',
            'instagram' => 'instagram_link',
            'insta' => 'instagram_link',
            'instagram_url' => 'instagram_link',
            'link_instagram' => 'instagram_link',
            'facebook' => 'facebook_link',
            'fb' => 'facebook_link',
            'facebook_url' => 'facebook_link',
            'link_facebook' => 'facebook_link',
            'phone' => 'contact_phone',
            'sdt' => 'contact_phone',
            'dien_thoai' => 'contact_phone',
            'so_dien_thoai' => 'contact_phone',
            'email' => 'contact_email',
            'zalo' => 'contact_zalo',
            'ig' => 'instagram_link',
            'followers' => 'followers',
            'follower' => 'followers',
            'nguoi_theo_doi' => 'followers',
            'gmv' => 'gmv',
            'doanh_so' => 'gmv',
            'doanh_thu' => 'gmv',
            'items' => 'items',
            'so_san_pham' => 'items',
            'so_mon' => 'items',
            'so_mon_ban_ra' => 'items',
            'audience' => 'audience',
            'khan_gia' => 'audience',
            'doi_tuong' => 'audience',
            'doi_tuong_muc_tieu' => 'audience',
            'audience_segment' => 'audience',
            'target_audience' => 'audience',
            'tep_khach_hang' => 'audience',
            'tep_khach' => 'audience',
            'tep_kh' => 'audience',
            'tepkhachhang' => 'audience',
            'advantages' => 'advantages',
            'loi_the' => 'advantages',
            'address' => 'address',
            'dia_chi' => 'address',
            'content' => 'content',
            'noi_dung' => 'content',
            'loai_noi_dung' => 'content',
            'notes' => 'notes',
            'ghi_chu' => 'notes',
            'average_views' => 'average_views',
            'average_view' => 'average_views',
            'luot_xem_tb' => 'average_views',
            'luot_xem' => 'average_views',
            'view_tb' => 'average_views',
            'view_video_tb' => 'average_views',
            'view_video_trung_binh' => 'average_views',
            'video_view' => 'average_views',
            'video_views' => 'average_views',
            'luot_xem_trung_binh' => 'average_views',
            'view_trung_binh' => 'average_views',
            'view_video' => 'average_views',
            'views' => 'average_views',
            'tiktok_cid' => 'tiktok_cid',
            'cid' => 'tiktok_cid',
            'cid_tiktok' => 'tiktok_cid',
        ];

        return $map[$normalized] ?? $normalized;
    }

    /**
     * Parse giá trị số từ chuỗi (hỗ trợ định dạng như 1.5k, 5tr, 1,000,000)
     */
    private function parseNumericValue($value, ?string $field = null): int|float|null
    {
        $raw = trim((string)$value);
        if ($raw === '') return null;

        $s = mb_strtolower($raw, 'UTF-8');

        if (preg_match('/\b(freecast|free cast|free|mi[eê]n ?ph[ií])\b/u', $s)) {
            return -1;
        }

        // Tìm suffix (k, m, tr, triệu)
        $suffix = null;
        if (preg_match('/(k|k\b|m|tr|tri[uê]u|million)\b/u', $s, $ms)) {
            $suffix = $ms[1];
        }

        // Trích xuất phần số
        if (!preg_match('/([0-9\.,]+)/', $s, $m)) {
            return null;
        }
        $numStr = $m[1];

        // Chuẩn hóa dấu thập phân/phân cách hàng nghìn
        if (strpos($numStr, ',') !== false && strpos($numStr, '.') !== false) {
            $numStr = str_replace('.', '', $numStr);
            $numStr = str_replace(',', '.', $numStr);
        } elseif (strpos($numStr, ',') !== false) {
            if (substr_count($numStr, ',') === 1) {
                $parts = explode(',', $numStr);
                if (isset($parts[1]) && strlen($parts[1]) <= 2) {
                    $numStr = $parts[0] . '.' . $parts[1];
                } else {
                    $numStr = str_replace(',', '', $numStr);
                }
            } else {
                $numStr = str_replace(',', '', $numStr);
            }
        } elseif (strpos($numStr, '.') !== false) {
            if (substr_count($numStr, '.') === 1) {
                $parts = explode('.', $numStr);
                if (isset($parts[1]) && strlen($parts[1]) <= 2) {
                    $numStr = $parts[0] . '.' . $parts[1];
                } else {
                    $numStr = str_replace('.', '', $numStr);
                }
            } else {
                $numStr = str_replace('.', '', $numStr);
            }
        }

        $num = is_numeric($numStr) ? (float)$numStr : 0;

        // Áp dụng multiplier
        $mult = 1;
        if ($suffix) {
            if (stripos($suffix, 'k') !== false) $mult = 1000;
            elseif (stripos($suffix, 'tr') !== false || stripos($suffix, 'tri') !== false || stripos($suffix, 'm') !== false) $mult = 1000000;
            elseif (stripos($suffix, 'million') !== false) $mult = 1000000;
        }

        $result = round($num * $mult);
        
        if ($result < 0) {
            return null;
        }
        
        return $result;
    }

    /**
     * Đọc dữ liệu từ file CSV hoặc Excel
     * TỐI ƯU: Đọc CSV theo chunk (yield) thay vì load toàn bộ vào memory
     */
    private function readFileData($file): ?array
    {
        $extension = strtolower($file->getClientOriginalExtension());
        $rows = [];

        if (in_array($extension, ['xlsx', 'xls'])) {
            // Đọc file Excel sử dụng PhpSpreadsheet
            if (!class_exists(\PhpOffice\PhpSpreadsheet\IOFactory::class)) {
                throw new \Exception('PhpSpreadsheet not found. Vui lòng chạy: composer require phpoffice/phpspreadsheet');
            }

            try {
                $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file->getRealPath());
                $sheet = $spreadsheet->getActiveSheet();
                $sheetData = $sheet->toArray(null, true, true, true);

                // Chuyển đổi từ dạng A,B,C sang indexed array và đảm bảo UTF-8
                foreach ($sheetData as $r) {
                    $row = [];
                    foreach ($r as $cell) {
                        if ($cell !== null) {
                            $cellStr = (string) $cell;
                            if (!mb_check_encoding($cellStr, 'UTF-8')) {
                                $encoding = mb_detect_encoding($cellStr, ['UTF-8', 'Windows-1252', 'ISO-8859-1', 'ASCII'], true);
                                if ($encoding && $encoding !== 'UTF-8') {
                                    $cellStr = mb_convert_encoding($cellStr, 'UTF-8', $encoding);
                                }
                            }
                            $row[] = $cellStr;
                        } else {
                            $row[] = '';
                        }
                    }
                    $rows[] = $row;
                }
            } catch (\Throwable $e) {
                throw new \Exception('Không thể đọc file Excel: ' . $e->getMessage());
            }
        } else {
            // Đọc file CSV/TXT - dùng fgetcsv để xử lý đúng chuẩn CSV
            $handle = fopen($file->getRealPath(), 'r');
            if ($handle === false) {
                throw new \Exception('Không thể đọc file');
            }

            // Đọc header dòng đầu tiên
            $headers = fgetcsv($handle);
            if ($headers === false || $headers === null) {
                fclose($handle);
                throw new \Exception('File không có dữ liệu');
            }

            // Chuẩn hóa encoding cho header, loại bỏ BOM nếu có
            $headers = array_map(function ($h) {
                // Loại bỏ BOM UTF-8 (\xEF\xBB\xBF)
                if (strlen($h) > 0 && ord($h[0]) === 0xEF) {
                    $h = preg_replace('/^\xEF\xBB\xBF/', '', $h);
                }
                if (!mb_check_encoding($h, 'UTF-8')) {
                    $encoding = mb_detect_encoding($h, ['UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-16BE', 'Windows-1252', 'ISO-8859-1', 'ASCII'], true);
                    if ($encoding && $encoding !== 'UTF-8') {
                        $h = mb_convert_encoding($h, 'UTF-8', $encoding);
                    }
                }
                return trim($h);
            }, $headers);

            // Đọc từng dòng bằng fgetcsv (xử lý quoted fields, escape tự động)
            $maxCols = count($headers);
            while (($row = fgetcsv($handle)) !== false) {
                // Padding row thiếu cột để khớp với số header
                $rowCount = count($row);
                if ($rowCount < $maxCols) {
                    $row = array_pad($row, $maxCols, '');
                }
                // Bỏ qua dòng toàn rỗng
                $allEmpty = true;
                foreach ($row as $v) {
                    if (trim((string)$v) !== '') {
                        $allEmpty = false;
                        break;
                    }
                }
                if ($allEmpty) continue;
                // Chuẩn hóa encoding cho từng giá trị trong row
                $row = array_map(function ($v) {
                    if (!mb_check_encoding((string)$v, 'UTF-8')) {
                        $encoding = mb_detect_encoding((string)$v, ['UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-16BE', 'Windows-1252', 'ISO-8859-1', 'ASCII'], true);
                        if ($encoding && $encoding !== 'UTF-8') {
                            $v = mb_convert_encoding((string)$v, 'UTF-8', $encoding);
                        }
                    }
                    return trim((string)$v);
                }, $row);
                $rows[] = $row;
            }
            fclose($handle);

            if (empty($rows)) {
                throw new \Exception('File không có dữ liệu');
            }

            return ['headers' => $headers, 'rows' => $rows];
        }

        if (count($rows) < 1) {
            return null;
        }

        $headers = array_shift($rows);
        return ['headers' => $headers, 'rows' => $rows];
    }

    /**
     * Import creators từ file CSV hoặc Excel
     * 
     * TỐI ƯU:
     * - Batch insert thay vì 1 query / 1 row
     * - Chunk rows thay vì insert tất cả cùng lúc
     * - Transaction cho mỗi chunk
     * - Clear metrics cache sau khi import
     */
    public function importFromCsv($file, ?string $orgHex, $userId): array
    {
        $extension = strtolower($file->getClientOriginalExtension());
        if (!in_array($extension, ['csv', 'txt', 'xlsx', 'xls'])) {
            return StringHelper::sanitizeUtf8(['error' => 'Chỉ hỗ trợ file CSV, TXT hoặc Excel (.xlsx, .xls)']);
        }

        $orgBin = IdFormatter::hexToBinary($orgHex);

        try {
            $fileData = $this->readFileData($file);
            if (!$fileData) {
                return StringHelper::sanitizeUtf8(['error' => 'File không có dữ liệu hoặc định dạng không đúng']);
            }
        } catch (\Exception $e) {
            return StringHelper::sanitizeUtf8(['error' => $e->getMessage()]);
        }

        $headers = array_map([$this, 'normalizeFieldName'], array_map('trim', $fileData['headers']));
        $rows = $fileData['rows'];
        $numericFields = ['followers', 'gmv', 'items', 'average_views'];

        // Validate headers có creator_name không
        if (!in_array('creator_name', $headers)) {
            return StringHelper::sanitizeUtf8(['error' => 'File CSV phải có cột "Tên KOC" hoặc "creator_name"']);
        }

        // Pre-load danh sách tên KOC đã tồn tại trong organization để kiểm tra nhanh
        $existingNames = $this->repository->getAllNamesByOrganization($orgHex);

        $inserted = 0;
        $errors = [];
        $batchRecords = [];
        $batchSize = 500;
        $seenNames = []; // Tên đã thấy trong file import để tránh trùng trong cùng file

        // Import từ dưới lên: rows cuối CSV (thường đầy đủ thông tin hơn) được insert trước
        // để hiển thị lên đầu listing (sắp xếp created_at desc)
        $rows = array_reverse($rows);

        foreach ($rows as $rowIndex => $row) {
            $originalRowNum = count($rows) - $rowIndex + 1;

            // Đảm bảo số cột trong row khớp với header
            $rowCount = count($row);
            $headerCount = count($headers);
            if ($rowCount < $headerCount) {
                $row = array_pad($row, $headerCount, '');
            } elseif ($rowCount > $headerCount) {
                $row = array_slice($row, 0, $headerCount);
            }

            // Kiểm tra row có empty hoàn toàn không
            $allEmpty = true;
            foreach ($row as $v) {
                if (trim((string)$v) !== '') {
                    $allEmpty = false;
                    break;
                }
            }
            if ($allEmpty) continue;

            $data = [];
            foreach ($headers as $index => $header) {
                if ($index >= count($row)) continue;
                $value = trim((string)$row[$index]);

                if (in_array($header, $numericFields)) {
                    $num = $this->parseNumericValue($value, $header);
                    if ($num === null) {
                        $data[$header] = 0;
                    } else {
                        $data[$header] = max(0, $num);
                    }
                } else {
                    $data[$header] = $value === '' ? null : $value;
                }
            }

            if (empty($data['creator_name'])) {
                continue;
            }

            // Kiểm tra tên trùng trong organization
            $nameLower = mb_strtolower(trim($data['creator_name']), 'UTF-8');
            if (in_array($nameLower, $existingNames)) {
                $errors[] = 'Dòng ' . $originalRowNum . ': Tên "' . $data['creator_name'] . '" đã tồn tại trong hệ thống';
                continue;
            }

            // Kiểm tra tên trùng trong cùng file import
            if (in_array($nameLower, $seenNames)) {
                $errors[] = 'Dòng ' . $originalRowNum . ': Tên "' . $data['creator_name'] . '" bị trùng trong file import';
                continue;
            }
            $seenNames[] = $nameLower;

            $data['id'] = Uuid::uuid7Binary();
            $data['created_by_id'] = $userId;
            if ($orgBin) {
                $data['organization_id'] = $orgBin;
            }

            $batchRecords[] = $data;

            // Batch insert khi đủ batchSize
            if (count($batchRecords) >= $batchSize) {
                try {
                    $inserted += $this->repository->batchInsert($batchRecords);
                } catch (\Exception $e) {
                    $errors[] = 'Batch ' . (count($errors) + 1) . ': ' . $e->getMessage();
                    // Thử insert từng record trong batch để biết record nào lỗi
                    foreach ($batchRecords as $rec) {
                        try {
                            $this->repository->create($rec);
                            $inserted++;
                        } catch (\Exception $e2) {
                            $errors[] = ($rec['creator_name'] ?? 'Unknown') . ': ' . $e2->getMessage();
                        }
                    }
                }
                $batchRecords = [];
            }
        }

        // Insert records còn lại
        if (!empty($batchRecords)) {
            try {
                $inserted += $this->repository->batchInsert($batchRecords);
            } catch (\Exception $e) {
                foreach ($batchRecords as $rec) {
                    try {
                        $this->repository->create($rec);
                        $inserted++;
                    } catch (\Exception $e2) {
                        $errors[] = ($rec['creator_name'] ?? 'Unknown') . ': ' . $e2->getMessage();
                    }
                }
            }
        }

        // Clear metrics cache sau khi import
        $this->clearMetricsCache($orgHex);

        $result = StringHelper::sanitizeUtf8([
            'inserted' => $inserted,
            'errors' => $errors,
        ]);

        $details = 'Nhập CSV KOC: ' . $inserted . ' thành công';
        if (count($errors) > 0) {
            $details .= ', ' . count($errors) . ' lỗi';
        }
        AuditLog::log('import_csv_koc', 'koc', null, 'Nhập CSV', $details, AuditLog::detectTabFromReferer('koc'));

        return $result;
    }

    /**
     * Bulk update creators từ file CSV hoặc Excel
     * 
     * TỐI ƯU:
     * - Chunk reading
     * - Clear metrics cache sau khi update
     */
    public function bulkUpdateFromCsv($file, ?string $orgHex): array
    {
        $extension = strtolower($file->getClientOriginalExtension());
        if (!in_array($extension, ['csv', 'txt', 'xlsx', 'xls'])) {
            return StringHelper::sanitizeUtf8(['error' => 'Chỉ hỗ trợ file CSV, TXT hoặc Excel (.xlsx, .xls)']);
        }

        try {
            $fileData = $this->readFileData($file);
            if (!$fileData) {
                return StringHelper::sanitizeUtf8(['error' => 'File không có dữ liệu hoặc định dạng không đúng']);
            }
        } catch (\Exception $e) {
            return StringHelper::sanitizeUtf8(['error' => $e->getMessage()]);
        }

        $headers = array_map([$this, 'normalizeFieldName'], array_map('trim', $fileData['headers']));
        $rows = $fileData['rows'];
        $numericFields = ['followers', 'gmv', 'items', 'average_views'];

        if (!in_array('creator_name', $headers)) {
            return StringHelper::sanitizeUtf8(['error' => 'CSV phải có cột ten_koc hoặc creator_name để tìm kiếm']);
        }

        $updated = 0;
        $errors = [];
        $notFound = [];

        // Cache các creator đã tìm thấy theo tên để tránh query duplicate
        $creatorCache = [];

        foreach ($rows as $row) {
            // Đảm bảo số cột trong row khớp với header
            $rowCount = count($row);
            $headerCount = count($headers);
            if ($rowCount < $headerCount) {
                $row = array_pad($row, $headerCount, '');
            } elseif ($rowCount > $headerCount) {
                $row = array_slice($row, 0, $headerCount);
            }

            $allEmpty = true;
            foreach ($row as $v) {
                if (trim((string)$v) !== '') {
                    $allEmpty = false;
                    break;
                }
            }
            if ($allEmpty) continue;

            $data = [];
            $creatorName = '';
            foreach ($headers as $index => $header) {
                if ($index >= count($row)) continue;
                $value = trim((string)$row[$index]);
                if ($value === '') continue;

                if ($header === 'creator_name') {
                    $creatorName = $value;
                } else {
                    if (in_array($header, $numericFields)) {
                        $num = $this->parseNumericValue($value, $header);
                        $data[$header] = $num === null ? null : $num;
                    } else {
                        $data[$header] = $value;
                    }
                }
            }

            if (empty($creatorName)) {
                continue;
            }

            // Kiểm tra cache trước khi query DB
            if (!isset($creatorCache[$creatorName])) {
                $creator = $this->repository->searchByName($creatorName, $orgHex)->first();
                $creatorCache[$creatorName] = $creator;
            } else {
                $creator = $creatorCache[$creatorName];
            }

            if (!$creator) {
                $notFound[] = $creatorName;
                continue;
            }

            try {
                $this->repository->updateInOrganization($creator->hex_id, $data, $orgHex);
                $updated++;
            } catch (\Exception $e) {
                $errors[] = $creatorName . ': ' . $e->getMessage();
            }
        }

        // Clear metrics cache sau bulk update
        $this->clearMetricsCache($orgHex);

        $result = StringHelper::sanitizeUtf8([
            'updated' => $updated,
            'not_found' => $notFound,
            'errors' => $errors,
        ]);

        $details = 'Cập nhật hàng loạt KOC: ' . $updated . ' thành công';
        if (count($notFound) > 0) {
            $details .= ', ' . count($notFound) . ' không tìm thấy';
        }
        if (count($errors) > 0) {
            $details .= ', ' . count($errors) . ' lỗi';
        }
        AuditLog::log('bulk_update_koc', 'koc', null, 'Cập nhật hàng loạt', $details, AuditLog::detectTabFromReferer('koc'));

        return $result;
    }
}