"""
Coupon Management Endpoints for Mitai Jinkendo

Handles coupon CRUD (admin) and redemption (users).
"""
from datetime import datetime, timedelta
from typing import Optional
from fastapi import APIRouter, HTTPException, Depends

from db import get_db, get_cursor, r2d
from auth import require_auth, require_admin

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


@router.get("")
def list_coupons(session: dict = Depends(require_admin)):
    """Admin: List all coupons with redemption stats."""
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute("""
            SELECT
                c.*,
                t.name as tier_name,
                (SELECT COUNT(*) FROM coupon_redemptions WHERE coupon_id = c.id) as redemptions
            FROM coupons c
            LEFT JOIN tiers t ON t.id = c.tier_id
            ORDER BY c.created DESC
        """)
        return [r2d(r) for r in cur.fetchall()]


@router.post("")
def create_coupon(data: dict, session: dict = Depends(require_admin)):
    """
    Admin: Create new coupon.

    Required fields:
    - code: Unique coupon code
    - type: 'single_use', 'period', or 'wellpass'
    - tier_id: Target tier
    - duration_days: For period/wellpass coupons

    Optional fields:
    - max_redemptions: NULL = unlimited
    - valid_from, valid_until: Validity period
    - description: Internal note
    """
    code = data.get('code', '').strip().upper()
    coupon_type = data.get('type')
    tier_id = data.get('tier_id')
    duration_days = data.get('duration_days')
    max_redemptions = data.get('max_redemptions')
    valid_from = data.get('valid_from')
    valid_until = data.get('valid_until')
    description = data.get('description', '')

    if not code:
        raise HTTPException(400, "Coupon-Code fehlt")
    if coupon_type not in ['single_use', 'period', 'wellpass']:
        raise HTTPException(400, "Ungültiger Coupon-Typ")
    if not tier_id:
        raise HTTPException(400, "Tier fehlt")
    if coupon_type in ['period', 'wellpass'] and not duration_days:
        raise HTTPException(400, "duration_days fehlt für period/wellpass Coupons")

    with get_db() as conn:
        cur = get_cursor(conn)

        # Check if code already exists
        cur.execute("SELECT id FROM coupons WHERE code = %s", (code,))
        if cur.fetchone():
            raise HTTPException(400, f"Coupon-Code '{code}' existiert bereits")

        # Create coupon
        cur.execute("""
            INSERT INTO coupons (
                code, type, tier_id, duration_days, max_redemptions,
                valid_from, valid_until, description, created_by
            )
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING id
        """, (
            code, coupon_type, tier_id, duration_days, max_redemptions,
            valid_from, valid_until, description, session['profile_id']
        ))

        coupon_id = cur.fetchone()['id']
        conn.commit()

        return {"ok": True, "id": coupon_id, "code": code}


@router.put("/{coupon_id}")
def update_coupon(coupon_id: str, data: dict, session: dict = Depends(require_admin)):
    """Admin: Update coupon."""
    with get_db() as conn:
        cur = get_cursor(conn)

        updates = []
        values = []

        if 'active' in data:
            updates.append('active = %s')
            values.append(data['active'])
        if 'max_redemptions' in data:
            updates.append('max_redemptions = %s')
            values.append(data['max_redemptions'])
        if 'valid_until' in data:
            updates.append('valid_until = %s')
            values.append(data['valid_until'])
        if 'description' in data:
            updates.append('description = %s')
            values.append(data['description'])

        if not updates:
            return {"ok": True}

        updates.append('updated = CURRENT_TIMESTAMP')
        values.append(coupon_id)

        cur.execute(
            f"UPDATE coupons SET {', '.join(updates)} WHERE id = %s",
            values
        )
        conn.commit()

        return {"ok": True}


@router.delete("/{coupon_id}")
def delete_coupon(coupon_id: str, session: dict = Depends(require_admin)):
    """Admin: Delete coupon (soft-delete: set active=false)."""
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute("UPDATE coupons SET active = false WHERE id = %s", (coupon_id,))
        conn.commit()
        return {"ok": True}


@router.get("/{coupon_id}/redemptions")
def get_coupon_redemptions(coupon_id: str, session: dict = Depends(require_admin)):
    """Admin: Get all redemptions for a coupon."""
    with get_db() as conn:
        cur = get_cursor(conn)
        cur.execute("""
            SELECT
                cr.id,
                cr.redeemed_at,
                p.name as profile_name,
                p.email as profile_email,
                ag.valid_from,
                ag.valid_until,
                ag.is_active
            FROM coupon_redemptions cr
            JOIN profiles p ON p.id = cr.profile_id
            LEFT JOIN access_grants ag ON ag.id = cr.access_grant_id
            WHERE cr.coupon_id = %s
            ORDER BY cr.redeemed_at DESC
        """, (coupon_id,))
        return [r2d(r) for r in cur.fetchall()]


@router.post("/redeem")
def redeem_coupon(data: dict, session: dict = Depends(require_auth)):
    """
    User: Redeem a coupon code.

    Creates an access_grant and handles Wellpass pause/resume logic.
    """
    code = data.get('code', '').strip().upper()
    if not code:
        raise HTTPException(400, "Coupon-Code fehlt")

    profile_id = session['profile_id']

    with get_db() as conn:
        cur = get_cursor(conn)

        # Get coupon
        cur.execute("""
            SELECT * FROM coupons
            WHERE code = %s AND active = true
        """, (code,))
        coupon = cur.fetchone()

        if not coupon:
            raise HTTPException(404, "Ungültiger Coupon-Code")

        # Check validity period
        now = datetime.now()
        if coupon['valid_from'] and now < coupon['valid_from']:
            raise HTTPException(400, "Coupon noch nicht gültig")
        if coupon['valid_until'] and now > coupon['valid_until']:
            raise HTTPException(400, "Coupon abgelaufen")

        # Check max redemptions
        if coupon['max_redemptions'] is not None:
            if coupon['redemption_count'] >= coupon['max_redemptions']:
                raise HTTPException(400, "Coupon bereits vollständig eingelöst")

        # Check if user already redeemed this coupon
        cur.execute("""
            SELECT id FROM coupon_redemptions
            WHERE coupon_id = %s AND profile_id = %s
        """, (coupon['id'], profile_id))
        if cur.fetchone():
            raise HTTPException(400, "Du hast diesen Coupon bereits eingelöst")

        # Create access grant
        valid_from = now
        valid_until = now + timedelta(days=coupon['duration_days']) if coupon['duration_days'] else None

        # Wellpass logic: Pause existing personal grants
        if coupon['type'] == 'wellpass':
            cur.execute("""
                SELECT id, valid_until
                FROM access_grants
                WHERE profile_id = %s
                  AND is_active = true
                  AND granted_by != 'wellpass'
                  AND valid_until > CURRENT_TIMESTAMP
            """, (profile_id,))
            active_grants = cur.fetchall()

            for grant in active_grants:
                # Calculate remaining days
                remaining = (grant['valid_until'] - now).days
                # Pause grant
                cur.execute("""
                    UPDATE access_grants
                    SET is_active = false,
                        paused_at = CURRENT_TIMESTAMP,
                        remaining_days = %s
                    WHERE id = %s
                """, (remaining, grant['id']))

        # Insert access grant
        cur.execute("""
            INSERT INTO access_grants (
                profile_id, tier_id, granted_by, coupon_id,
                valid_from, valid_until, is_active
            )
            VALUES (%s, %s, %s, %s, %s, %s, true)
            RETURNING id
        """, (
            profile_id, coupon['tier_id'],
            coupon['type'], coupon['id'],
            valid_from, valid_until
        ))
        grant_id = cur.fetchone()['id']

        # Record redemption
        cur.execute("""
            INSERT INTO coupon_redemptions (coupon_id, profile_id, access_grant_id)
            VALUES (%s, %s, %s)
        """, (coupon['id'], profile_id, grant_id))

        # Increment coupon redemption count
        cur.execute("""
            UPDATE coupons
            SET redemption_count = redemption_count + 1
            WHERE id = %s
        """, (coupon['id'],))

        # Log activity
        cur.execute("""
            INSERT INTO user_activity_log (profile_id, action, details)
            VALUES (%s, 'coupon_redeemed', %s)
        """, (
            profile_id,
            f'{{"coupon_code": "{code}", "tier": "{coupon["tier_id"]}", "duration_days": {coupon["duration_days"]}}}'
        ))

        conn.commit()

        return {
            "ok": True,
            "message": f"Coupon erfolgreich eingelöst: {coupon['tier_id']} für {coupon['duration_days']} Tage",
            "grant_id": grant_id,
            "valid_until": valid_until.isoformat() if valid_until else None
        }
