<?php
header('Content-Type: application/json');
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') { exit(0); }

define('DATA_DIR', __DIR__ . '/data/');

if (!is_dir(DATA_DIR)) mkdir(DATA_DIR, 0755, true);

function readData($name) {
    $file = DATA_DIR . $name . '.json';
    if (!file_exists($file)) return [];
    $content = file_get_contents($file);
    $decoded = json_decode($content, true);
    return is_array($decoded) ? $decoded : [];
}

function writeData($name, $data) {
    file_put_contents(DATA_DIR . $name . '.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}

function genId() {
    return base_convert(time(), 10, 36) . base_convert(rand(0, 1679616), 10, 36);
}

function todayDate() {
    return date('Y-m-d');
}

function parseTgIdFromName($name) {
    $name = trim((string)$name);
    if ($name === '') return '';
    if (preg_match('/(?:^|\\s)(\\d{6,})\\s*$/u', $name, $m)) return $m[1];
    return '';
}

function baseNameFromName($name) {
    $name = trim((string)$name);
    $tgId = parseTgIdFromName($name);
    if ($tgId) $name = trim(preg_replace('/\\s*' . preg_quote($tgId, '/') . '\\s*$/u', '', $name));
    return $name;
}

function mergeClient($old, $new) {
    // keep old id/created, but take non-empty new fields
    $out = $old;
    foreach (['name','phone','project','amount','currency','status','note','tgId','baseName'] as $k) {
        if (isset($new[$k]) && trim((string)$new[$k]) !== '') $out[$k] = $new[$k];
    }

    // Preserve stage amounts: card open fee vs topup amount
    // Convention: status=card_opened => openFee, status=funded => topup
    $oldStatus = $old['status'] ?? '';
    $newStatus = $new['status'] ?? '';
    $oldAmt = $old['amount'] ?? '';
    $oldCur = $old['currency'] ?? 'USD';
    $newAmt = $new['amount'] ?? '';
    $newCur = $new['currency'] ?? 'USD';

    if (($old['openAmount'] ?? '') === '' && $oldStatus === 'card_opened' && trim((string)$oldAmt) !== '') {
        $out['openAmount'] = normAmountStr($oldAmt, $oldCur);
        $out['openCurrency'] = normCurrency($oldCur);
    }
    if (($old['topupAmount'] ?? '') === '' && $oldStatus === 'funded' && trim((string)$oldAmt) !== '') {
        $out['topupAmount'] = normAmountStr($oldAmt, $oldCur);
        $out['topupCurrency'] = normCurrency($oldCur);
    }

    if ($newStatus === 'card_opened' && trim((string)$newAmt) !== '') {
        $out['openAmount'] = normAmountStr($newAmt, $newCur);
        $out['openCurrency'] = normCurrency($newCur);
    }
    if ($newStatus === 'funded' && trim((string)$newAmt) !== '') {
        $out['topupAmount'] = normAmountStr($newAmt, $newCur);
        $out['topupCurrency'] = normCurrency($newCur);
    }

    // Commission staged by status (commissionAmount/commissionCurrency in input)
    $newComm = $new['commissionAmount'] ?? '';
    $newCommCur = normCurrency($new['commissionCurrency'] ?? ($new['currency'] ?? 'USD'));
    if ($newStatus === 'card_opened' && trim((string)$newComm) !== '') {
        $out['openCommissionAmount'] = normAmountStr($newComm, $newCommCur);
        $out['openCommissionCurrency'] = $newCommCur;
    }
    if ($newStatus === 'funded' && trim((string)$newComm) !== '') {
        $out['topupCommissionAmount'] = normAmountStr($newComm, $newCommCur);
        $out['topupCommissionCurrency'] = $newCommCur;
    }

    // If both stage amounts exist, keep status as funded but allow UI to show combined
    $out['updated'] = todayDate();
    return $out;
}

function normCurrency($cur) {
    $cur = strtoupper(trim((string)$cur));
    return in_array($cur, ['RUB','USD','AED'], true) ? $cur : 'USD';
}

function normAmountStr($amount, $cur) {
    $cur = normCurrency($cur);
    $n = is_numeric($amount) ? (float)$amount : (float)str_replace(',', '.', (string)$amount);
    if (!is_finite($n)) $n = 0.0;
    if ($cur === 'RUB') return (string)round($n);
    return number_format($n, 2, '.', '');
}

function upsertClientIncome($client) {
    $clientId = $client['id'] ?? '';
    if (!$clientId) return;

    $amountMap = []; // currency => float sum
    $add = function($amtRaw, $curRaw) use (&$amountMap) {
        $cur = normCurrency($curRaw ?? 'USD');
        $n = (float)str_replace(',', '.', (string)$amtRaw);
        if (!is_finite($n) || $n <= 0) return;
        if (!isset($amountMap[$cur])) $amountMap[$cur] = 0.0;
        $amountMap[$cur] += $n;
    };

    // Prefer stage sums (open + topup) if present
    if (($client['openAmount'] ?? '') !== '' || ($client['topupAmount'] ?? '') !== '') {
        $add($client['openAmount'] ?? '', $client['openCurrency'] ?? ($client['currency'] ?? 'USD'));
        $add($client['topupAmount'] ?? '', $client['topupCurrency'] ?? ($client['currency'] ?? 'USD'));
    } else {
        $add($client['amount'] ?? '', $client['currency'] ?? 'USD');
    }

    $hasAmount = count($amountMap) > 0;

    // Build formatted amounts and choose primary currency (prefer USD)
    $formattedAmounts = [];
    foreach ($amountMap as $c => $sum) {
        $formattedAmounts[$c] = normAmountStr($sum, $c);
    }
    $primaryCur = isset($formattedAmounts['USD']) ? 'USD' : array_key_first($formattedAmounts);
    $primaryAmount = $primaryCur ? ($formattedAmounts[$primaryCur] ?? '') : '';

    $finances = readData('finances');
    $out = [];
    $found = false;

    foreach ($finances as $f) {
        $isLinked = (($f['sourceEntity'] ?? '') === 'clients') && (($f['sourceId'] ?? '') === $clientId);
        if ($isLinked) {
            $found = true;
            if (!$hasAmount) {
                // remove linked finance record if client amount cleared
                continue;
            }

            $name = 'Клиент: ' . ($client['name'] ?? '');
            if (($client['project'] ?? '') !== '') $name .= ' — ' . $client['project'];

            $f['type'] = 'income';
            $f['name'] = $name;
            $f['amount'] = $primaryAmount;
            $f['currency'] = $primaryCur ?: 'USD';
            $f['amounts'] = $formattedAmounts;
            if (!isset($f['category']) || $f['category'] === '') $f['category'] = '👥 Клиенты';
            if (!isset($f['date']) || $f['date'] === '') $f['date'] = todayDate();
            $f['sourceEntity'] = 'clients';
            $f['sourceId'] = $clientId;
            $out[] = $f;
        } else {
            $out[] = $f;
        }
    }

    if (!$found && $hasAmount) {
        $name = 'Клиент: ' . ($client['name'] ?? '');
        if (($client['project'] ?? '') !== '') $name .= ' — ' . $client['project'];
        array_unshift($out, [
            'type' => 'income',
            'name' => $name,
            'category' => '👥 Клиенты',
            'amount' => $primaryAmount,
            'currency' => $primaryCur ?: 'USD',
            'amounts' => $formattedAmounts,
            'date' => todayDate(),
            'due' => '',
            'note' => '',
            'id' => genId(),
            'created' => todayDate(),
            'sourceEntity' => 'clients',
            'sourceId' => $clientId,
        ]);
    }

    writeData('finances', $out);
}

function upsertClientCommission($client) {
    $clientId = $client['id'] ?? '';
    if (!$clientId) return;

    $entries = [
        ['kind' => 'commission_open',  'amount' => $client['openCommissionAmount'] ?? '',  'currency' => $client['openCommissionCurrency'] ?? ($client['commissionCurrency'] ?? 'USD')],
        ['kind' => 'commission_topup', 'amount' => $client['topupCommissionAmount'] ?? '', 'currency' => $client['topupCommissionCurrency'] ?? ($client['commissionCurrency'] ?? 'USD')],
    ];

    // Legacy: if only commissionAmount is present (no stage), attach to open by default
    if (($client['commissionAmount'] ?? '') !== '' && ($client['openCommissionAmount'] ?? '') === '' && ($client['topupCommissionAmount'] ?? '') === '') {
        $entries[0]['amount'] = $client['commissionAmount'];
        $entries[0]['currency'] = $client['commissionCurrency'] ?? ($client['currency'] ?? 'USD');
    }

    $finances = readData('finances');
    $out = [];

    // Precompute desired
    $desired = [];
    foreach ($entries as $e) {
        $amtRaw = $e['amount'];
        $cur = normCurrency($e['currency'] ?? 'USD');
        $amtNum = (float)str_replace(',', '.', (string)$amtRaw);
        if (is_finite($amtNum) && $amtNum > 0) {
            $desired[$e['kind']] = ['amount' => normAmountStr($amtRaw, $cur), 'currency' => $cur];
        }
    }

    // Update/remove existing linked commission expenses
    foreach ($finances as $f) {
        $isLinked = (($f['sourceEntity'] ?? '') === 'clients') && (($f['sourceId'] ?? '') === $clientId) && (($f['sourceKind'] ?? '') !== '');
        if ($isLinked && str_starts_with(($f['sourceKind'] ?? ''), 'commission_')) {
            $kind = $f['sourceKind'];
            if (!isset($desired[$kind])) {
                continue; // remove
            }
            $d = $desired[$kind];
            $f['type'] = 'expense';
            $f['name'] = 'Комиссия — ' . ($client['name'] ?? '');
            $f['category'] = '💸 Комиссия';
            $f['amount'] = $d['amount'];
            $f['currency'] = $d['currency'];
            $f['amounts'] = [$d['currency'] => $d['amount']];
            if (!isset($f['date']) || $f['date'] === '') $f['date'] = todayDate();
            $out[] = $f;
            unset($desired[$kind]);
        } else {
            $out[] = $f;
        }
    }

    // Add missing desired commission expenses
    foreach ($desired as $kind => $d) {
        array_unshift($out, [
            'type' => 'expense',
            'name' => 'Комиссия — ' . ($client['name'] ?? ''),
            'category' => '💸 Комиссия',
            'amount' => $d['amount'],
            'currency' => $d['currency'],
            'amounts' => [$d['currency'] => $d['amount']],
            'date' => todayDate(),
            'due' => '',
            'note' => '',
            'id' => genId(),
            'created' => todayDate(),
            'sourceEntity' => 'clients',
            'sourceId' => $clientId,
            'sourceKind' => $kind,
        ]);
    }

    writeData('finances', $out);
}

function upsertFinanceCommission($finance) {
    // Link expense commission to an income finance item by id
    if (($finance['type'] ?? '') !== 'income') return;
    $fid = $finance['id'] ?? '';
    if (!$fid) return;

    $commRaw = $finance['commissionAmount'] ?? '';
    $cur = normCurrency($finance['commissionCurrency'] ?? ($finance['currency'] ?? 'USD'));
    $commNum = (float)str_replace(',', '.', (string)$commRaw);
    $has = is_finite($commNum) && $commNum > 0;

    $finances = readData('finances');
    $out = [];
    $found = false;

    foreach ($finances as $f) {
        $isLinked = (($f['sourceEntity'] ?? '') === 'finances') && (($f['sourceId'] ?? '') === $fid) && (($f['sourceKind'] ?? '') === 'commission');
        if ($isLinked) {
            $found = true;
            if (!$has) continue; // delete
            $f['type'] = 'expense';
            $f['name'] = 'Комиссия — ' . ($finance['name'] ?? '');
            $f['category'] = '💸 Комиссия';
            $f['amount'] = normAmountStr($commRaw, $cur);
            $f['currency'] = $cur;
            $f['amounts'] = [$cur => $f['amount']];
            if (!isset($f['date']) || $f['date'] === '') $f['date'] = $finance['date'] ?? todayDate();
            $out[] = $f;
        } else {
            $out[] = $f;
        }
    }

    if (!$found && $has) {
        array_unshift($out, [
            'type' => 'expense',
            'name' => 'Комиссия — ' . ($finance['name'] ?? ''),
            'category' => '💸 Комиссия',
            'amount' => normAmountStr($commRaw, $cur),
            'currency' => $cur,
            'amounts' => [$cur => normAmountStr($commRaw, $cur)],
            'date' => $finance['date'] ?? todayDate(),
            'due' => '',
            'note' => '',
            'id' => genId(),
            'created' => todayDate(),
            'sourceEntity' => 'finances',
            'sourceId' => $fid,
            'sourceKind' => 'commission',
        ]);
    }

    writeData('finances', $out);
}

$entity = $_GET['entity'] ?? '';
$allowed = ['clients', 'finances', 'tasks', 'notes', 'tracker', 'settings'];

if (!in_array($entity, $allowed)) {
    echo json_encode(['error' => 'Unknown entity']);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    $data = readData($entity);
    echo json_encode($data);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $body = json_decode(file_get_contents('php://input'), true);
    
    // Settings is a special key-value store
    if ($entity === 'settings') {
        $current = readData('settings');
        if (!is_array($current) || isset($current[0])) $current = [];
        $merged = array_merge($current, $body);
        writeData('settings', $merged);
        echo json_encode(['ok' => true]);
        exit;
    }

    $action = $body['action'] ?? '';
    $data_in = $body['data'] ?? [];
    $items = readData($entity);

    if ($entity === 'clients') {
        // enrich input with tgId/baseName for deduping
        if (isset($data_in['name'])) {
            $data_in['tgId'] = parseTgIdFromName($data_in['name']);
            $data_in['baseName'] = mb_strtolower(baseNameFromName($data_in['name']));
        }
        // stage amounts support on update/add
        if (isset($data_in['status']) && isset($data_in['amount']) && trim((string)$data_in['amount']) !== '') {
            $st = $data_in['status'];
            $cur = normCurrency($data_in['currency'] ?? 'USD');
            if ($st === 'card_opened') {
                $data_in['openAmount'] = normAmountStr($data_in['amount'], $cur);
                $data_in['openCurrency'] = $cur;
            } elseif ($st === 'funded') {
                $data_in['topupAmount'] = normAmountStr($data_in['amount'], $cur);
                $data_in['topupCurrency'] = $cur;
            }
        }
        // stage commission support on update/add
        if (isset($data_in['status']) && isset($data_in['commissionAmount']) && trim((string)$data_in['commissionAmount']) !== '') {
            $st = $data_in['status'];
            $cur = normCurrency($data_in['commissionCurrency'] ?? ($data_in['currency'] ?? 'USD'));
            if ($st === 'card_opened') {
                $data_in['openCommissionAmount'] = normAmountStr($data_in['commissionAmount'], $cur);
                $data_in['openCommissionCurrency'] = $cur;
            } elseif ($st === 'funded') {
                $data_in['topupCommissionAmount'] = normAmountStr($data_in['commissionAmount'], $cur);
                $data_in['topupCommissionCurrency'] = $cur;
            }
        }
    }

    if ($entity === 'clients' && $action === 'mergeDuplicates') {
        // Merge duplicates by tgId (preferred) or baseName; keep first occurrence
        $byKey = [];
        $kept = [];
        $idMap = []; // oldId => keptId

        foreach ($items as $c) {
            $tgId = $c['tgId'] ?? parseTgIdFromName($c['name'] ?? '');
            $base = $c['baseName'] ?? mb_strtolower(baseNameFromName($c['name'] ?? ''));
            $key = $tgId ? ('tg:' . $tgId) : ('nm:' . $base);
            if (!$key || $key === 'nm:') { // can't key -> keep as-is
                $kept[] = $c;
                continue;
            }
            if (!isset($byKey[$key])) {
                $byKey[$key] = $c;
                $kept[] = $c;
            } else {
                $primary = $byKey[$key];
                $merged = mergeClient($primary, $c);
                // update kept list entry in-place
                foreach ($kept as $i => $k) {
                    if (($k['id'] ?? '') === ($primary['id'] ?? '')) { $kept[$i] = $merged; break; }
                }
                $byKey[$key] = $merged;
                $oldId = $c['id'] ?? '';
                $keepId = $primary['id'] ?? '';
                if ($oldId && $keepId && $oldId !== $keepId) $idMap[$oldId] = $keepId;
            }
        }

        // Update linked finances sourceId for merged clients, and upsert incomes
        $finances = readData('finances');
        $finChanged = false;
        foreach ($finances as &$f) {
            if (($f['sourceEntity'] ?? '') !== 'clients') continue;
            $sid = $f['sourceId'] ?? '';
            if ($sid && isset($idMap[$sid])) { $f['sourceId'] = $idMap[$sid]; $finChanged = true; }
        }
        unset($f);
        if ($finChanged) writeData('finances', $finances);

        foreach ($kept as $c) upsertClientIncome($c);
        foreach ($kept as $c) upsertClientCommission($c);

        writeData('clients', $kept);
        echo json_encode(['ok' => true, 'items' => $kept, 'merged' => $idMap]);
        exit;
    }

    if ($action === 'add') {
        $item = $data_in;
        if ($entity === 'clients') {
            // try to merge into existing by tgId, otherwise by baseName
            $tgId = $item['tgId'] ?? '';
            $base = $item['baseName'] ?? '';
            $merged = false;
            foreach ($items as $idx => $c) {
                $cTg = $c['tgId'] ?? parseTgIdFromName($c['name'] ?? '');
                $cBase = $c['baseName'] ?? mb_strtolower(baseNameFromName($c['name'] ?? ''));
                if (($tgId && $cTg === $tgId) || (!$tgId && $base && $cBase === $base)) {
                    $items[$idx] = mergeClient($c, $item);
                    upsertClientIncome($items[$idx]);
                    upsertClientCommission($items[$idx]);
                    $merged = true;
                    break;
                }
            }
            if (!$merged) {
                $item['id'] = genId();
                $item['created'] = todayDate();
                $item['updated'] = todayDate();
                array_unshift($items, $item);
                upsertClientIncome($item);
                upsertClientCommission($item);
            }
        } else {
            $item['id'] = genId();
            $item['created'] = todayDate();
            array_unshift($items, $item);
        }

        if ($entity === 'finances') {
            upsertFinanceCommission($item);
        }

    } elseif ($action === 'update') {
        $id = $data_in['id'] ?? ($data_in['date'] ?? null);
        foreach ($items as &$item) {
            $key = ($entity === 'tracker') ? ($item['date'] ?? '') : ($item['id'] ?? '');
            if ($key === $id) {
                if ($entity === 'clients') {
                    // Migration behavior: if moving from card_opened -> funded, keep previous amount as openAmount (if not set)
                    $prevStatus = $item['status'] ?? '';
                    $nextStatus = $data_in['status'] ?? $prevStatus;
                    if ($prevStatus === 'card_opened' && $nextStatus === 'funded') {
                        if (($item['openAmount'] ?? '') === '' && trim((string)($item['amount'] ?? '')) !== '') {
                            $cur = normCurrency($item['currency'] ?? 'USD');
                            $item['openAmount'] = normAmountStr($item['amount'], $cur);
                            $item['openCurrency'] = $cur;
                        }
                        if (($item['openCommissionAmount'] ?? '') === '' && trim((string)($item['commissionAmount'] ?? '')) !== '') {
                            $cur = normCurrency($item['commissionCurrency'] ?? ($item['currency'] ?? 'USD'));
                            $item['openCommissionAmount'] = normAmountStr($item['commissionAmount'], $cur);
                            $item['openCommissionCurrency'] = $cur;
                        }
                    }
                }
                $item = array_merge($item, $data_in);
                if ($entity === 'clients') $item['updated'] = todayDate();
                break;
            }
        }
        unset($item);
        // tracker: if not found, add
        if ($entity === 'tracker') {
            $found = false;
            foreach ($items as $item) { if (($item['date'] ?? '') === $id) { $found = true; break; } }
            if (!$found) {
                $new = $data_in;
                $new['id'] = genId();
                array_unshift($items, $new);
            }
        }

        if ($entity === 'clients') {
            foreach ($items as $c) {
                if (($c['id'] ?? '') === $id) { upsertClientIncome($c); upsertClientCommission($c); break; }
            }
        }

        if ($entity === 'finances') {
            foreach ($items as $f) {
                if (($f['id'] ?? '') === $id) { upsertFinanceCommission($f); break; }
            }
        }

    } elseif ($action === 'delete') {
        $id = $data_in['id'] ?? '';
        $items = array_values(array_filter($items, fn($i) => ($i['id'] ?? '') !== $id));

        if ($entity === 'clients') {
            $finances = readData('finances');
            $finances = array_values(array_filter($finances, fn($f) => !(($f['sourceEntity'] ?? '') === 'clients' && ($f['sourceId'] ?? '') === $id)));
            writeData('finances', $finances);
        }

        if ($entity === 'finances') {
            // Remove linked commission expense (if deleting an income record)
            $finances = readData('finances');
            $finances = array_values(array_filter($finances, fn($f) => !(($f['sourceEntity'] ?? '') === 'finances' && ($f['sourceId'] ?? '') === $id && ($f['sourceKind'] ?? '') === 'commission')));
            writeData('finances', $finances);
        }
    }

    writeData($entity, $items);
    echo json_encode(['ok' => true, 'items' => $items]);
    exit;
}
