# edited by glg
import json

import requests

from pypos.modules.sinkronisasi.services.settlement_direct_service import SettlementDirectService


class _DummyExportService:
    def __init__(self, payload):
        self.payload = payload

    def build_direct_settlement_payload(self, transaksi_ids=None, settlement_counter=""):
        _ = transaksi_ids
        _ = settlement_counter
        return self.payload


class _DummyResponse:
    def __init__(self, status_code=200, payload=None):
        self.status_code = int(status_code)
        self._payload = payload if isinstance(payload, dict) else {}
        self.text = json.dumps(self._payload)

    def json(self):
        return dict(self._payload)


# edited by glg
class _DummyTextResponse:
    def __init__(self, status_code=200, text=""):
        self.status_code = int(status_code)
        self.text = str(text or "")

    def json(self):
        raise ValueError("invalid json")


def test_send_settlement_direct_skip_when_disabled():
    service = SettlementDirectService(
        export_service=_DummyExportService(payload={}),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: False,
    )
    result = service.send_settlement({"counter": "ST-1", "transaksi_ids": [1, 2]})
    assert result["attempted"] is False
    assert result["skipped"] == "disabled"


def test_send_settlement_direct_success_response():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )
    service.request_with_retry = lambda *args, **kwargs: _DummyResponse(
        status_code=200,
        payload={"success": True, "message": "ok"},
    )

    result = service.send_settlement({"counter": "ST-20260311-001", "transaksi_ids": [1, 2]})
    assert result["attempted"] is True
    assert result["ok"] is True
    assert result["status_code"] == 200
    assert result["idempotency_key"]


def test_send_settlement_direct_rejected_response():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )
    service.request_with_retry = lambda *args, **kwargs: _DummyResponse(
        status_code=200,
        payload={"success": False, "error": "invalid payload"},
    )

    result = service.send_settlement({"counter": "ST-20260311-002", "transaksi_ids": [10]})
    assert result["attempted"] is True
    assert result["ok"] is False
    assert "invalid payload" in str(result["error"]).lower()


def test_send_settlement_direct_duplicate_diterima_sebagai_sukses():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )
    service.request_with_retry = lambda *args, **kwargs: _DummyResponse(
        status_code=200,
        payload={"reason": "duplicate", "message": "replay aman"},
    )

    result = service.send_settlement({"counter": "ST-20260311-003", "transaksi_ids": [1, 2]})
    assert result["attempted"] is True
    assert result["ok"] is True
    assert result["status_code"] == 200
    assert result["reason_code"] == "duplicate"


def test_send_settlement_direct_http_409_idempotency_in_progress():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )

    def _raise_http_error(*args, **kwargs):
        response = _DummyResponse(
            status_code=409,
            payload={
                "reason": "idempotency_in_progress",
                "message": "permintaan masih diproses",
            },
        )
        raise requests.exceptions.HTTPError("HTTP 409", response=response)

    service.request_with_retry = _raise_http_error
    result = service.send_settlement({"counter": "ST-20260311-004", "transaksi_ids": [10]})
    assert result["attempted"] is True
    assert result["ok"] is False
    assert result["status_code"] == 409
    assert result["reason_code"] == "idempotency_in_progress"
    assert result["retryable"] is True
    assert "diproses" in str(result["error"]).lower()


def test_send_settlement_direct_http_401_unauthorized_user_context():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )

    def _raise_http_error(*args, **kwargs):
        response = _DummyResponse(
            status_code=401,
            payload={
                "reason": "unauthorized_user_context",
                "message": "user context tidak valid",
            },
        )
        raise requests.exceptions.HTTPError("HTTP 401", response=response)

    service.request_with_retry = _raise_http_error
    result = service.send_settlement({"counter": "ST-20260311-005", "transaksi_ids": [11]})
    assert result["attempted"] is True
    assert result["ok"] is False
    assert result["status_code"] == 401
    assert result["reason_code"] == "unauthorized_user_context"
    assert result["retryable"] is False


def test_send_settlement_direct_skip_invalid_endpoint_kosong():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "",
        },
        enabled_getter=lambda: True,
    )
    result = service.send_settlement({"counter": "ST-20260311-006", "transaksi_ids": [1, 2]})
    assert result["attempted"] is False
    assert result["skipped"] == "invalid_endpoint"


def test_send_settlement_direct_skip_payload_empty():
    service = SettlementDirectService(
        export_service=_DummyExportService(payload={}),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
    )
    result = service.send_settlement({"counter": "ST-20260311-007", "transaksi_ids": [1]})
    assert result["attempted"] is False
    assert result["skipped"] == "payload_empty"
    assert result["context"]["counter"] == "ST-20260311-007"
    assert result["context"]["transaksi_ids"] == [1]


def test_send_settlement_direct_http_400_invalid_payload():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )

    def _raise_http_error(*args, **kwargs):
        response = _DummyResponse(
            status_code=400,
            payload={
                "reason": "invalid_payload",
                "message": "komponen transaksi tidak valid",
            },
        )
        raise requests.exceptions.HTTPError("HTTP 400", response=response)

    service.request_with_retry = _raise_http_error
    result = service.send_settlement({"counter": "ST-20260311-008", "transaksi_ids": [12]})
    assert result["attempted"] is True
    assert result["ok"] is False
    assert result["status_code"] == 400
    assert result["reason_code"] == "invalid_payload"
    assert result["retryable"] is False


def test_send_settlement_direct_http_409_idempotency_key_conflict_non_retry():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )

    def _raise_http_error(*args, **kwargs):
        response = _DummyResponse(
            status_code=409,
            payload={
                "reason": "idempotency_key_conflict",
                "message": "kunci bentrok",
            },
        )
        raise requests.exceptions.HTTPError("HTTP 409", response=response)

    service.request_with_retry = _raise_http_error
    result = service.send_settlement({"counter": "ST-20260311-009", "transaksi_ids": [13]})
    assert result["attempted"] is True
    assert result["ok"] is False
    assert result["status_code"] == 409
    assert result["reason_code"] == "idempotency_key_conflict"
    assert result["retryable"] is False


def test_send_settlement_direct_http_500_db_transaction_failed_retryable():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )

    def _raise_http_error(*args, **kwargs):
        response = _DummyResponse(
            status_code=500,
            payload={
                "reason": "db_transaction_failed",
                "message": "rollback karena insert gagal",
            },
        )
        raise requests.exceptions.HTTPError("HTTP 500", response=response)

    service.request_with_retry = _raise_http_error
    result = service.send_settlement({"counter": "ST-20260311-010", "transaksi_ids": [14]})
    assert result["attempted"] is True
    assert result["ok"] is False
    assert result["status_code"] == 500
    assert result["reason_code"] == "db_transaction_failed"
    assert result["retryable"] is True


def test_send_settlement_direct_debug_no_commit_tetap_sukses():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )
    service.request_with_retry = lambda *args, **kwargs: _DummyResponse(
        status_code=200,
        payload={"reason": "debug_no_commit", "message": "simulasi tanpa commit"},
    )
    result = service.send_settlement({"counter": "ST-20260311-011", "transaksi_ids": [15]})
    assert result["attempted"] is True
    assert result["ok"] is True
    assert result["status_code"] == 200
    assert result["reason_code"] == "debug_no_commit"


def test_send_settlement_direct_status_200_legacy_tetap_sukses():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )
    service.request_with_retry = lambda *args, **kwargs: _DummyResponse(
        status_code=200,
        payload={"status": 200, "message": "settlement sukses di kirim"},
    )
    result = service.send_settlement({"counter": "ST-20260311-012", "transaksi_ids": [16]})
    assert result["attempted"] is True
    assert result["ok"] is True
    assert result["status_code"] == 200


def test_send_settlement_direct_salvage_json_dari_body_warning_tetap_sukses():
    payload = {
        "user_id": 188,
        "dtime": "2026-03-11 10:00:00",
        "cabang_id": 100,
        "device_id": "118933446257318",
        "data": {"2026-03-11": {"id_penjualan": [1, 2]}},
    }
    service = SettlementDirectService(
        export_service=_DummyExportService(payload=payload),
        endpoint_config_reader=lambda: {
            "api_base_url": "https://example.com",
            "ep_settlement_direct": "/settlement",
        },
        enabled_getter=lambda: True,
        auth_required_getter=lambda: False,
        timeout_getter=lambda: 3,
        retry_max_getter=lambda: 1,
        retry_backoff_getter=lambda: 0.0,
    )
    service.request_with_retry = lambda *args, **kwargs: _DummyTextResponse(
        status_code=200,
        text=(
            "Warning: Undefined index abc in /var/www/html/file.php on line 10\n"
            '{"status":1,"reason":"success","message":"settlement sukses di kirim"}'
        ),
    )
    result = service.send_settlement({"counter": "ST-20260311-013", "transaksi_ids": [17]})
    assert result["attempted"] is True
    assert result["ok"] is True
    assert result["status_code"] == 200
    assert result["reason_code"] == "success"
