# edited by glg
import hashlib
import json
import time
import uuid
from datetime import datetime

import pytest

from pypos.modules.sinkronisasi.services.event_outbox_service import EventOutboxService

pytestmark = [pytest.mark.perf_smoke, pytest.mark.non_functional]


def test_event_outbox_simulasi_10000_cabang_perf_smoke(tmp_path):
    db_path = str(tmp_path / "event_outbox_10000_cabang.db")
    service = EventOutboxService(db_path=db_path)

    total_cabang = 10000
    started_at = time.perf_counter()
    now_text = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
    rows = []
    for idx in range(total_cabang):
        source_id = f"CABANG-{idx + 1:05d}"
        payload = {
            "branch_id": idx + 1,
            "last_sync_ts": "2026-04-12 00:00:00",
            "pending_delta": idx % 9,
        }
        payload_json = json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
        dedup_key = hashlib.sha256(
            f"sync.branch.heartbeat|{source_id.lower()}|{payload_json}".encode("utf-8")
        ).hexdigest()
        rows.append(
            (
                str(uuid.uuid4()),
                dedup_key,
                "sync.branch.heartbeat",
                payload_json,
                "{}",
                now_text,
                source_id,
                now_text,
                now_text,
            )
        )

    conn = service._connect()
    try:
        cur = conn.cursor()
        cur.executemany(
            """
            INSERT INTO event_outbox (
                event_id, dedup_key, topic, payload_json, headers_json,
                status, attempt_count, available_at, lease_token, lease_until,
                error_code, error_message, source_id, created_at, updated_at
            ) VALUES (?, ?, ?, ?, ?, 'PENDING', 0, ?, NULL, NULL, NULL, NULL, ?, ?, ?)
            """,
            rows,
        )
        conn.commit()
    finally:
        conn.close()

    processed = 0
    empty_streak = 0
    while processed < total_cabang:
        batch = service.claim_batch(limit=500, lease_seconds=45, max_inflight=25000)
        if not batch:
            empty_streak += 1
            if empty_streak >= 3:
                break
            continue
        empty_streak = 0
        ids = [int(item.get("id") or 0) for item in batch if int(item.get("id") or 0) > 0]
        if not ids:
            continue
        service.ack_events(ids)
        processed += len(ids)

    metrics = service.get_queue_metrics()
    elapsed_ms = (time.perf_counter() - started_at) * 1000.0

    assert processed == total_cabang
    assert int(metrics.get("pending") or 0) == 0
    assert int(metrics.get("inflight") or 0) == 0
    assert int(metrics.get("sent") or 0) >= total_cabang
    # Target smoke: simulasi 10k cabang tetap dalam batas waktu wajar di CI.
    assert elapsed_ms < 45000.0
