"""
Yield Domain API endpoints.

Manages domain activation for yield/intent routing and revenue tracking.
"""
import json
from datetime import datetime, timedelta
from decimal import Decimal
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy import func, and_, or_, Integer, case, select
from sqlalchemy.orm import selectinload
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, get_current_user
from app.models.user import User
from app.models.yield_domain import YieldDomain, YieldTransaction, YieldPayout, AffiliatePartner
from app.config import get_settings

settings = get_settings()
from app.schemas.yield_domain import (
    YieldDomainCreate,
    YieldDomainUpdate,
    YieldDomainResponse,
    YieldDomainListResponse,
    YieldTransactionResponse,
    YieldTransactionListResponse,
    YieldPayoutResponse,
    YieldPayoutListResponse,
    YieldDashboardStats,
    YieldDashboardResponse,
    DomainYieldAnalysis,
    IntentAnalysis,
    YieldValueEstimate,
    AffiliatePartnerResponse,
    DNSVerificationResult,
    DNSSetupInstructions,
    ActivateYieldRequest,
    ActivateYieldResponse,
    YieldLandingPreview,
)
from app.services.intent_detector import (
    detect_domain_intent,
    estimate_domain_yield,
    get_intent_detector,
)
from app.services.yield_dns import verify_yield_dns
from app.services.telemetry import track_event

router = APIRouter(prefix="/yield", tags=["yield"])


# ============================================================================
# Intent Analysis (Public)
# ============================================================================

@router.post("/analyze", response_model=DomainYieldAnalysis)
async def analyze_domain_intent(
    domain: str = Query(..., min_length=3, description="Domain to analyze"),
):
    """
    Analyze a domain's intent and estimate yield potential.
    
    This endpoint is public - no authentication required.
    """
    analysis = estimate_domain_yield(domain)
    
    intent_result = detect_domain_intent(domain)
    
    return DomainYieldAnalysis(
        domain=domain,
        intent=IntentAnalysis(
            category=intent_result.category,
            subcategory=intent_result.subcategory,
            confidence=intent_result.confidence,
            keywords_matched=intent_result.keywords_matched,
            suggested_partners=intent_result.suggested_partners,
            monetization_potential=intent_result.monetization_potential,
        ),
        value=YieldValueEstimate(
            estimated_monthly_min=analysis["value"]["estimated_monthly_min"],
            estimated_monthly_max=analysis["value"]["estimated_monthly_max"],
            currency=analysis["value"]["currency"],
            potential=analysis["value"]["potential"],
            confidence=analysis["value"]["confidence"],
            geo=analysis["value"]["geo"],
        ),
        partners=analysis["partners"],
        monetization_potential=analysis["monetization_potential"],
    )


# ============================================================================
# Dashboard
# ============================================================================

@router.get("/dashboard", response_model=YieldDashboardResponse)
async def get_yield_dashboard(
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Get yield dashboard with stats, domains, and recent transactions.
    """
    # Get user's yield domains with partner relationship eagerly loaded
    result = await db.execute(
        select(YieldDomain)
        .options(selectinload(YieldDomain.partner))
        .where(YieldDomain.user_id == current_user.id)
        .order_by(YieldDomain.total_revenue.desc())
    )
    domains = list(result.scalars().all())
    
    # Calculate stats
    now = datetime.utcnow()
    month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    
    # Monthly stats from transactions (simplified for async)
    monthly_revenue = Decimal("0")
    monthly_clicks = 0
    monthly_conversions = 0
    
    if domains:
        domain_ids = [d.id for d in domains]
        monthly_result = await db.execute(
            select(
                func.coalesce(
                    func.sum(
                        case(
                            (YieldTransaction.status.in_(["confirmed", "paid"]), YieldTransaction.net_amount),
                            else_=0,
                        )
                    ),
                    0,
                ).label("revenue"),
                func.sum(
                    case(
                        (YieldTransaction.event_type == "click", 1),
                        else_=0,
                    )
                ).label("clicks"),
                func.sum(
                    case(
                        (
                            and_(
                                YieldTransaction.event_type.in_(["lead", "sale"]),
                                YieldTransaction.status.in_(["confirmed", "paid"]),
                            ),
                            1,
                        ),
                        else_=0,
                    )
                ).label("conversions"),
            ).where(
                YieldTransaction.yield_domain_id.in_(domain_ids),
                YieldTransaction.created_at >= month_start,
            )
        )
        monthly_stats = monthly_result.first()
        if monthly_stats:
            monthly_revenue = monthly_stats.revenue or Decimal("0")
            monthly_clicks = monthly_stats.clicks or 0
            monthly_conversions = monthly_stats.conversions or 0
    
    # Aggregate domain stats
    total_active = sum(1 for d in domains if d.status == "active")
    total_pending = sum(1 for d in domains if d.status in ["pending", "verifying"])
    lifetime_revenue = sum(d.total_revenue for d in domains)
    lifetime_clicks = sum(d.total_clicks for d in domains)
    lifetime_conversions = sum(d.total_conversions for d in domains)
    
    # Pending payout
    pending_payout = Decimal("0")
    if domains:
        domain_ids = [d.id for d in domains]
        pending_result = await db.execute(
            select(func.coalesce(func.sum(YieldTransaction.net_amount), 0)).where(
                YieldTransaction.yield_domain_id.in_(domain_ids),
        YieldTransaction.status == "confirmed",
        YieldTransaction.paid_at.is_(None),
            )
        )
        pending_payout = pending_result.scalar() or Decimal("0")
    
    # Get recent transactions
    recent_txs = []
    if domains:
        domain_ids = [d.id for d in domains]
        recent_result = await db.execute(
            select(YieldTransaction)
            .where(YieldTransaction.yield_domain_id.in_(domain_ids))
            .order_by(YieldTransaction.created_at.desc())
            .limit(10)
        )
        recent_txs = list(recent_result.scalars().all())
    
    # Top performing domains
    top_domains = sorted(domains, key=lambda d: d.total_revenue, reverse=True)[:5]
    
    stats = YieldDashboardStats(
        total_domains=len(domains),
        active_domains=total_active,
        pending_domains=total_pending,
        monthly_revenue=monthly_revenue,
        monthly_clicks=monthly_clicks,
        monthly_conversions=monthly_conversions,
        lifetime_revenue=lifetime_revenue,
        lifetime_clicks=lifetime_clicks,
        lifetime_conversions=lifetime_conversions,
        pending_payout=pending_payout,
        next_payout_date=(month_start + timedelta(days=32)).replace(day=1),
        currency="CHF",
    )
    
    return YieldDashboardResponse(
        stats=stats,
        domains=[_domain_to_response(d) for d in domains],
        recent_transactions=[_tx_to_response(tx) for tx in recent_txs],
        top_domains=[_domain_to_response(d) for d in top_domains],
    )


# ============================================================================
# Domain Management
# ============================================================================

@router.get("/domains", response_model=YieldDomainListResponse)
async def list_yield_domains(
    status: Optional[str] = Query(None, description="Filter by status"),
    limit: int = Query(50, le=100),
    offset: int = Query(0, ge=0),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    List user's yield domains.
    """
    query = select(YieldDomain).where(YieldDomain.user_id == current_user.id)
    
    if status:
        query = query.where(YieldDomain.status == status)
    
    # Get total count
    count_result = await db.execute(
        select(func.count(YieldDomain.id)).where(YieldDomain.user_id == current_user.id)
    )
    total = count_result.scalar() or 0
    
    # Get domains
    result = await db.execute(
        query.order_by(YieldDomain.created_at.desc()).offset(offset).limit(limit)
    )
    domains = list(result.scalars().all())
    
    # Aggregates from all domains
    all_result = await db.execute(
        select(YieldDomain).where(YieldDomain.user_id == current_user.id)
    )
    all_domains = list(all_result.scalars().all())
    total_active = sum(1 for d in all_domains if d.status == "active")
    total_revenue = sum(d.total_revenue for d in all_domains)
    total_clicks = sum(d.total_clicks for d in all_domains)
    
    return YieldDomainListResponse(
        domains=[_domain_to_response(d) for d in domains],
        total=total,
        total_active=total_active,
        total_revenue=total_revenue,
        total_clicks=total_clicks,
    )


@router.get("/domains/{domain_id}", response_model=YieldDomainResponse)
async def get_yield_domain(
    domain_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Get details of a specific yield domain.
    """
    result = await db.execute(
        select(YieldDomain).where(
        YieldDomain.id == domain_id,
        YieldDomain.user_id == current_user.id,
        )
    )
    domain = result.scalar_one_or_none()
    
    if not domain:
        raise HTTPException(status_code=404, detail="Yield domain not found")
    
    return _domain_to_response(domain)


@router.post("/activate", response_model=ActivateYieldResponse)
async def activate_domain_for_yield(
    request: ActivateYieldRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Activate a domain for yield/intent routing.
    
    SECURITY: Domain must be in user's portfolio AND DNS-verified.
    This creates the yield domain record and returns DNS setup instructions.
    """
    from app.models.portfolio import PortfolioDomain
    from app.models.subscription import Subscription, SubscriptionTier
    
    domain = request.domain.lower().strip()
    
    # SECURITY CHECK 1: Domain must be in user's portfolio
    portfolio_result = await db.execute(
        select(PortfolioDomain).where(
            PortfolioDomain.domain == domain,
            PortfolioDomain.user_id == current_user.id,
        )
    )
    portfolio_domain = portfolio_result.scalar_one_or_none()
    
    if not portfolio_domain:
        raise HTTPException(
            status_code=403,
            detail="Domain must be in your portfolio before activating Yield. Add it to your portfolio first.",
        )
    
    # SECURITY CHECK 2: Domain must be DNS-verified
    if not portfolio_domain.is_dns_verified:
        raise HTTPException(
            status_code=403,
            detail="Domain must be DNS-verified before activating Yield. Verify ownership in your portfolio first.",
        )
    
    # SECURITY CHECK 3: Domain must not be sold
    if portfolio_domain.is_sold:
        raise HTTPException(
            status_code=400,
            detail="Cannot activate Yield for a sold domain.",
        )

    # SECURITY CHECK 4: Tier gating + limits
    sub_result = await db.execute(select(Subscription).where(Subscription.user_id == current_user.id))
    subscription = sub_result.scalar_one_or_none()
    tier = subscription.tier if subscription else SubscriptionTier.SCOUT
    tier_value = tier.value if hasattr(tier, "value") else str(tier)

    # Check if tier has yield feature
    from app.models.subscription import TIER_CONFIG
    tier_config = TIER_CONFIG.get(tier, {})
    has_yield = tier_config.get("features", {}).get("yield", False)
    
    if not has_yield:
        raise HTTPException(
            status_code=403,
            detail="Yield is available on Tycoon plan only. Upgrade to unlock.",
        )

    # Yield limits: Trader = 10, Tycoon = unlimited
    max_yield_domains = 10 if tier_value == "trader" else 10_000_000
    user_domain_count = (
        await db.execute(
            select(func.count(YieldDomain.id)).where(YieldDomain.user_id == current_user.id)
        )
    ).scalar() or 0
    if user_domain_count >= max_yield_domains:
        raise HTTPException(
            status_code=403,
            detail=f"Yield domain limit reached for your plan ({max_yield_domains}).",
        )
    
    # Check if domain already exists in yield system
    existing_result = await db.execute(
        select(YieldDomain).where(YieldDomain.domain == domain)
    )
    existing = existing_result.scalar_one_or_none()
    if existing:
        if existing.user_id == current_user.id:
            raise HTTPException(
                status_code=400, 
                detail="Domain already activated for yield"
            )
        else:
            raise HTTPException(
                status_code=400, 
                detail="Domain is already registered by another user"
            )
    
    # Analyze domain intent
    intent_result = detect_domain_intent(domain)
    value_estimate = get_intent_detector().estimate_value(domain)

    # Generate landing page config (Tycoon-only yield requirement)
    # No fallback: if the LLM gateway is unavailable, activation must fail.
    from app.services.llm_vision import generate_yield_landing
    landing_cfg, landing_model = await generate_yield_landing(domain)
    
    # Create yield domain record
    yield_domain = YieldDomain(
        user_id=current_user.id,
        domain=domain,
        detected_intent=f"{intent_result.category}_{intent_result.subcategory}" if intent_result.subcategory else intent_result.category,
        intent_confidence=intent_result.confidence,
        intent_keywords=json.dumps(intent_result.keywords_matched),
        status="pending",
        landing_config_json=landing_cfg.model_dump_json(),
        landing_template=landing_cfg.template,
        landing_headline=landing_cfg.headline,
        landing_intro=landing_cfg.seo_intro,
        landing_cta_label=landing_cfg.cta_label,
        landing_model=landing_model,
        landing_generated_at=datetime.utcnow(),
    )
    
    # Find best matching partner
    if intent_result.suggested_partners:
        partner_result = await db.execute(
            select(AffiliatePartner).where(
            AffiliatePartner.slug == intent_result.suggested_partners[0],
            AffiliatePartner.is_active == True,
            )
        )
        partner = partner_result.scalar_one_or_none()
        if partner:
            yield_domain.partner_id = partner.id
            yield_domain.active_route = partner.slug
    
    db.add(yield_domain)
    await db.commit()
    await db.refresh(yield_domain)
    
    # Create DNS instructions
    yield_nameservers = settings.yield_nameserver_list
    if not yield_nameservers:
        raise HTTPException(status_code=500, detail="Yield nameservers are not configured on server.")
    dns_instructions = DNSSetupInstructions(
        domain=domain,
        nameservers=yield_nameservers,
        cname_host="@",
        cname_target=settings.yield_cname_target,
        verification_url=f"{settings.site_url}/api/v1/yield/domains/{yield_domain.id}/verify",
    )
    
    return ActivateYieldResponse(
        domain_id=yield_domain.id,
        domain=domain,
        status=yield_domain.status,
        intent=IntentAnalysis(
            category=intent_result.category,
            subcategory=intent_result.subcategory,
            confidence=intent_result.confidence,
            keywords_matched=intent_result.keywords_matched,
            suggested_partners=intent_result.suggested_partners,
            monetization_potential=intent_result.monetization_potential,
        ),
        value_estimate=YieldValueEstimate(
            estimated_monthly_min=value_estimate["estimated_monthly_min"],
            estimated_monthly_max=value_estimate["estimated_monthly_max"],
            currency=value_estimate["currency"],
            potential=value_estimate["potential"],
            confidence=value_estimate["confidence"],
            geo=value_estimate["geo"],
        ),
        dns_instructions=dns_instructions,
        landing=YieldLandingPreview(
            template=yield_domain.landing_template or "generic",
            headline=yield_domain.landing_headline or "",
            seo_intro=yield_domain.landing_intro or "",
            cta_label=yield_domain.landing_cta_label or "View offers",
            model=getattr(yield_domain, "landing_model", None),
            generated_at=getattr(yield_domain, "landing_generated_at", None),
        ),
        message="Domain registered! Point your DNS to our nameservers to complete activation.",
    )


@router.post("/domains/{domain_id}/verify", response_model=DNSVerificationResult)
async def verify_domain_dns(
    domain_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Verify DNS configuration for a yield domain.
    """
    result = await db.execute(
        select(YieldDomain).where(
        YieldDomain.id == domain_id,
        YieldDomain.user_id == current_user.id,
        )
    )
    domain = result.scalar_one_or_none()
    
    if not domain:
        raise HTTPException(status_code=404, detail="Yield domain not found")
    
    # Production-grade DNS check
    check = verify_yield_dns(
        domain=domain.domain,
        expected_nameservers=settings.yield_nameserver_list,
        cname_target=settings.yield_cname_target,
    )
    verified = check.verified
    actual_ns = check.actual_ns
    error = check.error
    
    # Update domain status
    if verified and not domain.dns_verified:
        domain.dns_verified = True
        domain.dns_verified_at = datetime.utcnow()
        domain.connected_at = domain.dns_verified_at
        domain.status = "active"
        domain.activated_at = datetime.utcnow()

        await track_event(
            db,
            event_name="yield_connected",
            request=None,
            user_id=current_user.id,
            is_authenticated=True,
            source="terminal",
            domain=domain.domain,
            yield_domain_id=domain.id,
            metadata={"method": check.method, "cname_ok": check.cname_ok, "actual_ns": check.actual_ns},
        )
        await db.commit()
    
    return DNSVerificationResult(
        domain=domain.domain,
        verified=verified,
        method=check.method,
        expected_ns=settings.yield_nameserver_list,
        actual_ns=check.actual_ns,
        actual_a=check.actual_a,
        cname_ok=check.cname_ok if verified else False,
        error=error,
        checked_at=datetime.utcnow(),
    )


@router.patch("/domains/{domain_id}", response_model=YieldDomainResponse)
async def update_yield_domain(
    domain_id: int,
    update: YieldDomainUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Update yield domain settings.
    """
    result = await db.execute(
        select(YieldDomain).where(
        YieldDomain.id == domain_id,
        YieldDomain.user_id == current_user.id,
        )
    )
    domain = result.scalar_one_or_none()
    
    if not domain:
        raise HTTPException(status_code=404, detail="Yield domain not found")
    
    # Apply updates
    if update.active_route is not None:
        # Validate partner exists
        partner_result = await db.execute(
            select(AffiliatePartner).where(
            AffiliatePartner.slug == update.active_route,
            AffiliatePartner.is_active == True,
            )
        )
        partner = partner_result.scalar_one_or_none()
        if not partner:
            raise HTTPException(status_code=400, detail="Invalid partner route")
        domain.active_route = update.active_route
        domain.partner_id = partner.id
    
    if update.landing_page_url is not None:
        domain.landing_page_url = update.landing_page_url
    
    if update.status is not None:
        if update.status == "paused":
            domain.status = "paused"
            domain.paused_at = datetime.utcnow()
        elif update.status == "active" and domain.dns_verified:
            domain.status = "active"
            domain.paused_at = None
    
    await db.commit()
    await db.refresh(domain)
    
    return _domain_to_response(domain)


@router.delete("/domains/{domain_id}")
async def delete_yield_domain(
    domain_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    Remove a domain from yield program.
    """
    result = await db.execute(
        select(YieldDomain).where(
        YieldDomain.id == domain_id,
        YieldDomain.user_id == current_user.id,
        )
    )
    domain = result.scalar_one_or_none()
    
    if not domain:
        raise HTTPException(status_code=404, detail="Yield domain not found")
    
    await db.delete(domain)
    await db.commit()
    
    return {"message": "Yield domain removed"}


# ============================================================================
# Transactions
# ============================================================================

@router.get("/transactions", response_model=YieldTransactionListResponse)
async def list_transactions(
    domain_id: Optional[int] = Query(None),
    status: Optional[str] = Query(None),
    limit: int = Query(50, le=100),
    offset: int = Query(0, ge=0),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    List yield transactions for user's domains.
    """
    # Get user's domain IDs
    domain_ids_result = await db.execute(
        select(YieldDomain.id).where(YieldDomain.user_id == current_user.id)
    )
    domain_ids = [row[0] for row in domain_ids_result.all()]
    
    if not domain_ids:
        return YieldTransactionListResponse(
            transactions=[],
            total=0,
            total_gross=Decimal("0"),
            total_net=Decimal("0"),
        )
    
    query = select(YieldTransaction).where(
        YieldTransaction.yield_domain_id.in_(domain_ids)
    )
    
    if domain_id:
        query = query.where(YieldTransaction.yield_domain_id == domain_id)
    
    if status:
        query = query.where(YieldTransaction.status == status)
    
    # Get count
    count_query = select(func.count(YieldTransaction.id)).where(
        YieldTransaction.yield_domain_id.in_(domain_ids)
    )
    if domain_id:
        count_query = count_query.where(YieldTransaction.yield_domain_id == domain_id)
    if status:
        count_query = count_query.where(YieldTransaction.status == status)
    
    count_result = await db.execute(count_query)
    total = count_result.scalar() or 0
    
    # Get transactions
    result = await db.execute(
        query.order_by(YieldTransaction.created_at.desc()).offset(offset).limit(limit)
    )
    transactions = list(result.scalars().all())
    
    # Aggregates
    total_gross = sum(tx.gross_amount for tx in transactions)
    total_net = sum(tx.net_amount for tx in transactions)
    
    return YieldTransactionListResponse(
        transactions=[_tx_to_response(tx) for tx in transactions],
        total=total,
        total_gross=total_gross,
        total_net=total_net,
    )


# ============================================================================
# Payouts
# ============================================================================

@router.get("/payouts", response_model=YieldPayoutListResponse)
async def list_payouts(
    status: Optional[str] = Query(None),
    limit: int = Query(20, le=50),
    offset: int = Query(0, ge=0),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """
    List user's yield payouts.
    """
    query = select(YieldPayout).where(YieldPayout.user_id == current_user.id)
    
    if status:
        query = query.where(YieldPayout.status == status)
    
    # Get count
    count_result = await db.execute(
        select(func.count(YieldPayout.id)).where(YieldPayout.user_id == current_user.id)
    )
    total = count_result.scalar() or 0
    
    # Get payouts
    result = await db.execute(
        query.order_by(YieldPayout.created_at.desc()).offset(offset).limit(limit)
    )
    payouts = list(result.scalars().all())
    
    # Aggregates
    total_paid = sum(p.amount for p in payouts if p.status == "completed")
    total_pending = sum(p.amount for p in payouts if p.status in ["pending", "processing"])
    
    return YieldPayoutListResponse(
        payouts=[_payout_to_response(p) for p in payouts],
        total=total,
        total_paid=total_paid,
        total_pending=total_pending,
    )


# ============================================================================
# Partners (Public info)
# ============================================================================

@router.get("/partners", response_model=list[AffiliatePartnerResponse])
async def list_partners(
    category: Optional[str] = Query(None, description="Filter by intent category"),
    db: AsyncSession = Depends(get_db),
):
    """
    List available affiliate partners.
    """
    result = await db.execute(
        select(AffiliatePartner)
        .where(AffiliatePartner.is_active == True)
        .order_by(AffiliatePartner.priority.desc())
    )
    partners = list(result.scalars().all())
    
    # Filter by category if specified
    if category:
        partners = [p for p in partners if category in p.intent_list]
    
    return [
        AffiliatePartnerResponse(
            slug=p.slug,
            name=p.name,
            network=p.network,
            intent_categories=p.intent_list,
            geo_countries=p.country_list,
            payout_type=p.payout_type,
            description=p.description,
            logo_url=p.logo_url,
        )
        for p in partners
    ]


# ============================================================================
# Helpers
# ============================================================================

def _domain_to_response(domain: YieldDomain) -> YieldDomainResponse:
    """Convert YieldDomain model to response schema."""
    # Safely get partner name
    partner_name = None
    try:
        if domain.partner:
            partner_name = domain.partner.name
    except Exception:
        pass
    
    return YieldDomainResponse(
        id=domain.id,
        domain=domain.domain,
        status=domain.status,
        detected_intent=domain.detected_intent,
        intent_confidence=domain.intent_confidence,
        active_route=domain.active_route,
        partner_name=partner_name,
        landing_template=getattr(domain, "landing_template", None),
        landing_headline=getattr(domain, "landing_headline", None),
        landing_intro=getattr(domain, "landing_intro", None),
        landing_cta_label=getattr(domain, "landing_cta_label", None),
        landing_model=getattr(domain, "landing_model", None),
        landing_generated_at=getattr(domain, "landing_generated_at", None),
        dns_verified=domain.dns_verified,
        dns_verified_at=domain.dns_verified_at,
        connected_at=getattr(domain, "connected_at", None),
        total_clicks=domain.total_clicks,
        total_conversions=domain.total_conversions,
        total_revenue=domain.total_revenue,
        currency=domain.currency,
        activated_at=domain.activated_at,
        created_at=domain.created_at,
    )


def _tx_to_response(tx: YieldTransaction) -> YieldTransactionResponse:
    """Convert YieldTransaction model to response schema."""
    return YieldTransactionResponse(
        id=tx.id,
        event_type=tx.event_type,
        partner_slug=tx.partner_slug,
        click_id=getattr(tx, "click_id", None),
        gross_amount=tx.gross_amount,
        net_amount=tx.net_amount,
        currency=tx.currency,
        status=tx.status,
        geo_country=tx.geo_country,
        created_at=tx.created_at,
        confirmed_at=tx.confirmed_at,
    )


def _payout_to_response(payout: YieldPayout) -> YieldPayoutResponse:
    """Convert YieldPayout model to response schema."""
    return YieldPayoutResponse(
        id=payout.id,
        amount=payout.amount,
        currency=payout.currency,
        period_start=payout.period_start,
        period_end=payout.period_end,
        transaction_count=payout.transaction_count,
        status=payout.status,
        payment_method=payout.payment_method,
        payment_reference=payout.payment_reference,
        created_at=payout.created_at,
        completed_at=payout.completed_at,
    )



