"""Picker earnings ledger — one row per delivered order, equal to that
order's delivery fee plus its picking fee plus its package fee (the picker
is compensated for the transport, the labor of gathering the order, and the
packaging materials they supply). Admin authorizes payout in batches (marks
a picker's pending earnings as paid); pickers choose their own payout
cadence."""

from datetime import datetime, timezone
from decimal import Decimal

from accounts.supabase_client import get_client


def record_earning_if_delivered(order):
    """Call whenever an order's status changes to 'delivered' — creates a
    pending earning for the assigned picker equal to that order's delivery
    fee + picking fee, minus the platform's commission (if any), if one
    doesn't already exist for this order (unique on order_id). The
    commission percentage is locked in at earn-time so a later admin change
    never silently reprices earnings that already happened."""
    if order.get('status') != 'delivered' or not order.get('picker_id'):
        return
    client = get_client()
    existing = client.table('pickker_picker_earnings').select('id').eq('order_id', order['id']).execute()
    if existing.data:
        return

    from .site_settings import get_platform_commission_pct

    gross = Decimal(str(order['delivery_fee'])) + Decimal(str(order.get('picking_fee') or 0)) + Decimal(str(order.get('package_fee') or 0))
    commission_pct = Decimal(str(get_platform_commission_pct()))
    commission_amount = (gross * commission_pct / Decimal('100')).quantize(Decimal('0.01'))
    net_amount = gross - commission_amount
    client.table('pickker_picker_earnings').insert({
        'picker_id': order['picker_id'],
        'order_id': order['id'],
        'amount': str(net_amount),
        'gross_amount': str(gross),
        'commission_pct': str(commission_pct),
        'commission_amount': str(commission_amount),
    }).execute()


def get_picker_earnings_summary(picker_id):
    rows = get_client().table('pickker_picker_earnings').select('*').eq('picker_id', picker_id).execute().data
    pending = sum((Decimal(str(r['amount'])) for r in rows if r['status'] == 'pending'), Decimal('0'))
    paid = sum((Decimal(str(r['amount'])) for r in rows if r['status'] == 'paid'), Decimal('0'))
    return {
        'pending_amount': pending,
        'pending_count': sum(1 for r in rows if r['status'] == 'pending'),
        'paid_amount': paid,
        'lifetime_amount': pending + paid,
    }


def get_earnings_history(picker_id, limit=20):
    return (
        get_client()
        .table('pickker_picker_earnings')
        .select('*')
        .eq('picker_id', picker_id)
        .order('earned_at', desc=True)
        .limit(limit)
        .execute()
        .data
    )


def get_picker_earnings_summary_and_history(picker_id, history_limit=10):
    """Same numbers as calling get_picker_earnings_summary() and
    get_earnings_history() separately, from one fetch instead of two —
    both read the same pickker_picker_earnings rows for the same picker,
    so picker_home (loaded on every picker dashboard visit) doesn't pay
    for the round trip twice. The summary genuinely needs every row (to
    total pending/paid across a picker's whole history, not just the
    most recent ones); ordering that same unbounded fetch by earned_at
    desc lets the history list just be its own first `history_limit`
    rows, no separate query."""
    rows = (
        get_client()
        .table('pickker_picker_earnings')
        .select('*')
        .eq('picker_id', picker_id)
        .order('earned_at', desc=True)
        .execute()
        .data
    )
    pending = sum((Decimal(str(r['amount'])) for r in rows if r['status'] == 'pending'), Decimal('0'))
    paid = sum((Decimal(str(r['amount'])) for r in rows if r['status'] == 'paid'), Decimal('0'))
    summary = {
        'pending_amount': pending,
        'pending_count': sum(1 for r in rows if r['status'] == 'pending'),
        'paid_amount': paid,
        'lifetime_amount': pending + paid,
    }
    return summary, rows[:history_limit]


def set_payout_frequency(picker_id, frequency):
    if frequency not in ('daily', 'weekly'):
        return
    get_client().table('pickker_picker_profiles').update({'payout_frequency': frequency}).eq('user_id', picker_id).execute()


def pay_out_picker(picker_id, admin_id):
    """Marks all of a picker's currently-pending earnings as paid in one
    settlement action."""
    now = datetime.now(timezone.utc).isoformat()
    get_client().table('pickker_picker_earnings').update({
        'status': 'paid', 'paid_at': now, 'paid_by': admin_id,
    }).eq('picker_id', picker_id).eq('status', 'pending').execute()


def get_all_pickers_earnings_overview():
    """For the admin payout page — every picker with any earnings history,
    plus their chosen payout cadence, sorted by who's owed the most."""
    client = get_client()
    earnings = client.table('pickker_picker_earnings').select('*').execute().data
    by_picker = {}
    for e in earnings:
        by_picker.setdefault(e['picker_id'], []).append(e)

    picker_ids = list(by_picker.keys())
    if not picker_ids:
        return []

    users_by_id = {
        u['id']: u for u in
        client.table('pickker_users').select('id, first_name, last_name, email').in_('id', picker_ids).execute().data
    }
    profiles_by_id = {
        p['user_id']: p for p in
        client.table('pickker_picker_profiles').select('user_id, payout_frequency').in_('user_id', picker_ids).execute().data
    }

    overview = []
    for picker_id, rows in by_picker.items():
        user = users_by_id.get(picker_id)
        profile = profiles_by_id.get(picker_id, {})
        pending = sum((Decimal(str(r['amount'])) for r in rows if r['status'] == 'pending'), Decimal('0'))
        paid = sum((Decimal(str(r['amount'])) for r in rows if r['status'] == 'paid'), Decimal('0'))
        overview.append({
            'picker_id': picker_id,
            'name': f"{user['first_name']} {user['last_name']}".strip() if user else 'Unknown',
            'email': user['email'] if user else '',
            'payout_frequency': profile.get('payout_frequency', 'weekly'),
            'pending_amount': pending,
            'pending_count': sum(1 for r in rows if r['status'] == 'pending'),
            'paid_amount': paid,
        })
    overview.sort(key=lambda o: o['pending_amount'], reverse=True)
    return overview
