
<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

$action   = isset($_GET['action']) ? $_GET['action'] : 'geocode';
$dataFile = __DIR__ . '/database.json';
$csvFile  = __DIR__ . '/branches_export.csv';

// ─── حداکثر حجم ورودی (5MB) ─────────────────────────────────────────────
define('MAX_INPUT_SIZE', 5 * 1024 * 1024);

// ─── Helper: نوشتن امن فایل با flock ─────────────────────────────────────
function safeFileWrite($path, $content) {
    $fp = fopen($path, 'c');
    if (!$fp) return false;

    if (flock($fp, LOCK_EX)) {
        ftruncate($fp, 0);
        rewind($fp);
        $written = fwrite($fp, $content);
        fflush($fp);
        flock($fp, LOCK_UN);
        fclose($fp);
        return $written !== false;
    }

    fclose($fp);
    return false;
}

// ─── Helper: خواندن امن فایل با flock ─────────────────────────────────────
function safeFileRead($path) {
    if (!file_exists($path)) return false;

    $fp = fopen($path, 'r');
    if (!$fp) return false;

    if (flock($fp, LOCK_SH)) {
        $content = stream_get_contents($fp);
        flock($fp, LOCK_UN);
        fclose($fp);
        return $content;
    }

    fclose($fp);
    return false;
}

// ─── Helper: rebuild CSV from current DB ────────────────────────────────────
function rebuildCSV($dataFile, $csvFile) {
    $raw = safeFileRead($dataFile);
    if ($raw === false) return;

    $stores = json_decode($raw, true);
    if (!is_array($stores)) return;

    $statusKeys = ['location_sent', 'area_manager_visit', 'exec_manager_visit', 'contract', 'contract_sent', 'hq_receive'];
    $statusLabels = [
        'location_sent'      => 'ارسال لوکیشن',
        'area_manager_visit' => 'بازدید مدیر منطقه',
        'exec_manager_visit' => 'بازدید مدیر اجرایی',
        'contract'           => 'قرارداد',
        'contract_sent'      => 'ارسال قرارداد',
        'hq_receive'         => 'دریافت ستاد',
    ];

    // ── الگوریتم تبدیل میلادی به شمسی (معتبر و تست‌شده) ──────────────────
    $toJalali = function ($gy, $gm, $gd) {
        $gy = (int)$gy;
        $gm = (int)$gm;
        $gd = (int)$gd;

        $g_d_m = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];

        $gy2  = ($gm > 2) ? ($gy + 1) : $gy;
        $days = 355666 + (365 * $gy) + ((int)(($gy2 + 3) / 4)) - ((int)(($gy2 + 99) / 100))
                + ((int)(($gy2 + 399) / 400)) + $gd + $g_d_m[$gm - 1];

        $jy    = -1595 + (33 * (int)($days / 12053));
        $days %= 12053;

        $jy   += 4 * (int)($days / 1461);
        $days %= 1461;

        if ($days > 365) {
            $jy  += (int)(($days - 1) / 365);
            $days = ($days - 1) % 365;
        }

        if ($days < 186) {
            $jm = 1 + (int)($days / 31);
            $jd = 1 + ($days % 31);
        } else {
            $jm = 7 + (int)(($days - 186) / 30);
            $jd = 1 + (($days - 186) % 30);
        }

        return [$jy, $jm, $jd];
    };

    // ── مدت زمان خوانا ──────────────────────────────────────────────────────
    $formatDuration = function($startISO, $endISO) {
        $start = strtotime($startISO);
        if ($start === false) return '';
        $end  = $endISO ? strtotime($endISO) : time();
        if ($end === false) $end = time();
        $diff = max(0, $end - $start);

        $days    = (int)floor($diff / 86400);
        $hours   = (int)floor(($diff % 86400) / 3600);
        $minutes = (int)floor(($diff % 3600) / 60);

        $parts = [];
        if ($days)    $parts[] = "{$days} روز";
        if ($hours)   $parts[] = "{$hours} ساعت";
        if ($minutes) $parts[] = "{$minutes} دقیقه";
        return $parts ? implode(' و ', $parts) : 'کمتر از یک دقیقه';
    };

    // ── تاریخ ISO به فارسی-خوانا ───────────────────────────────────────────
    $formatDate = function($iso) use ($toJalali) {
        if (!$iso || !is_string($iso)) return '';
        try {
            $dt = new DateTime($iso, new DateTimeZone('UTC'));
            $dt->setTimezone(new DateTimeZone('Asia/Tehran'));
            [$jy, $jm, $jd] = $toJalali((int)$dt->format('Y'), (int)$dt->format('n'), (int)$dt->format('j'));
            $time = $dt->format('H:i');
            return sprintf('%04d/%02d/%02d %s', $jy, $jm, $jd, $time);
        } catch (Exception $e) {
            return '';
        }
    };

    $csvEscape = function($val) {
        $str = (string)($val ?? '');
        if (strpbrk($str, ",\"\n\r") !== false) {
            return '"' . str_replace('"', '""', $str) . '"';
        }
        return $str;
    };

    // ── هدرها ───────────────────────────────────────────────────────────────
    $baseHeaders = [
        'وضعیت فعلی', 'کد شعبه', 'نام شعبه',
        'lat', 'lng', 'آدرس', 'شهر', 'استان',
        'منطقه شهرداری', 'زون ترافیکی', 'زون طرح زوج-فرد',
        'روستا', 'شهرستان', 'ناحیه', 'فرانچایز',
        'تاریخ ثبت', 'آخرین بروزرسانی',
    ];

    $stageHeaders = [];
    foreach ($statusKeys as $key) {
        $label = $statusLabels[$key];
        $stageHeaders[] = "شروع {$label}";
        $stageHeaders[] = "پایان {$label}";
        $stageHeaders[] = "مدت {$label}";
    }

    $rows   = [];
    $rows[] = implode(',', array_map($csvEscape, array_merge($baseHeaders, $stageHeaders)));

    // ── پردازش هر شعبه ─────────────────────────────────────────────────────
    foreach ($stores as $store) {
        if (!is_array($store)) continue;

        $history = $store['status_history'] ?? [];

        $stageTimings = [];
        foreach ($statusKeys as $key) {
            $stageTimings[$key] = ['start' => null, 'end' => null];
        }

        if (is_array($history)) {
            foreach ($history as $i => $h) {
                if (!is_array($h)) continue;

                $to   = $h['to']   ?? null;
                $from = $h['from'] ?? null;
                $at   = $h['at']   ?? null;

                if ($to && isset($stageTimings[$to])) {
                    $stageTimings[$to]['start'] = $at;
                    $stageTimings[$to]['end']   = null;
                }

                if ($from && isset($stageTimings[$from]) && $stageTimings[$from]['start']) {
                    $stageTimings[$from]['end'] = $at;
                }
            }
        }

        $currentStatus = $store['status'] ?? null;

        $inTrafficZone = $store['in_traffic_zone'] ?? false;
        $inOddEvenZone = $store['in_odd_even_zone'] ?? false;
        $isFranchise   = $store['is_franchise'] ?? false;

        $baseRow = [
            $currentStatus ? ($statusLabels[$currentStatus] ?? $currentStatus) : '',
            $store['store_code']        ?? '',
            $store['store_name']        ?? '',
            $store['lat']               ?? '',
            $store['lng']               ?? '',
            $store['formatted_address'] ?? '',
            $store['city']              ?? '',
            $store['state']             ?? '',
            $store['municipality_zone'] ?? '',
            ($inTrafficZone === true  || $inTrafficZone === 'TRUE'  || $inTrafficZone === 'true'  || $inTrafficZone === 1 || $inTrafficZone === '1') ? 'TRUE' : 'FALSE',
            ($inOddEvenZone === true  || $inOddEvenZone === 'TRUE' || $inOddEvenZone === 'true'  || $inOddEvenZone === 1 || $inOddEvenZone === '1') ? 'TRUE' : 'FALSE',
            $store['village']           ?? '',
            $store['county']            ?? '',
            $store['district']          ?? '',
            ($isFranchise === true || $isFranchise === '1' || $isFranchise === 1) ? '1' : '0',
            $formatDate($store['created_at'] ?? ''),
            $formatDate($store['updated_at'] ?? ''),
        ];

        $stageRow = [];
        foreach ($statusKeys as $key) {
            $timing = $stageTimings[$key];
            $start  = $timing['start'];
            $end    = $timing['end'];

            if (!$start) {
                $stageRow[] = '';
                $stageRow[] = '';
                $stageRow[] = '';
            } else {
                $isActive   = ($key === $currentStatus && !$end);
                $stageRow[] = $formatDate($start);
                $stageRow[] = $end ? $formatDate($end) : 'در جریان';
                $stageRow[] = $formatDuration($start, $end ?: null) . ($isActive ? ' (ادامه دارد)' : '');
            }
        }

        $rows[] = implode(',', array_map($csvEscape, array_merge($baseRow, $stageRow)));
    }

    safeFileWrite($csvFile, "\xEF\xBB\xBF" . implode("\n", $rows));
}

// ─── 1. Load ─────────────────────────────────────────────────────────────────
if ($action === 'load') {
    if (!file_exists($dataFile)) {
        safeFileWrite($dataFile, '[]');
    }
    $content = safeFileRead($dataFile);
    if ($content === false) {
        echo '[]';
        exit();
    }
    $decoded = json_decode($content, true);
    if ($decoded === null) {
        safeFileWrite($dataFile, '[]');
        echo '[]';
    } else {
        echo $content;
    }
    exit();
}

// ─── 2. Save + rebuild CSV (Race Condition Fixed) ─────────────────────────
if ($action === 'save') {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        http_response_code(405);
        echo json_encode(['success' => false, 'error' => 'Method not allowed']);
        exit();
    }

    $inputJSON = file_get_contents('php://input', false, null, 0, MAX_INPUT_SIZE + 1);

    if ($inputJSON === false || strlen($inputJSON) > MAX_INPUT_SIZE) {
        http_response_code(413);
        echo json_encode(['success' => false, 'error' => 'Input too large or unreadable']);
        exit();
    }

    $singleStore = json_decode($inputJSON, true);

    if (!is_array($singleStore) || !isset($singleStore['id'])) {
        http_response_code(400);
        echo json_encode(['success' => false, 'error' => 'Invalid store data or missing ID']);
        exit();
    }
    $fp = fopen($dataFile, 'c+');
    if (!$fp) {
        http_response_code(500);
        echo json_encode(['success' => false, 'error' => 'Cannot open database file']);
        exit();
    }

    if (flock($fp, LOCK_EX)) {
        $fileSize = filesize($dataFile);
        $existingData = [];
        
        if ($fileSize > 0) {
            $jsonContent = fread($fp, $fileSize);
            $existingData = json_decode($jsonContent, true) ?: [];
        }

        $found = false;
        foreach ($existingData as &$store) {
            if (isset($store['id']) && $store['id'] === $singleStore['id']) {
                $store = $singleStore; 
                $found = true;
                break;
            }
        }
        unset($store); 

        if (!$found) {
            $existingData[] = $singleStore;
        }

        ftruncate($fp, 0);
        rewind($fp);
        fwrite($fp, json_encode($existingData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
        fflush($fp);
        
        flock($fp, LOCK_UN);
        fclose($fp);

        rebuildCSV($dataFile, $csvFile);

        echo json_encode(['success' => true, 'message' => 'Store saved successfully', 'csv_updated' => true]);
    } else {
        fclose($fp);
        http_response_code(500);
        echo json_encode(['success' => false, 'error' => 'Could not lock database file (System busy)']);
    }
    exit();
}


// ─── 3. دانلود مستقیم CSV ───────────────────────────────────────────────────
if ($action === 'download_csv') {
    if (!file_exists($csvFile)) {
        rebuildCSV($dataFile, $csvFile);
    }
    if (!file_exists($csvFile)) {
        http_response_code(404);
        echo json_encode(['error' => 'CSV file not found and could not be generated']);
        exit();
    }
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="branches_export.csv"');
    header('Content-Length: ' . filesize($csvFile));
    header_remove('Access-Control-Allow-Origin');
    readfile($csvFile);
    exit();
}

// ─── 4. Geocode proxy ────────────────────────────────────────────────────────
if ($action === 'geocode') {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        http_response_code(405);
        echo json_encode(['error' => 'Method not allowed', 'http_code' => 405]);
        exit();
    }


    $rawInput = file_get_contents('php://input', false, null, 0, 4096);
    $input    = json_decode($rawInput, true);

    if (!$input || !isset($input['lat']) || !isset($input['lng'])) {
        http_response_code(400);
        echo json_encode(['error' => 'Missing lat/lng', 'http_code' => 400]);
        exit();
    }

    $lat = filter_var($input['lat'], FILTER_VALIDATE_FLOAT);
    $lng = filter_var($input['lng'], FILTER_VALIDATE_FLOAT);

    if ($lat === false || $lng === false) {
        http_response_code(400);
        echo json_encode(['error' => 'Invalid lat/lng values', 'http_code' => 400]);
        exit();
    }

    if ($lat < 24.0 || $lat > 40.0 || $lng < 44.0 || $lng > 64.0) {
        http_response_code(400);
        echo json_encode(['error' => 'Coordinates out of Iran range', 'http_code' => 400]);
        exit();
    }

    $apiKey = 'service.d3c8ad2c2dda4d7bb64811075c939f84';

    $url = "https://api.neshan.org/v5/reverse?" . http_build_query(['lat' => $lat, 'lng' => $lng]);

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 15,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_HTTPHEADER     => ['Api-Key: ' . $apiKey, 'Accept: application/json'],
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 3,
        CURLOPT_USERAGENT      => 'StoreDashboard/1.0',
    ]);

    $response  = curl_exec($ch);
    $httpCode  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);

    if ($curlError) {
        echo json_encode([
            'error'     => 'cURL Error: ' . $curlError,
            'http_code' => 0,
            'data'      => ['status' => 'NetworkError'],
        ]);
        exit();
    }

    $data = json_decode($response, true);
    echo json_encode(['http_code' => $httpCode, 'data' => $data ?: ['status' => "Error_$httpCode"]]);
    exit();
}

// ─── عمل ناشناخته ────────────────────────────────────────────────────────────
http_response_code(400);
echo json_encode(['error' => 'Unknown action: ' . htmlspecialchars($action)]);
exit();
