#!/usr/bin/env python3
from __future__ import annotations

import csv
from pathlib import Path
from typing import List, Dict

BASE = Path(__file__).resolve().parents[1]
INPUT = BASE / '12_Output' / 'customer_segments.csv'
OUT = BASE / '12_Output'


def fnum(v: str) -> float:
    try:
        return float((v or '').strip() or 0)
    except ValueError:
        return 0.0


def yes(v: str) -> bool:
    return (v or '').strip().lower() in {'yes', 'true', '1'}


def marketable(row: Dict[str, str]) -> bool:
    return row.get('email') and not yes(row.get('opt_out')) and row.get('is_email_valid', '').lower() != 'false'


with INPUT.open(newline='', encoding='utf-8') as f:
    rows = list(csv.DictReader(f))

win_back: List[Dict[str, str]] = []
retention: List[Dict[str, str]] = []
package_renewal: List[Dict[str, str]] = []
slow_day: List[Dict[str, str]] = []

for row in rows:
    bookings = fnum(row.get('total_bookings'))
    spend = fnum(row.get('total_spend'))
    days = fnum(row.get('days_since_last_booking'))
    segment = row.get('customer_segment', '')
    member = segment == 'member'
    has_package = (row.get('punch_card_status', '') or '').lower() not in {'', 'no'} or 'package' in (row.get('punch_card_status', '') or '').lower()

    base = {
        'external_id': row.get('external_id', ''),
        'email': row.get('email', ''),
        'phone': row.get('phone', ''),
        'full_name': row.get('full_name', ''),
        'customer_segment': segment,
        'membership_plan': row.get('membership_plan', ''),
        'punch_card_status': row.get('punch_card_status', ''),
        'total_bookings': row.get('total_bookings', ''),
        'total_spend': row.get('total_spend', ''),
        'days_since_last_booking': row.get('days_since_last_booking', ''),
    }

    if marketable(row) and bookings >= 1 and 15 <= days <= 90 and not member:
        score = int(min(100, 40 + bookings * 5 + (20 if spend >= 150 else 0) + (15 if days <= 45 else 5)))
        win_back.append({**base, 'win_back_score': score, 'reason': 'lapsed 15-90 days with prior booking history'})

    if marketable(row) and member and days >= 21:
        score = int(min(100, 50 + (15 if days >= 30 else 0) + (10 if bookings >= 3 else 0)))
        retention.append({**base, 'retention_score': score, 'reason': 'member showing booking inactivity'})

    if marketable(row) and has_package and days >= 21:
        score = int(min(100, 45 + (20 if days >= 30 else 10) + (10 if bookings >= 2 else 0)))
        package_renewal.append({**base, 'package_renewal_score': score, 'reason': 'package customer inactive long enough for renewal nudge'})

    if marketable(row) and not member and (segment in {'new_lead', 'first_time_customer', 'repeat_customer'}) and days >= 7:
        score = int(min(100, 35 + (10 if segment == 'repeat_customer' else 0) + (15 if 14 <= days <= 60 else 5)))
        slow_day.append({**base, 'slow_day_score': score, 'reason': 'eligible for off-peak promo outreach'})

for name, data, fields in [
    ('win_back_targets.csv', win_back, ['external_id','email','phone','full_name','customer_segment','membership_plan','punch_card_status','total_bookings','total_spend','days_since_last_booking','win_back_score','reason']),
    ('member_retention_targets.csv', retention, ['external_id','email','phone','full_name','customer_segment','membership_plan','total_bookings','total_spend','days_since_last_booking','retention_score','reason']),
    ('package_renewal_targets.csv', package_renewal, ['external_id','email','phone','full_name','customer_segment','punch_card_status','total_bookings','total_spend','days_since_last_booking','package_renewal_score','reason']),
    ('slow_day_enriched_targets.csv', slow_day, ['external_id','email','phone','full_name','customer_segment','total_bookings','total_spend','days_since_last_booking','slow_day_score','reason']),
]:
    path = OUT / name
    with path.open('w', newline='', encoding='utf-8') as f:
        w = csv.DictWriter(f, fieldnames=fields)
        w.writeheader()
        ordered = sorted(data, key=lambda r: float(next(v for k, v in r.items() if k.endswith('_score'))), reverse=True)
        for row in ordered:
            w.writerow({k: row.get(k, '') for k in fields})

summary = OUT / 'automation_target_summary.txt'
summary.write_text(
    '\n'.join([
        f'win_back_targets: {len(win_back)}',
        f'member_retention_targets: {len(retention)}',
        f'package_renewal_targets: {len(package_renewal)}',
        f'slow_day_enriched_targets: {len(slow_day)}',
    ]) + '\n', encoding='utf-8'
)

print(summary.read_text())
