#!/usr/bin/env python3
"""FASE 5 — VALIDATION SUITE

Tests:
  1. CRM: activities, tags, loyalty, analytics
  2. Service Orders: create, status transitions, items, labor, kanban
  3. Images: upload info delete
"""

import os, sys, io, time
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from PIL import Image

from tenant_db import get_master_conn, get_tenant_conn_by_dbname
from services.crm_engine import (
    log_activity, get_activities, create_tag, list_tags,
    assign_tag, get_customer_tags, add_loyalty_points,
    redeem_points, get_loyalty_history, get_customer_analytics,
)
from services.service_order_engine import (
    create_service_order, get_service_order, list_service_orders,
    update_status, add_item, add_labor, get_kanban_summary,
)
from services.image_service import save_image, delete_image, get_image_info

MASTER_DB_URL = os.environ.get('MASTER_DB_URL', 'postgresql://postgres@/nexus_autoparts')
TENANT_TEMPLATE = os.environ.get('TENANT_DB_URL_TEMPLATE', 'postgresql://postgres@/{db_name}')

PASS = '\033[92mPASS\033[0m'
FAIL = '\033[91mFAIL\033[0m'
passed = 0
failed = 0


def ok(label, condition, detail=''):
    global passed, failed
    if condition:
        print(f"  [{PASS}] {label}")
        passed += 1
    else:
        print(f"  [{FAIL}] {label} {detail}")
        failed += 1


# Get a test tenant
master = get_master_conn()
cur = master.cursor()
cur.execute("SELECT db_name FROM tenants WHERE is_active = true ORDER BY id LIMIT 1")
row = cur.fetchone()
cur.close(); master.close()

if not row:
    print("No active tenant found!")
    sys.exit(1)

db_name = row[0]
conn = get_tenant_conn_by_dbname(db_name)

print("=" * 60)
print("FASE 5: CRM + Service Orders + Images — VALIDATION")
print("=" * 60)

# ─── Find test customer ─────────────────────────────
cur = conn.cursor()
cur.execute("SELECT id FROM customers WHERE is_active = true LIMIT 1")
cust_row = cur.fetchone()
customer_id = cust_row[0] if cust_row else None
cur.close()

if not customer_id:
    print("No customer found — creating one")
    cur = conn.cursor()
    cur.execute("INSERT INTO customers (name, phone, is_active) VALUES ('Test CRM', '5550000000', true) RETURNING id")
    customer_id = cur.fetchone()[0]
    conn.commit()
    cur.close()

print(f"\nTest customer_id: {customer_id}")

# ─── CRM: Activities ─────────────────────────────
print("\n[CRM ACTIVITIES]")
try:
    act_id = log_activity(conn, customer_id, 'note', title='Test note', description='Hello CRM')
    ok("Log activity", act_id is not None)

    acts = get_activities(conn, customer_id)
    ok("Get activities", len(acts) >= 1, f"count={len(acts)}")
except Exception as e:
    conn.rollback()
    ok("CRM activities", False, str(e))

# ─── CRM: Tags ─────────────────────────────
print("\n[CRM TAGS]")
try:
    tag_name = f"VIP-{int(time.time())}"
    tag_id = create_tag(conn, 1, tag_name, color='#FFD700', description='Very Important Customer')
    ok("Create tag", tag_id is not None)

    tags = list_tags(conn, 1)
    ok("List tags", any(t['name'] == tag_name for t in tags))

    assign_tag(conn, customer_id, tag_id)
    cust_tags = get_customer_tags(conn, customer_id)
    ok("Assign tag", any(t['name'] == tag_name for t in cust_tags))
except Exception as e:
    conn.rollback()
    ok("CRM tags", False, str(e))

# ─── CRM: Loyalty ─────────────────────────────
print("\n[CRM LOYALTY]")
try:
    # Add enough points for gold tier
    pid = add_loyalty_points(conn, customer_id, 2500, points_type='earned',
                             source_type='sale', description='Test points')
    ok("Add loyalty points", pid is not None)

    history = get_loyalty_history(conn, customer_id)
    ok("Loyalty history", len(history) >= 1)

    # Check balance updated (may have points from previous runs)
    cur = conn.cursor()
    cur.execute("SELECT loyalty_points_balance, loyalty_tier FROM customers WHERE id = %s", (customer_id,))
    bal, tier = cur.fetchone()
    cur.close()
    ok("Balance updated", bal >= 2500, f"balance={bal}")
    ok("Tier updated", tier in ('gold', 'platinum'), f"tier={tier}")  # 2500+ pts = gold or platinum
except Exception as e:
    conn.rollback()
    ok("CRM loyalty", False, str(e))

# ─── CRM: Analytics ─────────────────────────────
print("\n[CRM ANALYTICS]")
try:
    analytics = get_customer_analytics(conn, customer_id)
    ok("Analytics computed", isinstance(analytics, dict))
    ok("Analytics has LTV", 'ltv' in analytics)
    ok("Analytics has churn_risk", analytics.get('churn_risk') in ['low', 'medium', 'high'])
except Exception as e:
    conn.rollback()
    ok("CRM analytics", False, str(e))

# ─── Service Orders ─────────────────────────────
print("\n[SERVICE ORDERS]")
try:
    so = create_service_order(conn, {
        'tenant_id': 1, 'branch_id': None, 'customer_id': customer_id,
        'priority': 'high', 'reception_notes': 'Test order',
        'estimated_cost': 1500.00, 'mileage_in': 50000,
    })
    ok("Create SO", so.get('service_order_id') is not None, f"id={so.get('service_order_id')}")
    so_id = so['service_order_id']

    so_detail = get_service_order(conn, so_id)
    ok("Get SO detail", so_detail is not None and so_detail['status'] == 'received')
    ok("SO has order_number", so_detail.get('order_number', '').startswith('SO-'))

    # Status transition: received -> diagnosis
    result = update_status(conn, so_id, 'diagnosis', changed_by=1, notes='Starting diagnosis')
    ok("Status received->diagnosis", result['new_status'] == 'diagnosis')

    # Invalid transition
    try:
        update_status(conn, so_id, 'delivered')
        ok("Invalid transition blocked", False, "Should have raised ValueError")
    except ValueError:
        ok("Invalid transition blocked", True)

    # Add item
    item_id = add_item(conn, so_id, {
        'part_number': 'BP-123', 'name': 'Brake Pads', 'quantity': 2,
        'unit_price': 450.00, 'status': 'pending',
    })
    ok("Add item", item_id is not None)

    # Add labor
    labor_id = add_labor(conn, so_id, {
        'description': 'Replace brake pads', 'hours': 2.0, 'hourly_rate': 350.00,
    })
    ok("Add labor", labor_id is not None)

    # Refresh detail
    so_detail2 = get_service_order(conn, so_id)
    ok("SO has items", len(so_detail2.get('items', [])) >= 1)
    ok("SO has labor", len(so_detail2.get('labor', [])) >= 1)

    # List orders
    orders = list_service_orders(conn, status='diagnosis')
    ok("List orders", orders.get('data') is not None)

    # Kanban summary
    summary = get_kanban_summary(conn)
    ok("Kanban summary", 'received' in summary or 'diagnosis' in summary)

except Exception as e:
    conn.rollback()
    import traceback
    ok("Service Orders", False, f"{e}\n{traceback.format_exc()}")

# ─── Images ─────────────────────────────
print("\n[IMAGES]")
try:
    # Create a test image in memory
    img = Image.new('RGB', (800, 600), color='red')
    buf = io.BytesIO()
    img.save(buf, format='PNG')
    buf.seek(0)

    # Need a tenant_id and item_id
    tenant_id = 1
    cur = conn.cursor()
    cur.execute("SELECT id FROM inventory WHERE is_active = true LIMIT 1")
    inv_row = cur.fetchone()
    if inv_row:
        item_id = inv_row[0]
    else:
        cur.execute("INSERT INTO inventory (part_number, name, is_active) VALUES ('IMG-TEST', 'Image Test', true) RETURNING id")
        item_id = cur.fetchone()[0]
        conn.commit()
    cur.close()

    result = save_image(tenant_id, item_id, file_obj=buf, filename_hint='test.png')
    ok("Save image", result.get('image_url') is not None)

    info = get_image_info(tenant_id, item_id)
    ok("Get image info", info['has_image'] is True)

    delete_image(tenant_id, item_id)
    info2 = get_image_info(tenant_id, item_id)
    ok("Delete image", info2['has_image'] is False)
except Exception as e:
    conn.rollback()
    import traceback
    ok("Images", False, f"{e}\n{traceback.format_exc()}")

conn.close()

print("\n" + "=" * 60)
print(f"RESULTS: {PASS} {passed} passed, {FAIL} {failed} failed")
print("=" * 60)

sys.exit(0 if failed == 0 else 1)
