"""Warren Buffett-style quality-value scoring.

Buffett buys wonderful businesses at fair prices: durable moats (high,
stable returns on equity and margins), conservative balance sheets (low
debt), owner earnings (strong free cash flow), and a margin of safety
versus a rough intrinsic value.
"""
from __future__ import annotations

from ..data import StockData
from ..scoring import (Signal, StrategyResult, combine, higher_better,
                       lower_better, verdict_from)


def _intrinsic_dcf(sd: StockData) -> tuple[float | None, float | None]:
    """Very rough owner-earnings DCF. Returns (intrinsic_per_share, margin_of_safety)."""
    fcf = sd.get("freeCashflow")
    shares = sd.get("sharesOutstanding")
    price = sd.price
    if not fcf or not shares or shares == 0 or not price:
        return None, None

    growth = sd.get("earningsGrowth")
    # Clamp growth into a sane band; default to a conservative 5%.
    g = 0.05 if growth is None else max(-0.05, min(0.12, growth))
    discount = 0.10          # required return
    terminal_g = 0.025       # perpetuity growth
    years = 10

    cash = fcf
    pv = 0.0
    for yr in range(1, years + 1):
        cash *= (1 + g)
        pv += cash / (1 + discount) ** yr
    terminal = (cash * (1 + terminal_g)) / (discount - terminal_g)
    pv += terminal / (1 + discount) ** years

    intrinsic_ps = pv / shares
    margin = (intrinsic_ps - price) / intrinsic_ps if intrinsic_ps else None
    return intrinsic_ps, margin


def evaluate(sd: StockData) -> StrategyResult:
    roe = sd.get("returnOnEquity")
    dte = sd.get("debtToEquity")           # yfinance reports as percent (e.g. 45 = 0.45x)
    gross = sd.get("grossMargins")
    op = sd.get("operatingMargins")
    fcf = sd.get("freeCashflow")
    mcap = sd.market_cap
    fcf_yield = (fcf / mcap) if (fcf and mcap) else None
    rev_growth = sd.get("revenueGrowth")
    pe = sd.get("trailingPE")
    current_ratio = sd.get("currentRatio")

    _, margin_of_safety = _intrinsic_dcf(sd)

    signals = [
        Signal("ROE", roe, higher_better(roe, 0.08, 0.25), 0.18,
               "return on equity, moat proxy"),
        Signal("Debt/Equity", dte, lower_better(dte, 30, 150), 0.15,
               "conservative balance sheet"),
        Signal("GrossMargin", gross, higher_better(gross, 0.20, 0.55), 0.10),
        Signal("OpMargin", op, higher_better(op, 0.08, 0.25), 0.12),
        Signal("FCF_Yield", fcf_yield, higher_better(fcf_yield, 0.01, 0.08), 0.15,
               "owner earnings"),
        Signal("RevGrowth", rev_growth, higher_better(rev_growth, 0.0, 0.15), 0.08),
        Signal("P/E", pe, lower_better(pe, 10, 35), 0.10, "fair price"),
        Signal("CurrentRatio", current_ratio, higher_better(current_ratio, 1.0, 2.0), 0.05),
        Signal("MarginOfSafety", margin_of_safety,
               higher_better(margin_of_safety, 0.0, 0.4), 0.07, "vs DCF intrinsic value"),
    ]
    score = combine(signals)
    return StrategyResult("Buffett", score, signals, verdict_from(score))
