from pathlib import Path

from app.followup_service import FOLLOW_UP_CADENCES, follow_up_suggested_message


def read(path: str) -> str:
    return Path(path).read_text(encoding="utf-8")


def test_quote_cadence_starts_with_commercial_followup():
    quote = FOLLOW_UP_CADENCES["quote"]
    assert [step["delay_business_days"] for step in quote] == [2, 4, 5]
    assert quote[0]["action_code"] == "FOLLOW_UP_QUOTE"
    assert quote[0]["purpose"] == "objection_check"
    assert quote[-1]["purpose"] == "final_attempt"
    assert all(step["action_code"] != "CONFIRM_DELIVERY" for step in quote)


def test_payment_cadence_is_short_and_progressive_without_delivery_gate():
    payment = FOLLOW_UP_CADENCES["payment"]
    assert [step["delay_business_days"] for step in payment] == [2, 3, 3, 5]
    assert payment[0]["purpose"] == "payment_date"
    assert payment[-1]["purpose"] == "final_attempt"
    assert all(step["action_code"] != "CONFIRM_DELIVERY" for step in payment)


def test_delivery_confirmation_message_remains_available_for_manual_use():
    message = follow_up_suggested_message(
        action_code="CONFIRM_DELIVERY",
        customer_name="Maria Silva",
        follow_up_stage=1,
        follow_up_family="quote",
    )
    assert "confirmar se recebeu o orçamento" in message
    assert "reenvio de imediato" in message


def test_lifecycle_schema_and_safe_reopen_are_additive():
    service = read("app/opportunity_service.py")
    for field in [
        "lifecycle_state",
        "last_customer_activity_at",
        "last_operator_activity_at",
        "last_outbound_sent_at",
        "last_delivery_checked_at",
        "last_delivery_status",
        "last_commercial_activity_at",
        "next_follow_up_at",
        "follow_up_attempts",
        "nurture_until",
        "lost_reason",
    ]:
        assert f"ADD COLUMN IF NOT EXISTS {field}" in service
    assert "_find_reopenable_opportunity_by_conversation" in service
    assert "stage IN ('LOST', 'NO_INTEREST')" in service
    assert "DELIVERED" not in service.split("def _find_reopenable_opportunity_by_conversation", 1)[1].split("def _open_opportunities_for_contact", 1)[0]


def test_opportunity_ui_has_recovery_nurture_and_mandatory_loss_reason():
    page = read("app/admin_ui/pages/opportunities.py")
    for label in [
        "A aguardar cliente",
        "Follow-up vencido",
        "Recuperação",
        "Acompanhamento futuro",
        "Por valorizar",
    ]:
        assert label in page
    assert '@router.post("/opportunities/{opportunity_id}/lost")' in page
    assert "Motivo de perda obrigatório" in read("app/opportunity_service.py")
    assert "Timing futuro deve usar acompanhamento futuro" in read("app/opportunity_service.py")


def test_backfill_script_is_dry_run_safe_and_skips_delivery_confirmation():
    script = read("scripts/sync_opportunity_followup_lifecycle.py")
    assert 'parser.add_argument("--apply", action="store_true"' in script
    assert '"--include-zero-value"' in script
    assert "Dry-run only" in script
    assert "materialize_initial_follow_up_for_opportunity" in script
    assert 'due_at=None' in script
    assert "migration_v4928_1_5_127" in script
    assert "send_email" not in script
