<?php

/*
|--------------------------------------------------------------------------
| OwnStore - Build your own online store
| Author: TakfeDev (MKJUEL)
| All Rights Reserved
|--------------------------------------------------------------------------
*/

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use App\Models\Setting;
use App\Models\Country;
use App\Models\State;
use App\Models\City;
use Inertia\Inertia;
use ZipArchive;

class GlobalizationController extends Controller
{
    public function index()
    {
        $dbPath = storage_path('app/ip2location/IP2LOCATION.BIN');
        $dbExists = File::exists($dbPath);
        
        $csvPath = storage_path('app/ip2location/records.csv');
        $csvExists = File::exists($csvPath);

        return Inertia::render('cp/Settings/Globalization/Index', [
            'databaseStatus' => [
                'exists' => $dbExists,
                'size' => $dbExists ? round(File::size($dbPath) / 1048576, 2) . ' MB' : 'Not Found',
                'last_updated' => $dbExists ? date('Y-m-d H:i:s', File::lastModified($dbPath)) : 'N/A'
            ],
            'csvStatus' => [
                'exists' => $csvExists,
                'size' => $csvExists ? round(File::size($csvPath) / 1048576, 2) . ' MB' : 'Not Found',
            ],
            'apiSettings' => [
                'token' => Setting::where('key', 'ip2location_token')->value('value') ?? '',
                'db_code' => Setting::where('key', 'ip2location_db_code')->value('value') ?? 'DB1LITEBIN',
            ]
        ]);
    }

    public function updateIpDatabase(Request $request)
    {
        $request->validate(['database_file' => 'required|file|max:512000']);
        $file = $request->file('database_file');
        
        if (!File::exists(storage_path('app/ip2location'))) {
            File::makeDirectory(storage_path('app/ip2location'), 0755, true);
        }
        $file->move(storage_path('app/ip2location'), 'IP2LOCATION.BIN');
        return back()->with('success', 'IP2Location BIN file uploaded successfully.');
    }

    public function downloadDatabase(Request $request)
    {
        $request->validate(['token' => 'required|string', 'db_code' => 'required|string']);
        Setting::updateOrCreate(['key' => 'ip2location_token'], ['value' => $request->token]);
        Setting::updateOrCreate(['key' => 'ip2location_db_code'], ['value' => $request->db_code]);

        $url = "https://www.ip2location.com/download?token={$request->token}&file={$request->db_code}";
        $tempZip = storage_path('app/ip2location/temp_bin.zip');

        try {
            set_time_limit(600);
            Http::timeout(600)->sink($tempZip)->get($url);

            $zip = new ZipArchive;
            if ($zip->open($tempZip) === TRUE) {
                $binFileName = null;
                for ($i = 0; $i < $zip->numFiles; $i++) {
                    if (str_ends_with(strtoupper($zip->getNameIndex($i)), '.BIN')) {
                        $binFileName = $zip->getNameIndex($i); break;
                    }
                }
                if ($binFileName) {
                    $zip->extractTo(storage_path('app/ip2location/'), [$binFileName]);
                    $zip->close();
                    File::move(storage_path("app/ip2location/{$binFileName}"), storage_path('app/ip2location/IP2LOCATION.BIN'));
                    File::delete($tempZip);
                    return back()->with('success', 'IP-Lookup BIN successfully synced!');
                }
            }
            File::delete($tempZip);
            return back()->withErrors(['error' => 'Could not extract valid BIN from ZIP.']);
        } catch (\Exception $e) {
            return back()->withErrors(['error' => 'Sync Error: ' . $e->getMessage()]);
        }
    }

    public function downloadCsv(Request $request)
    {
        $request->validate(['token' => 'required|string', 'db_code' => 'required|string']);
        Setting::updateOrCreate(['key' => 'ip2location_token'], ['value' => $request->token]);

        $url = "https://www.ip2location.com/download?token={$request->token}&file={$request->db_code}";
        $tempZip = storage_path('app/ip2location/temp_csv.zip');
        $csvPath = storage_path('app/ip2location/records.csv');

        if (!File::exists(storage_path('app/ip2location'))) {
            File::makeDirectory(storage_path('app/ip2location'), 0755, true);
        }

        try {
            set_time_limit(900); // 15 mins
            if (File::exists($csvPath)) File::delete($csvPath);

            Http::timeout(900)->sink($tempZip)->get($url);

            $zip = new ZipArchive;
            if ($zip->open($tempZip) === TRUE) {
                $csvFileName = null;
                for ($i = 0; $i < $zip->numFiles; $i++) {
                    if (str_ends_with(strtoupper($zip->getNameIndex($i)), '.CSV')) {
                        $csvFileName = $zip->getNameIndex($i); break;
                    }
                }
                if ($csvFileName) {
                    $zip->extractTo(storage_path('app/ip2location/'), [$csvFileName]);
                    File::move(storage_path("app/ip2location/{$csvFileName}"), $csvPath);
                    $zip->close();
                    File::delete($tempZip);
                    return back()->with('success', 'CSV file successfully downloaded to local server!');
                }
                $zip->close();
            }
            File::delete($tempZip);
            return back()->withErrors(['error' => 'Failed to extract CSV data.']);
        } catch (\Exception $e) {
            return back()->withErrors(['error' => 'Download failed: ' . $e->getMessage()]);
        }
    }

    public function importFromCsv(Request $request)
    {
        $request->validate([
            'import_strategy' => 'required|in:all_global_records,all_countries_only,specific_country_all,specific_country_states',
            'country_code' => 'required_if:import_strategy,specific_country_all,specific_country_states|nullable|string|size:2',
        ]);

        $strategy = $request->import_strategy;
        $targetCountry = strtoupper($request->country_code);
        $csvPath = storage_path('app/ip2location/records.csv');

        if (!File::exists($csvPath)) {
            return back()->withErrors(['error' => 'Local CSV file not found. Please download it first.']);
        }

        try {
            set_time_limit(0); 
            ini_set('memory_limit', '1024M');

            $handle = fopen($csvPath, "r");
            
            while (($row = fgetcsv($handle)) !== FALSE) {
                $countryIso  = $row[2] ?? null;
                $countryName = $row[3] ?? null;
                $regionName  = $row[4] ?? null;
                $cityName    = $row[5] ?? null;

                if (empty($countryIso) || $countryIso === '-' || empty($countryName) || $countryName === '-') {
                    continue;
                }

                // If specific country is targeted, skip all other countries
                if (in_array($strategy, ['specific_country_all', 'specific_country_states']) && $countryIso !== $targetCountry) {
                    continue;
                }

                // 1. Create or Get Country
                $country = Country::firstOrCreate(
                    ['iso2' => $countryIso],
                    ['name' => $countryName, 'is_active' => true]
                );

                // Option 2: Only All Country Names -> Stop here
                if ($strategy === 'all_countries_only') {
                    continue; 
                }

                if (empty($regionName) || $regionName === '-') {
                    continue;
                }

                // 2. Create or Get State
                $state = State::firstOrCreate(
                    ['country_id' => $country->id, 'name' => $regionName],
                    ['is_active' => true]
                );

                // Option 4: Specific Country + States Only -> Stop here
                if ($strategy === 'specific_country_states') {
                    continue; 
                }

                if (empty($cityName) || $cityName === '-') {
                    continue;
                }

                // 3. Create or Get City (This runs for 'all_global_records' & 'specific_country_all')
                City::firstOrCreate(
                    ['state_id' => $state->id, 'name' => $cityName],
                    ['is_active' => true]
                );
            }

            fclose($handle);

            return back()->with('success', 'Records imported successfully based on your selected strategy!');

        } catch (\Exception $e) {
            if (isset($handle) && is_resource($handle)) fclose($handle);
            return back()->withErrors(['error' => 'Import failed: ' . $e->getMessage()]);
        }
    }

    public function getCountries()
    {
        return response()->json(Country::where('is_active', true)->orderBy('name')->get(['id', 'name', 'iso2', 'phone_code', 'currency']));
    }

    public function getStates($country_id)
    {
        return response()->json(State::where('country_id', $country_id)->where('is_active', true)->orderBy('name')->get(['id', 'name']));
    }

    public function getCities($state_id)
    {
        return response()->json(City::where('state_id', $state_id)->where('is_active', true)->orderBy('name')->get(['id', 'name']));
    }
}