<?php

namespace App\Services;

use App\Enums\ImportDatasourceStatus;
use App\Models\BigdataResume;
use App\Models\GlobalSetting;
use App\Models\ImportDatasource;
use App\Models\PbgTaskIndexIntegrations;
use App\Models\PbgTaskPrasarana;
use App\Models\PbgTaskRetributions;
use App\Models\TaskAssignment;
use Exception;
use App\Models\PbgTask;
use App\Traits\GlobalApiResponse;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use App\Services\ServiceClient;
use App\Services\GoogleSheetService;
use App\Models\DataSetting;
use App\Models\PbgTaskGoogleSheet;

class ServiceSIMBG
{
    use GlobalApiResponse;
    private $email;
    private $password;
    private $simbg_host;
    private $fetch_per_page;
    private $service_client;
    private $googleSheetService;
    /**
     * Create a new class instance.
     */
    public function __construct(GoogleSheetService $googleSheetService)
    {
        $settings = GlobalSetting::whereIn('key', [
            'SIMBG_EMAIL', 'SIMBG_PASSWORD', 'SIMBG_HOST', 'FETCH_PER_PAGE'
        ])->pluck('value', 'key');
    
        $this->email = trim((string) ($settings['SIMBG_EMAIL'] ?? ""));
        $this->password = trim((string) ($settings['SIMBG_PASSWORD'] ?? ""));
        $this->simbg_host = trim((string) ($settings['SIMBG_HOST'] ?? ""));
        $this->fetch_per_page = trim((string) ($settings['FETCH_PER_PAGE'] ?? ""));
    
        $this->service_client = new ServiceClient($this->simbg_host);
        $this->googleSheetService = $googleSheetService;
    }

    public function getToken(){
        try{
            $url = "/api/user/v1/auth/login/";
            $body = [
                'email' => $this->email,
                'password' => $this->password,
            ];
            
            $res = $this->service_client->post($url, $body);
            if(!$res->original['success']){
                Log::error("Token not retrieved ", ['response' => $res]);
                throw new Exception("Token not retrieved.");
            }
            return $res;
        }catch(Exception $e){
            Log::error("Error on method get token ", ['response' => $e->getMessage()]);
            throw $e;
        }
    }

    public function syncIndexIntegration($uuids)
    {
        try{
            if(empty($uuids)){
                return false;
            }

            $initResToken = $this->getToken();
            if (empty($initResToken->original['data']['token']['access'])) {
                Log::error("API response indicates failure", ['token' => 'Failed to retrieve token']);
                return false;
            }
            $token = $initResToken->original['data']['token']['access'];
            
            $integrations = [];
            foreach($uuids as $uuid){
                $url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
        
                $headers = [
                    'Authorization' => "Bearer " . $token,
                ];
            
                $res = $this->service_client->get($url, $headers);
            
                if (empty($res->original['success']) || !$res->original['success']) {
                    // Log error
                    Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
                    continue;
                }
            
                $data = $res->original['data']['data'] ?? null;
                if (!$data) {
                    Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
                    continue;
                }

                $integrations[] = [
                    'pbg_task_uid' => $uuid,
                    'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
                    'indeks_parameter_kompleksitas' => $data['indeks_parameter_kompleksitas'] ?? null,
                    'indeks_parameter_permanensi' => $data['indeks_parameter_permanensi'] ?? null,
                    'indeks_parameter_ketinggian' => $data['indeks_parameter_ketinggian'] ?? null,
                    'faktor_kepemilikan' => $data['faktor_kepemilikan'] ?? null,
                    'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null,
                    'total' => $data['total'] ?? null,
                ];
            }

            PbgTaskIndexIntegrations::upsert($integrations, ['pbg_task_uid'], ['indeks_fungsi_bangunan', 
            'indeks_parameter_kompleksitas', 'indeks_parameter_permanensi', 'indeks_parameter_ketinggian', 'faktor_kepemilikan', 'indeks_terintegrasi', 'total']);
            
            return true;
        }catch (Exception $e){
            Log::error('error when sync index integration ', ['index integration'=> $e->getMessage()]);
            throw $e;
        }
    }

    public function syncTaskPBG()
    {
        try {
            Log::info("Processing google sheet sync");
            $importDatasource = ImportDatasource::create([
                'status' => ImportDatasourceStatus::Processing->value,
            ]);

            // sync google sheet first
            $totalRowCount = $this->googleSheetService->getLastRowByColumn("C");
            $sheetData = $this->googleSheetService->getSheetDataCollection($totalRowCount);
            $sheet_big_data = $this->googleSheetService->get_data_by_sheet();
            $data_setting_result = []; // Initialize result storage
        
            $found_section = null; // Track which section is found
        
            foreach ($sheet_big_data as $row) {
                // Check for section headers
                if (in_array("•PROSES PENERBITAN:", $row)) {
                    $found_section = "MENUNGGU_KLIK_DPMPTSP";
                } elseif (in_array("•BERKAS AKTUAL TERVERIFIKASI DINAS TEKNIS 2024:", $row)) {
                    $found_section = "REALISASI_TERBIT_PBG";
                } elseif (in_array("•TERPROSES DI DPUTR: belum selesai rekomtek'", $row)) {
                    $found_section = "PROSES_DINAS_TEKNIS";
                }
        
                // If a section is found and we reach "Grand Total", save the corresponding values
                if ($found_section && isset($row[0]) && trim($row[0]) === "Grand Total") {
                    if ($found_section === "MENUNGGU_KLIK_DPMPTSP") {
                        $data_setting_result["MENUNGGU_KLIK_DPMPTSP_COUNT"] = $this->convertToInteger($row[2]) ?? null;
                        $data_setting_result["MENUNGGU_KLIK_DPMPTSP_SUM"] = $this->convertToDecimal($row[3])  ?? null;
                    } elseif ($found_section === "REALISASI_TERBIT_PBG") {
                        $data_setting_result["REALISASI_TERBIT_PBG_COUNT"] = $this->convertToInteger($row[2]) ?? null;
                        $data_setting_result["REALISASI_TERBIT_PBG_SUM"] = $this->convertToDecimal($row[4]) ?? null;
                    } elseif ($found_section === "PROSES_DINAS_TEKNIS") {
                        $data_setting_result["PROSES_DINAS_TEKNIS_COUNT"] = $this->convertToInteger($row[2]) ?? null;
                        $data_setting_result["PROSES_DINAS_TEKNIS_SUM"] = $this->convertToDecimal($row[3]) ?? null;
                    }
        
                    // Reset section tracking after capturing "Grand Total"
                    $found_section = null;
                }
            }

            Log::info("data setting result", ['result' => $data_setting_result]);

            foreach ($data_setting_result as $key => $value) {
                DataSetting::updateOrInsert(
                    ["key" => $key], // Find by key
                    ["value" => $value] // Update or insert value
                );
            }
            $mapToUpsert = [];

            foreach($sheetData as $data){
                $mapToUpsert[] = 
                    [
                        'no_registrasi' => $data['no__registrasi'] ?? null,
                        'jenis_konsultasi' => $data['jenis_konsultasi'] ?? null,
                        'fungsi_bg' => $data['fungsi_bg'] ?? null,
                        'tgl_permohonan' => $this->convertToDate($data['tgl_permohonan']),
                        'status_verifikasi' => $data['status_verifikasi'] ?? null,
                        'status_permohonan' => $this->convertToDate($data['status_permohonan']),
                        'alamat_pemilik' => $data['alamat_pemilik'] ?? null,
                        'no_hp' => $data['no__hp'] ?? null,
                        'email' => $data['e_mail'] ?? null,
                        'tanggal_catatan' => $this->convertToDate($data['tanggal_catatan']),
                        'catatan_kekurangan_dokumen' => $data['catatan_kekurangan_dokumen'] ?? null,
                        'gambar' => $data['gambar'] ?? null,
                        'krk_kkpr' => $data['krk_kkpr'] ?? null,
                        'no_krk' => $data['no__krk'] ?? null,
                        'lh' => $data['lh'] ?? null,
                        'ska' => $data['ska'] ?? null,
                        'keterangan' => $data['keterangan'] ?? null,
                        'helpdesk' => $data['helpdesk'] ?? null,
                        'pj' => $data['pj'] ?? null,
                        'kepemilikan' => $data['kepemilikan'] ?? null,
                        'potensi_taru' => $data['potensi_taru'] ?? null,
                        'validasi_dinas' => $data['validasi_dinas'] ?? null,
                        'kategori_retribusi' => $data['kategori_retribusi'] ?? null,
                        'no_urut_ba_tpt' => $data['no__urut_ba_tpt__2024_0001_'] ?? null,
                        'tanggal_ba_tpt' => $this->convertToDate($data['tanggal_ba_tpt']),
                        'no_urut_ba_tpa' => $data['no__urut_ba_tpa'] ?? null,
                        'tanggal_ba_tpa' => $this->convertToDate($data['tanggal_ba_tpa']),
                        'no_urut_skrd' => $data['no__urut_skrd__2024_0001_'] ?? null,
                        'tanggal_skrd' => $this->convertToDate($data['tanggal_skrd']),
                        'ptsp' => $data['ptsp'] ?? null,
                        'selesai_terbit' => $data['selesai_terbit'] ?? null,
                        'tanggal_pembayaran' => $this->convertToDate($data['tanggal_pembayaran__yyyy_mm_dd_']),
                        'format_sts' => $data['format_sts'] ?? null,
                        'tahun_terbit' => (int) $data['tahun_terbit'] ?? null,
                        'tahun_berjalan' => (int) $data['tahun_berjalan'] ?? null,
                        'kelurahan' => $data['kelurahan'] ?? null,
                        'kecamatan' => $data['kecamatan'] ?? null,
                        'lb' => $this->convertToDecimal($data['lb'])  ?? null,
                        'tb' => $this->convertToDecimal($data['tb']) ?? null,
                        'jlb' => (int) $data['jlb'] ?? null,
                        'unit' => (int) $data['unit'] ?? null,
                        'usulan_retribusi' => (int) $data['usulan_retribusi'] ?? null,
                        'nilai_retribusi_keseluruhan_simbg' => $this->convertToDecimal($data['nilai_retribusi_keseluruhan__simbg_']) ?? null,
                        'nilai_retribusi_keseluruhan_pad' => $this->convertToDecimal($data['nilai_retribusi_keseluruhan__pad_']) ?? null,
                        'denda' => $this->convertToDecimal($data['denda']) ?? null,
                        'latitude' => $data['latitude'] ?? null,
                        'longitude' => $data['longitude'] ?? null,
                        'nik_nib' => $data['nik_nib'] ?? null,
                        'dok_tanah' => $data['dok__tanah'] ?? null,
                        'temuan' => $data['temuan'] ?? null,
                    ];
            }

            $batchSize = 1000;
            $chunks = array_chunk($mapToUpsert, $batchSize);

            foreach($chunks as $chunk){
                PbgTaskGoogleSheet::upsert($chunk, ["no_registrasi"],[
                    'jenis_konsultasi',
                    'nama_pemilik',
                    'lokasi_bg',
                    'fungsi_bg',
                    'nama_bangunan',
                    'tgl_permohonan',
                    'status_verifikasi',
                    'status_permohonan',
                    'alamat_pemilik',
                    'no_hp',
                    'email',
                    'tanggal_catatan',
                    'catatan_kekurangan_dokumen',
                    'gambar',
                    'krk_kkpr',
                    'no_krk',
                    'lh',
                    'ska',
                    'keterangan',
                    'helpdesk',
                    'pj',
                    'kepemilikan',
                    'potensi_taru',
                    'validasi_dinas',
                    'kategori_retribusi',
                    'no_urut_ba_tpt',
                    'tanggal_ba_tpt',
                    'no_urut_ba_tpa',
                    'tanggal_ba_tpa',
                    'no_urut_skrd',
                    'tanggal_skrd',
                    'ptsp',
                    'selesai_terbit',
                    'tanggal_pembayaran',
                    'format_sts',
                    'tahun_terbit',
                    'tahun_berjalan',
                    'kelurahan',
                    'kecamatan',
                    'lb',
                    'tb',
                    'jlb',
                    'unit',
                    'usulan_retribusi',
                    'nilai_retribusi_keseluruhan_simbg',
                    'nilai_retribusi_keseluruhan_pad',
                    'denda',
                    'latitude',
                    'longitude',
                    'nik_nib',
                    'dok_tanah',
                    'temuan',
                ]);
            }
            
            $initResToken = $this->getToken();
            if (empty($initResToken->original['data']['token']['access'])) {
                $importDatasource->update([
                    'status' => ImportDatasourceStatus::Failed->value,
                    'response_body' => 'Failed to retrieve token'
                ]);
                return $this->resError("Failed to retrieve token");
            }
            $apiToken = $initResToken->original['data']['token']['access'];
            $headers = ['Authorization' => "Bearer " . $apiToken];

            $url = "/api/pbg/v1/list/?page=1&size={$this->fetch_per_page}&sort=ASC";
            $initialResponse = $this->service_client->get($url, $headers);

            $totalPage = $initialResponse->original['data']['total_page'] ?? 0;
            if ($totalPage == 0) {
                $importDatasource->update([
                    'status' => ImportDatasourceStatus::Failed->value,
                    'response_body' => 'Invalid response: no total_page'
                ]);
                return $this->resError("Invalid response from API");
            }

            $savedCount = $failedCount = 0;

            Log::info("Fetching tasks", ['total page' => $totalPage]);

            for ($currentPage = 1; $currentPage <= $totalPage; $currentPage++) {
                try {
                    $pageUrl = "/api/pbg/v1/list/?page={$currentPage}&size={$this->fetch_per_page}&sort=ASC";

                    Log::info("Fetching tasks", ['currentPage' => $currentPage]);
                    $headers = [
                        'Authorization' => "Bearer " . $apiToken, // Update headers
                    ];

                    for ($attempt = 0; $attempt < 2; $attempt++) { // Try twice (original + retry)

                        $response = $this->service_client->get($pageUrl, $headers);

                        if ($response instanceof \Illuminate\Http\JsonResponse) {
                            $decodedResponse = json_decode($response->getContent(), true);

                            if (isset($decodedResponse['errors']['code']) && $decodedResponse['errors']['code'] === 'token_not_valid') {
                                $initResToken = $this->getToken();

                                if (!empty($initResToken->original['data']['token']['access'])) {
                                    $new_token = $initResToken->original['data']['token']['access'];
                                    $headers['Authorization'] = "Bearer " . $new_token;
                                    continue;
                                } else {
                                    Log::error("Failed to refresh token");
                                    return $this->resError("Failed to refresh token");
                                }
                            }
                        }

                        // Success case, break loop
                        break;
                    }

                    $tasks = $response->original['data']['data'] ?? [];

                    if (empty($tasks)) {
                        Log::warning("No data found on page", ['page' => $currentPage]);
                        continue;
                    }

                    $tasksCollective = [];
                    foreach ($tasks as $item) {
                        try {
                            $tasksCollective[] = [
                                'uuid' => $item['uid'],
                                'name' => $item['name'],
                                'owner_name' => $item['owner_name'],
                                'application_type' => $item['application_type'],
                                'application_type_name' => $item['application_type_name'],
                                'condition' => $item['condition'],
                                'registration_number' => $item['registration_number'],
                                'document_number' => $item['document_number'],
                                'address' => $item['address'],
                                'status' => $item['status'],
                                'status_name' => $item['status_name'],
                                'slf_status' => $item['slf_status'] ?? null,
                                'slf_status_name' => $item['slf_status_name'] ?? null,
                                'function_type' => $item['function_type'],
                                'consultation_type' => $item['consultation_type'],
                                'due_date' => $item['due_date'],
                                'land_certificate_phase' => $item['land_certificate_phase'],
                                'task_created_at' => isset($item['created_at']) ? Carbon::parse($item['created_at'])->format('Y-m-d H:i:s') : null,
                                'updated_at' => now(),
                                'created_at' => now(),
                            ];

                            $this->syncTaskDetailSubmit($item['uid'], $apiToken);
                            $this->syncTaskAssignments($item['uid']);
                            $savedCount++;
                        } catch (Exception $e) {
                            $failedCount++;
                            Log::error("Failed to process task", [
                                'error' => $e->getMessage(),
                                'task' => $item,
                            ]);
                            continue; // Skip failed task, continue processing the rest
                        }
                    }

                    if (!empty($tasksCollective)) {
                        PbgTask::upsert($tasksCollective, ['uuid'], [
                            'name', 'owner_name', 'application_type', 'application_type_name', 'condition',
                            'registration_number', 'document_number', 'address', 'status', 'status_name',
                            'slf_status', 'slf_status_name', 'function_type', 'consultation_type', 'due_date',
                            'land_certificate_phase', 'task_created_at', 'updated_at'
                        ]);

                        $uuids = array_column($tasksCollective, 'uuid');
                        $this->syncIndexIntegration($uuids);
                    }
                } catch (Exception $e) {
                    Log::error("Failed to process page", [
                        'error' => $e->getMessage(),
                        'page' => $currentPage,
                    ]);
                    continue; // Skip the failed page and move to the next
                }
            }

            BigdataResume::generateResumeData($importDatasource->id, "all", $data_setting_result);
            BigdataResume::generateResumeData($importDatasource->id, now()->year, $data_setting_result);

            // Final update after processing all pages
            $importDatasource->update([
                'status' => ImportDatasourceStatus::Success->value,
                'message' => "Successfully processed: $savedCount, Failed: $failedCount"
            ]);
            
            Log::info("syncTaskList completed", ['savedCount' => $savedCount, 'failedCount' => $failedCount]);

            return $this->resSuccess(['savedCount' => $savedCount, 'failedCount' => $failedCount]);

        } catch (Exception $e) {
            Log::error("syncTaskList failed", ['error' => $e->getMessage()]);
            if (isset($importDatasource)) {
                $importDatasource->update([
                    'status' => ImportDatasourceStatus::Failed->value,
                    'response_body' => 'Critical failure: ' . $e->getMessage()
                ]);
            }
            return $this->resError("Critical failure occurred: " . $e->getMessage());
        }
    }

    public function syncTaskDetailSubmit($uuid, $token)
    {
        try{
            $url = "/api/pbg/v1/detail/" . $uuid . "/retribution/submit/";

            $headers = [
                'Authorization' => "Bearer " . $token,
            ];

            for ($attempt = 0; $attempt < 2; $attempt++) { 
                $res = $this->service_client->get($url, $headers);

                // Check if response is JsonResponse and decode it
                if ($res instanceof \Illuminate\Http\JsonResponse) {
                    $decodedResponse = json_decode($res->getContent(), true);

                    if (isset($decodedResponse['errors']['code']) && $decodedResponse['errors']['code'] === 'token_not_valid') {
                        $initResToken = $this->getToken();

                        if (!empty($initResToken->original['data']['token']['access'])) {
                            $new_token = $initResToken->original['data']['token']['access'];

                            $headers['Authorization'] = "Bearer " . $new_token;
                            continue; 
                        } else {
                            Log::error("Failed to refresh token");
                            return $this->resError("Failed to refresh token");
                        }
                    }
                }

                break;
            }

            // Ensure response is valid before accessing properties
            $responseData = $res->original ?? [];
            $data = $responseData['data']['data'] ?? [];
            if (empty($data)) {
                return false;
            }
    
            $detailCreatedAt = isset($data['created_at']) 
            ? Carbon::parse($data['created_at'])->format('Y-m-d H:i:s') 
            : null;
    
            $detailUpdatedAt = isset($data['updated_at']) 
            ? Carbon::parse($data['updated_at'])->format('Y-m-d H:i:s') 
            : null;
    
            $pbg_task_retributions = PbgTaskRetributions::updateOrCreate(
                ['detail_id' => $data['id']],
                [
                    'detail_uid' => $data['uid'] ?? null,
                    'detail_created_at' => $detailCreatedAt ?? null,
                    'detail_updated_at' => $detailUpdatedAt ?? null,
                    'luas_bangunan' => $data['luas_bangunan'] ?? null,
                    'indeks_lokalitas' => $data['indeks_lokalitas'] ?? null,
                    'wilayah_shst' => $data['wilayah_shst'] ?? null,
                    'kegiatan_id' => $data['kegiatan']['id'] ?? null,
                    'kegiatan_name' => $data['kegiatan']['name'] ?? null,
                    'nilai_shst' => $data['nilai_shst'] ?? null,
                    'indeks_terintegrasi' => $data['indeks_terintegrasi'] ?? null,
                    'indeks_bg_terbangun' => $data['indeks_bg_terbangun'] ?? null,
                    'nilai_retribusi_bangunan' => $data['nilai_retribusi_bangunan'] ?? null,
                    'nilai_prasarana' => $data['nilai_prasarana'] ?? null,
                    'created_by' => $data['created_by'] ?? null,
                    'pbg_document' => $data['pbg_document'] ?? null,
                    'underpayment' => $data['underpayment'] ?? null,
                    'skrd_amount' => $data['skrd_amount'] ?? null,
                    'pbg_task_uid' => $uuid,
                ]
            );
    
            $pbg_task_retribution_id = $pbg_task_retributions->id;
    
            $prasaranaData = $data['prasarana'] ?? [];
            if (!empty($prasaranaData)) {
                $insertData = array_map(fn($item) => [
                    'pbg_task_uid' => $uuid,
                    'pbg_task_retribution_id' => $pbg_task_retribution_id,
                    'prasarana_id' => $item['id'] ?? null,
                    'prasarana_type' => $item['prasarana_type'] ?? null,
                    'building_type' => $item['building_type'] ?? null,
                    'total' => $item['total'] ?? null,
                    'quantity' => $item['quantity'] ?? null,
                    'unit' => $item['unit'] ?? null,
                    'index_prasarana' => $item['index_prasarana'] ?? null,
                ], $prasaranaData);
        
                // Use bulk insert or upsert for faster database operation
                PbgTaskPrasarana::upsert($insertData, ['prasarana_id']);
            }
            return true;

        }catch(Exception $e){
            Log::error("Failed to sync task detail submit", ['error' => $e->getMessage(), 'uuid' => $uuid]);
            throw $e;
        }
    }

    public function syncTaskAssignments($uuid){
        try{
            $init_token = $this->getToken();
            $token = $init_token->original['data']['token']['access'];
            $url = "/api/pbg/v1/list-tim-penilai/". $uuid . "/?page=1&size=10";
            $headers = [
                'Authorization' => "Bearer " . $token,
            ];

            $response = $this->service_client->get($url, $headers);
            $datas = $response->original['data']['data'] ?? [];
            if(empty($datas)){
                return false;
            }
            $task_assignments = [];

            foreach ($datas as $data) {
                $task_assignments[] = [
                    'pbg_task_uid' => $uuid,
                    'user_id' => $data['user_id'],
                    'name' => $data['name'],
                    'username' => $data['username'],
                    'email' => $data['email'],
                    'phone_number' => $data['phone_number'],
                    'role' => $data['role'],
                    'role_name' => $data['role_name'],
                    'is_active' => $data['is_active'],
                    'file' => !empty($data['file']) ? json_encode($data['file']) : null, 
                    'expertise' => !empty($data['expertise']) ? json_encode($data['expertise']) : null,
                    'experience' => !empty($data['experience']) ? json_encode($data['experience']) : null,
                    'is_verif' => $data['is_verif'],
                    'uid' => $data['uid'],
                    'status' => $data['status'],
                    'status_name' => $data['status_name'],
                    'note' => $data['note'],
                    'ta_id' => $data['id'],
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
            TaskAssignment::upsert(
                $task_assignments,
                ['uid'], 
                ['ta_id','name', 'username', 'email', 'phone_number', 'role', 'role_name', 'is_active', 'file', 'expertise', 'experience', 'is_verif', 'status', 'status_name', 'note', 'updated_at']
            );
            return true;
        }catch(Exception $e){
            Log::error("Failed to sync task assignments", ['error' => $e->getMessage()]);
            throw $e;
        }
    }

    protected function convertToDecimal(?string $value): ?float
    {
        if (empty($value)) {
            return null; // Return null if the input is empty
        }

        // Remove all non-numeric characters except comma and dot
        $value = preg_replace('/[^0-9,\.]/', '', $value);

        // If the number contains both dot (.) and comma (,)
        if (strpos($value, '.') !== false && strpos($value, ',') !== false) {
            $value = str_replace('.', '', $value); // Remove thousands separator
            $value = str_replace(',', '.', $value); // Convert decimal separator to dot
        }
        // If only a dot is present (assumed as thousands separator)
        elseif (strpos($value, '.') !== false) {
            $value = str_replace('.', '', $value); // Remove all dots (treat as thousands separators)
        }
        // If only a comma is present (assumed as decimal separator)
        elseif (strpos($value, ',') !== false) {
            $value = str_replace(',', '.', $value); // Convert comma to dot (decimal separator)
        }

        // Ensure the value is numeric before returning
        return is_numeric($value) ? (float) number_format((float) $value, 2, '.', '') : null;
    }

    protected function convertToInteger($value) {
        // Check if the value is an empty string, and return null if true
        if (trim($value) === "") {
            return null;
        }

        $cleaned = str_replace('.','', $value);

        // Otherwise, cast to integer
        return (int) $cleaned;
    }

    protected function convertToDate($dateString)
    {
        try {
            // Check if the string is empty
            if (empty($dateString)) {
                return null;
            }

            // Try to parse the date string
            $date = Carbon::parse($dateString);

            // Return the Carbon instance
            return $date->format('Y-m-d');
        } catch (Exception $e) {
            // Return null if an error occurs during parsing
            return null;
        }
    }
}