"""Unit tests for fundamental_service — unavailable_fields persistence."""

from __future__ import annotations

import json

import pytest
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine

from app.database import Base
from app.models.ticker import Ticker
from app.services import fundamental_service

# Use a dedicated engine so commit/refresh work without conflicting
# with the conftest transactional session.
_engine = create_async_engine("sqlite+aiosqlite://", echo=False)
_session_factory = async_sessionmaker(_engine, class_=AsyncSession, expire_on_commit=False)


@pytest.fixture(autouse=True)
async def _setup_tables():
    async with _engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    yield
    async with _engine.begin() as conn:
        await conn.run_sync(Base.metadata.drop_all)


@pytest.fixture
async def session() -> AsyncSession:
    async with _session_factory() as s:
        yield s


@pytest.fixture
async def ticker(session: AsyncSession) -> Ticker:
    """Create a test ticker."""
    t = Ticker(symbol="AAPL")
    session.add(t)
    await session.commit()
    await session.refresh(t)
    return t


@pytest.mark.asyncio
async def test_store_fundamental_persists_unavailable_fields(
    session: AsyncSession, ticker: Ticker
):
    """unavailable_fields dict is serialized to JSON and stored."""
    fields = {"pe_ratio": "requires paid plan", "revenue_growth": "requires paid plan"}

    record = await fundamental_service.store_fundamental(
        session,
        symbol="AAPL",
        pe_ratio=None,
        revenue_growth=None,
        market_cap=1_000_000.0,
        unavailable_fields=fields,
    )

    assert json.loads(record.unavailable_fields_json) == fields


@pytest.mark.asyncio
async def test_store_fundamental_defaults_to_empty_dict(
    session: AsyncSession, ticker: Ticker
):
    """When unavailable_fields is not provided, column defaults to '{}'."""
    record = await fundamental_service.store_fundamental(
        session,
        symbol="AAPL",
        pe_ratio=25.0,
    )

    assert json.loads(record.unavailable_fields_json) == {}


@pytest.mark.asyncio
async def test_store_fundamental_updates_unavailable_fields(
    session: AsyncSession, ticker: Ticker
):
    """Updating an existing record also updates unavailable_fields_json."""
    # First store
    await fundamental_service.store_fundamental(
        session,
        symbol="AAPL",
        pe_ratio=None,
        unavailable_fields={"pe_ratio": "requires paid plan"},
    )

    # Second store — fields now available
    record = await fundamental_service.store_fundamental(
        session,
        symbol="AAPL",
        pe_ratio=25.0,
        unavailable_fields={},
    )

    assert json.loads(record.unavailable_fields_json) == {}
