from __future__ import annotations

from pathlib import Path

from PIL import Image

import pytest

from eightmem.services.compare_card import (
    build_card_proof_items,
    build_compare_share_card,
    build_passport_share_card,
    is_passport_card_eligible,
    is_share_card_eligible,
    parse_compare_output,
    parse_passport_summary,
)


def test_parse_compare_output_extracts_card_sections(fake_home):
    output = (
        "8mem Compare\n"
        "Prompt: Draft: write a founder update\n\n"
        "Standard answer:\n"
        "We made progress this week.\n\n"
        "Answer shaped by what I know about you:\n"
        "- Progress: shipped Phase 1.\n"
        "- Risk: keep scope tight.\n\n"
        "What changed because of memory:\n"
        "- Reply length/style: concise\n"
        "- Format: structured bullets\n"
    )

    parsed = parse_compare_output(output)

    assert parsed.prompt == "Draft: write a founder update"
    assert parsed.standard_answer == "We made progress this week."
    assert "shipped Phase 1" in parsed.memory_answer
    assert parsed.basis == ["Reply length/style: concise", "Format: structured bullets"]


def test_build_compare_share_card_writes_privacy_safe_png(fake_home):
    output = (
        "8mem Compare\n"
        "Prompt: Draft: write a founder update\n\n"
        "Standard answer:\n"
        "We made progress this week and are excited about what comes next.\n\n"
        "Answer shaped by what I know about you:\n"
        "- Progress: shipped Phase 1 without expanding scope.\n"
        "- Risk: keep stability ahead of polish.\n"
        "- Next: test with real users.\n\n"
        "What changed because of memory:\n"
        "- Reply length/style: concise\n"
        "- Format: structured bullets\n"
    )

    path = build_compare_share_card(output, user_id="card-user")

    assert path.exists()
    assert path.suffix == ".png"
    assert "card-user" in path.name
    with Image.open(Path(path)) as image:
        assert image.size == (1200, 900)
        assert image.format == "PNG"


def test_build_passport_share_card_writes_privacy_safe_png(fake_home):
    summary = (
        "8mem Passport\n\n"
        "Here's the memory I'm using for you:\n\n"
        "Status: Stable\n"
        "Active entries: 3\n"
        "Corrections tracked: 1\n\n"
        "Currently using:\n"
        "- Preference: Keep answers concise.\n"
        "- Correction: do not use emojis\n\n"
        "Memory status: Stable\n\n"
        "Trust basis:\n"
        "- I'm using 1 saved preference.\n"
        "- I'm also following 1 saved correction.\n"
    )

    parsed = parse_passport_summary(summary)
    path = build_passport_share_card(summary, user_id="passport-card-user")

    assert parsed.status == "Stable"
    assert parsed.active_entries == "3"
    assert parsed.current_items[0] == "Preference: Keep answers concise."
    assert path.exists()
    assert path.suffix == ".png"
    assert "passport-card-user" in path.name
    with Image.open(Path(path)) as image:
        assert image.size == (1200, 900)
        assert image.format == "PNG"


def test_empty_passport_is_not_share_card_eligible(fake_home):
    summary = (
        "8mem Passport\n\n"
        "Here's the memory I'm using for you:\n\n"
        "Status: No trusted memory yet\n"
        "Active entries: 0\n"
        "Corrections tracked: 0\n\n"
        "Currently using:\n"
        "- Nothing yet. Add one preference or correction to start shaping replies.\n"
    )

    assert is_passport_card_eligible(summary) is False


def test_weak_or_identical_compare_output_is_not_share_card_eligible(fake_home):
    output = (
        "8mem Compare\n"
        "Prompt: Draft: write a founder update in my style\n\n"
        "Standard answer:\n"
        "- Progress: shipped Phase 1.\n\n"
        "Answer shaped by what I know about you:\n"
        "- Progress: shipped Phase 1.\n\n"
        "What changed because of memory:\n"
        "- Reply length/style: detailed\n\n"
        "Memory signal is weak for this prompt.\n"
        "I don't have enough style or project signal yet to make this meaningfully different.\n"
    )

    parsed = parse_compare_output(output)

    assert parsed.weak_signal is True
    assert is_share_card_eligible(output) is False
    with pytest.raises(ValueError, match="not strong enough"):
        build_compare_share_card(output, user_id="weak-card-user")


def test_identical_compare_output_is_not_share_card_eligible_even_without_weak_copy(fake_home):
    output = (
        "8mem Compare\n"
        "Prompt: Draft: write a founder update in my style\n\n"
        "Standard answer:\n"
        "- Progress: shipped Phase 1.\n\n"
        "Answer shaped by what I know about you:\n"
        "- Progress: shipped Phase 1.\n\n"
        "What changed because of memory:\n"
        "- Preference: Give detailed explanations\n"
    )

    assert is_share_card_eligible(output) is False


def test_generic_detailed_memory_is_not_share_card_eligible(fake_home):
    output = (
        "8mem Compare\n"
        "Prompt: Draft: write a founder update in my style\n\n"
        "Standard answer:\n"
        "- Progress: We tightened execution.\n\n"
        "Answer shaped by what I know about you:\n"
        "- Progress: We kept execution moving while holding the line on stability.\n\n"
        "What changed because of memory:\n"
        "- Reply length/style: detailed\n"
        "- Format: long-form\n"
        "- Preference: Give detailed explanations\n"
    )

    assert is_share_card_eligible(output) is False


def test_card_ready_signal_after_first_three_basis_items_is_eligible(fake_home):
    output = (
        "8mem Compare\n"
        "Prompt: Draft: write a founder update in my style\n\n"
        "Standard answer:\n"
        "- Progress: We tightened execution.\n\n"
        "Answer shaped by what I know about you:\n"
        "- Progress: We kept execution moving while holding the line on stability.\n\n"
        "What changed because of memory:\n"
        "- Reply length/style: detailed\n"
        "- Format: long-form\n"
        "- Preference: Give detailed explanations\n"
        "- Preference: Prefers short, direct, structured as Progress / Risk / Next\n"
    )

    assert is_share_card_eligible(output) is True


def test_card_proof_items_are_human_readable_and_prioritized(fake_home):
    proof = build_card_proof_items(
        [
            "Reply length/style: detailed",
            "Format: long-form",
            "Project context: 8mem, an AI memory layer for visible, correctable, portable memory",
            "Project context: I care about execution speed, but not at the cost of stability",
            "Preference: Prefers short, direct, structured as Progress / Risk / Next",
            "Correction: do not assume I want generic motivational language",
        ]
    )

    assert proof == [
        "You care about speed without breaking stability",
        "You prefer Progress / Risk / Next updates",
        "Avoid generic founder-speak",
    ]
