"""Warranty / RMA engine (Mejora #10).

Registers warranties at sale time and manages the claim lifecycle.

Tables:
  warranties       — one row per warranted item sold
  warranty_claims  — one row per claim filed
"""

from datetime import date, timedelta
from services.audit import log_action


def register_warranty(conn, sale_id, sale_item_id, inventory_id,
                      customer_id, warranty_months, supplier_id=None,
                      part_number=None, name=None, notes=None):
    """Register a warranty for a sold item.

    Args:
        warranty_months: int (e.g., 12, 24, 36)
    Returns:
        int: warranty_id
    """
    if not warranty_months or warranty_months <= 0:
        raise ValueError("warranty_months must be a positive integer")

    start = date.today()
    end = start + timedelta(days=30 * warranty_months)

    cur = conn.cursor()
    cur.execute("""
        INSERT INTO warranties
            (sale_id, sale_item_id, inventory_id, customer_id, supplier_id,
             part_number, name, warranty_months, start_date, end_date, notes)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        RETURNING id
    """, (
        sale_id, sale_item_id, inventory_id, customer_id, supplier_id,
        part_number, name, warranty_months, start, end, notes
    ))
    w_id = cur.fetchone()[0]
    cur.close()

    log_action(conn, 'WARRANTY_REGISTER', 'warranty', w_id,
               new_value={'months': warranty_months, 'end_date': str(end)})
    return w_id


def create_claim(conn, warranty_id, reason, employee_id=None, notes=None):
    """File a warranty claim.

    Args:
        warranty_id: int
        reason: str (min 10 chars)
    Returns:
        int: claim_id
    """
    if not reason or len(reason.strip()) < 10:
        raise ValueError("Claim reason must be at least 10 characters")

    cur = conn.cursor()
    # Verify warranty exists and is active
    cur.execute("SELECT status FROM warranties WHERE id = %s", (warranty_id,))
    row = cur.fetchone()
    if not row:
        raise ValueError("Warranty not found")
    if row[0] != 'active':
        raise ValueError(f"Cannot claim a warranty with status '{row[0]}'")

    cur.execute("""
        INSERT INTO warranty_claims
            (warranty_id, reason, employee_id, notes)
        VALUES (%s, %s, %s, %s)
        RETURNING id
    """, (warranty_id, reason, employee_id, notes))
    claim_id = cur.fetchone()[0]
    cur.close()

    log_action(conn, 'WARRANTY_CLAIM', 'warranty_claim', claim_id,
               new_value={'warranty_id': warranty_id, 'reason': reason})
    return claim_id


def resolve_claim(conn, claim_id, resolution, diagnosis=None,
                  replacement_inventory_id=None, refund_amount=None,
                  labor_cost=None, supplier_rma_number=None, notes=None):
    """Resolve a warranty claim.

    Args:
        resolution: 'approved'|'rejected'|'repaired'|'replaced'|'refunded'
    """
    if resolution not in ('approved', 'rejected', 'repaired', 'replaced', 'refunded'):
        raise ValueError(f"Invalid resolution: {resolution}")

    cur = conn.cursor()
    cur.execute("""
        UPDATE warranty_claims
        SET resolution = %s, diagnosis = COALESCE(%s, diagnosis),
            replacement_inventory_id = COALESCE(%s, replacement_inventory_id),
            refund_amount = COALESCE(%s, refund_amount),
            labor_cost = COALESCE(%s, labor_cost),
            supplier_rma_number = COALESCE(%s, supplier_rma_number),
            notes = COALESCE(notes || ' | ', '') || %s,
            status = 'resolved', resolved_at = NOW()
        WHERE id = %s AND status != 'closed'
    """, (
        resolution, diagnosis, replacement_inventory_id,
        refund_amount, labor_cost, supplier_rma_number,
        notes or 'Resuelto', claim_id
    ))
    updated = cur.rowcount > 0

    # If replaced or refunded, mark warranty as claimed
    if updated and resolution in ('replaced', 'refunded', 'approved'):
        cur.execute("""
            UPDATE warranties SET status = 'claimed'
            WHERE id = (SELECT warranty_id FROM warranty_claims WHERE id = %s)
        """, (claim_id,))

    cur.close()
    return updated


def close_claim(conn, claim_id):
    """Close a resolved claim (final status)."""
    cur = conn.cursor()
    cur.execute("""
        UPDATE warranty_claims
        SET status = 'closed'
        WHERE id = %s AND status = 'resolved'
    """, (claim_id,))
    updated = cur.rowcount > 0
    cur.close()
    return updated


def get_warranty(conn, warranty_id):
    """Get warranty detail."""
    cur = conn.cursor()
    cur.execute("""
        SELECT w.id, w.sale_id, w.sale_item_id, w.inventory_id, w.customer_id,
               w.supplier_id, w.part_number, w.name, w.warranty_months,
               w.start_date, w.end_date, w.status, w.notes, w.created_at,
               c.name as customer_name, s.name as supplier_name
        FROM warranties w
        LEFT JOIN customers c ON w.customer_id = c.id
        LEFT JOIN suppliers s ON w.supplier_id = s.id
        WHERE w.id = %s
    """, (warranty_id,))
    row = cur.fetchone()
    cur.close()
    if not row:
        return None
    return {
        'id': row[0], 'sale_id': row[1], 'sale_item_id': row[2],
        'inventory_id': row[3], 'customer_id': row[4], 'supplier_id': row[5],
        'part_number': row[6], 'name': row[7], 'warranty_months': row[8],
        'start_date': str(row[9]), 'end_date': str(row[10]),
        'status': row[11], 'notes': row[12], 'created_at': str(row[13]),
        'customer_name': row[14], 'supplier_name': row[15],
    }


def list_warranties(conn, customer_id=None, status=None, limit=50, offset=0):
    """List warranties."""
    cur = conn.cursor()
    filters = []
    params = []
    if customer_id:
        filters.append("w.customer_id = %s")
        params.append(customer_id)
    if status:
        filters.append("w.status = %s")
        params.append(status)
    where = "WHERE " + " AND ".join(filters) if filters else ""

    cur.execute(f"""
        SELECT w.id, w.part_number, w.name, w.warranty_months,
               w.start_date, w.end_date, w.status,
               c.name as customer_name
        FROM warranties w
        LEFT JOIN customers c ON w.customer_id = c.id
        {where}
        ORDER BY w.end_date ASC
        LIMIT %s OFFSET %s
    """, params + [limit, offset])
    rows = cur.fetchall()
    cur.close()
    return [{
        'id': r[0], 'part_number': r[1], 'name': r[2],
        'warranty_months': r[3], 'start_date': str(r[4]),
        'end_date': str(r[5]), 'status': r[6],
        'customer_name': r[7],
    } for r in rows]


def get_claim(conn, claim_id):
    """Get claim detail."""
    cur = conn.cursor()
    cur.execute("""
        SELECT wc.id, wc.warranty_id, wc.claim_date, wc.reason, wc.diagnosis,
               wc.resolution, wc.replacement_inventory_id, wc.refund_amount,
               wc.labor_cost, wc.status, wc.supplier_rma_number, wc.notes,
               wc.created_at, wc.resolved_at,
               w.part_number, w.name, w.customer_id, c.name as customer_name
        FROM warranty_claims wc
        JOIN warranties w ON wc.warranty_id = w.id
        LEFT JOIN customers c ON w.customer_id = c.id
        WHERE wc.id = %s
    """, (claim_id,))
    row = cur.fetchone()
    cur.close()
    if not row:
        return None
    return {
        'id': row[0], 'warranty_id': row[1], 'claim_date': str(row[2]),
        'reason': row[3], 'diagnosis': row[4], 'resolution': row[5],
        'replacement_inventory_id': row[6], 'refund_amount': float(row[7]) if row[7] else None,
        'labor_cost': float(row[8]) if row[8] else None,
        'status': row[9], 'supplier_rma_number': row[10], 'notes': row[11],
        'created_at': str(row[12]), 'resolved_at': str(row[13]) if row[13] else None,
        'part_number': row[14], 'name': row[15],
        'customer_id': row[16], 'customer_name': row[17],
    }


def list_claims(conn, status=None, warranty_id=None, limit=50, offset=0):
    """List warranty claims."""
    cur = conn.cursor()
    filters = []
    params = []
    if status:
        filters.append("wc.status = %s")
        params.append(status)
    if warranty_id:
        filters.append("wc.warranty_id = %s")
        params.append(warranty_id)
    where = "WHERE " + " AND ".join(filters) if filters else ""

    cur.execute(f"""
        SELECT wc.id, wc.claim_date, wc.reason, wc.resolution, wc.status,
               w.part_number, w.name, c.name as customer_name
        FROM warranty_claims wc
        JOIN warranties w ON wc.warranty_id = w.id
        LEFT JOIN customers c ON w.customer_id = c.id
        {where}
        ORDER BY wc.created_at DESC
        LIMIT %s OFFSET %s
    """, params + [limit, offset])
    rows = cur.fetchall()
    cur.close()
    return [{
        'id': r[0], 'claim_date': str(r[1]), 'reason': r[2],
        'resolution': r[3], 'status': r[4],
        'part_number': r[5], 'name': r[6], 'customer_name': r[7],
    } for r in rows]


def expire_warranties(conn):
    """Batch-update warranties whose end_date has passed to 'expired'.

    Should be run periodically (e.g., daily via cron).
    Returns number of warranties expired.
    """
    cur = conn.cursor()
    cur.execute("""
        UPDATE warranties
        SET status = 'expired'
        WHERE status = 'active' AND end_date < CURRENT_DATE
    """)
    count = cur.rowcount
    cur.close()
    return count
