#!/usr/bin/env python3
"""
Import merged_contacts.json into phonebook contacts.json schema.
Maps position prefix -> department id, splits name into firstName/lastName,
normalizes phones to 021-XXXXXXXX format when 8 digits start with 5.
"""
import json, re, sys, time, secrets, os

SRC = sys.argv[1] if len(sys.argv) > 1 else '/home/ubuntu/attachments/ab17f35f-7e71-49ec-9a58-712273e79527/merged_contacts.json'
DST = sys.argv[2] if len(sys.argv) > 2 else '/home/ubuntu/phonebook/data/contacts.json'

# Department prefix -> id
DEPT_MAP = [
    ('حوزه ریاست', 'leadership'),
    ('معاونت آموزشی', 'vp-edu'),
    ('معاونت پژوهش', 'vp-research'),
    ('معاونت پژهش', 'vp-research'),  # typo
    ('معاونت دانشجویی', 'vp-student'),
    ('اداره خدمات دانشجویی', 'vp-student'),
    ('معاونت فرهنگی', 'vp-cultural'),
    ('فرهنگی', 'vp-cultural'),
    ('معاونت پشتیبانی', 'vp-admin'),
    ('معاونت علوم پزشکی', 'vp-med'),
    ('دانشکده فنی', 'faculty-eng'),
    ('دانشکده پزشکی', 'faculty-med'),
    ('دانشکده علوم پایه', 'faculty-sci'),
    ('دانشکده علوم انسانی', 'faculty-hum'),
    ('دانشکده کشاورزی', 'faculty-agr'),
    ('دانشکده کشارزی', 'faculty-agr'),  # typo
    ('دانشکده پرستاری', 'faculty-nurse'),
    ('دانشکده هنر', 'faculty-art'),
    ('دانشکده حکمرانی', 'faculty-gov'),
    ('دانشکده طب ایرانی', 'faculty-traditional'),
    ('مرکز تحقیقات', 'research-center'),
    ('گیاهان دارویی', 'research-center'),
    ('مجتمع آموزشی ایثار', 'ethar'),
    ('رئیس ایثار', 'ethar'),
    ('انتظامات', 'security'),
    ('حراست', 'security'),
    ('کتابخانه', 'library'),
    ('درمانگاه', 'clinic'),
    ('ورزش', 'sport'),
    ('استخر', 'sport'),
    ('خوابگاه', 'dorm'),
    ('فناوری اطلاعات', 'it'),
    ('مدیر گروه ریاضی', 'faculty-sci'),
    ('مدیر گروه ادبیات', 'faculty-hum'),
    ('مدیر گروه زراعت', 'faculty-agr'),
    ('مدیر گروه باغبانی', 'faculty-agr'),
    ('مدیر گروه خاکشناسی', 'faculty-agr'),
    ('مدیر گروه کامپیوتر', 'faculty-eng'),
    ('مدیر گروه مخابرات', 'faculty-eng'),
    ('مدیر گروه کنترل', 'faculty-eng'),
    ('مدیر گروه قدرت', 'faculty-eng'),
    ('مدیر گروه الکترونیک', 'faculty-eng'),
    ('مدیر گروه عمران', 'faculty-eng'),
    ('مدیر گروه', 'faculty-eng'),  # other engineering groups
    ('مدیر مهندسی پزشکی', 'faculty-med'),
    ('کارشناس کشاورزی', 'faculty-agr'),
    ('مسئول آموزش پردیس', 'vp-edu'),
    ('مسئول پردیس', 'vp-edu'),
    ('انتشارات', 'vp-research'),
    ('تاسیسات', 'vp-admin'),
    ('پست دانشگاه', 'vp-admin'),
    ('فضای سبز', 'vp-admin'),
    ('هیات علمی', 'faculty-sci'),  # fallback
    ('کارشناس علوم انسانی', 'faculty-hum'),
    ('استاد راهنما', 'faculty-sci'),
    ('پشتیبانی', 'vp-admin'),
]

def pick_dept(position: str) -> str:
    if not position or position == '-' or position.strip() == '':
        return 'other'
    for prefix, dep in DEPT_MAP:
        if prefix in position:
            return dep
    return 'other'

# Titles to strip from start when extracting lastName
TITLES = ['آقای دکتر', 'خانم دکتر', 'دکتر', 'آقای', 'خانم', 'مهندس', 'استاد', 'سید', 'سیده']

def split_name(raw: str):
    """Returns (firstName, lastName, description_extra) tuple."""
    raw = (raw or '').strip()
    if not raw:
        return ('', '', '')

    # Split on ' - ' or ' / ' — first is primary, rest are shared-line extras
    parts = re.split(r'\s+[-/]\s+', raw)
    parts = [p.strip() for p in parts if p.strip()]
    primary = parts[0]
    extra = ' - '.join(parts[1:]) if len(parts) > 1 else ''

    # Extract parenthetical note (e.g. "شعاعی (سخت افزار)" -> "شعاعی" + note)
    paren_note = ''
    m = re.search(r'\((.*?)\)', primary)
    if m:
        paren_note = m.group(1).strip()
        primary = (primary[:m.start()] + primary[m.end():]).strip()

    is_doctor = 'دکتر' in primary
    cleaned = primary
    for t in TITLES:
        if cleaned.startswith(t + ' '):
            cleaned = cleaned[len(t)+1:].strip()
            break

    tokens = cleaned.split()
    if len(tokens) >= 2:
        first = tokens[0]
        last = ' '.join(tokens[1:])
    else:
        first = ''
        last = cleaned

    if is_doctor and not first:
        first = 'دکتر'
    elif is_doctor and first != 'دکتر':
        first = 'دکتر ' + first

    # Build extra description combining paren note and additional names
    extras = []
    if paren_note:
        extras.append(paren_note)
    if extra:
        extras.append(f'همراه: {extra}')
    return (first, last, ' — '.join(extras))

def normalize_phone(ph) -> str:
    """Return landline normalized as 021-XXXXXXXX for 8-digit ext numbers starting with 5.
    Returns empty string if invalid."""
    if ph is None:
        return ''
    s = str(ph).strip()
    # Keep only digits
    digits = re.sub(r'\D', '', s)
    if len(digits) == 8:
        return f'021-{digits}'
    if len(digits) == 10 and digits.startswith('021'):
        return f'021-{digits[3:]}'
    if len(digits) == 11 and digits.startswith('0'):
        return digits  # mobile or full landline with area code, keep as is
    if len(digits) == 12 and digits.startswith('98'):
        return '0' + digits[2:]
    if len(digits) == 13 and digits.startswith('0098'):
        return '0' + digits[4:]
    return ''

def new_id():
    return secrets.token_hex(6)

def main():
    with open(SRC, encoding='utf-8') as f:
        data = json.load(f)

    contacts = []
    now = int(time.time())
    stats = {'total': 0, 'imported': 0, 'skipped': 0, 'no_phone': 0, 'dept': {}}
    for item in data:
        stats['total'] += 1
        name = (item.get('name') or '').strip()
        position = (item.get('position') or '').strip()
        phone_raw = item.get('phone', '')

        if not name:
            stats['skipped'] += 1
            continue

        first, last, extra = split_name(name)
        # Role: strip leading "dept / dept / " from position, keep only the last segment as role
        role_parts = [p.strip() for p in position.split('/')]
        # Remove empty and the first dept-level part
        if len(role_parts) > 1:
            role = ' — '.join(role_parts[1:])
        elif len(role_parts) == 1 and role_parts[0] and role_parts[0] != '-':
            role = role_parts[0]
        else:
            role = ''

        dept = pick_dept(position)
        stats['dept'][dept] = stats['dept'].get(dept, 0) + 1

        landline = normalize_phone(phone_raw)
        if not landline:
            stats['no_phone'] += 1

        # split_name already builds 'extra' string (paren notes + shared-line names)
        description = extra

        contact = {
            'id': new_id(),
            'firstName': first,
            'lastName': last,
            'role': role,
            'department': dept,
            'landline': landline,
            'internal': '',
            'phone': '',
            'telegram': '',
            'rubika': '',
            'eitaa': '',
            'bale': '',
            'whatsapp': '',
            'email': '',
            'description': description,
            'photo': '',
            'status': 'approved',
            'submittedBy': 'admin',
            'createdAt': now,
            'updatedAt': now,
        }
        contacts.append(contact)
        stats['imported'] += 1

    # Sort by (dept, lastName, firstName) for stable display
    contacts.sort(key=lambda c: (c['department'], c['lastName'], c['firstName']))

    out = {'contacts': contacts}
    os.makedirs(os.path.dirname(DST), exist_ok=True)
    with open(DST, 'w', encoding='utf-8') as f:
        json.dump(out, f, ensure_ascii=False, indent=2)

    print(f"Imported {stats['imported']} / {stats['total']} contacts -> {DST}")
    print(f"  skipped: {stats['skipped']}, missing phone: {stats['no_phone']}")
    print("  dept distribution:")
    for d, n in sorted(stats['dept'].items(), key=lambda x: -x[1]):
        print(f"    {n:4d}  {d}")

if __name__ == '__main__':
    main()
