#!/usr/bin/env python3
"""
Script to clean EMBO members Excel file.

Filters:
1. Remove rows where ELECTED = 'no' (keep 'yes' and empty/NaN for older members)
2. Remove rows with missing first name or last name
"""

import sys
from pathlib import Path

import pandas as pd


def clean_embo_members_file(
    input_file: Path,
    output_file: Path = None
):
    """
    Clean EMBO members file.
    
    Filters applied:
    1. Remove rows where ELECTED = 'no' (keeps 'yes' and empty/NaN for older members)
    2. Remove rows with missing first name or last name
    
    Args:
        input_file: Path to input Excel file
        output_file: Path to output Excel file (if None, auto-generates)
    """
    print(f"\n📂 Reading EMBO members file: {input_file}")
    df = pd.read_excel(input_file)
    
    print(f"✓ Loaded {len(df)} rows")
    
    # Check if ELECTED column exists
    elected_col = "mem_joi_joi_ELC__Elections::ELECTED"
    if elected_col not in df.columns:
        print(f"\n❌ Error: Column '{elected_col}' not found!")
        print(f"\nAvailable columns with 'ELECT' in name:")
        for col in df.columns:
            if 'ELECT' in col.upper():
                print(f"  - {col}")
        sys.exit(1)
    
    # Show current distribution
    print(f"\nCurrent distribution of '{elected_col}':")
    value_counts = df[elected_col].value_counts(dropna=False)
    for value, count in value_counts.items():
        print(f"  - {value}: {count} rows ({count/len(df)*100:.1f}%)")
    
    # Count missing/empty values
    missing_elected = df[elected_col].isna() | (df[elected_col] == "")
    print(f"  - Missing/empty: {missing_elected.sum()} rows ({missing_elected.sum()/len(df)*100:.1f}%)")
    
    # Filter: Remove only rows where ELECTED = 'no'
    # Keep: 'yes' and empty/NaN (for older members)
    df_cleaned = df[df[elected_col] != "no"].copy()
    
    print(f"\n{'='*80}")
    print("FILTERING RESULTS - Step 1: Remove ELECTED = 'no'")
    print(f"{'='*80}")
    print(f"  - Original rows: {len(df)}")
    print(f"  - Rows removed (ELECTED = 'no'): {(df[elected_col] == 'no').sum()}")
    print(f"  - Rows kept (ELECTED = 'yes' or empty): {len(df_cleaned)} ({len(df_cleaned)/len(df)*100:.1f}%)")
    
    # Filter for rows with both first name and last name
    first_name_col = "mem_joi_PSUB__Person::PS_FirstNamePlusInitials"
    last_name_col = "mem_joi_PSUB__Person::PS_LastName"
    
    rows_with_missing_names = 0
    
    if first_name_col not in df_cleaned.columns or last_name_col not in df_cleaned.columns:
        print(f"\n⚠️  Warning: Name columns not found, skipping name filter")
        print(f"   First name column exists: {first_name_col in df_cleaned.columns}")
        print(f"   Last name column exists: {last_name_col in df_cleaned.columns}")
    else:
        # Count rows with missing names before filtering
        missing_first = df_cleaned[first_name_col].isna() | (df_cleaned[first_name_col] == "")
        missing_last = df_cleaned[last_name_col].isna() | (df_cleaned[last_name_col] == "")
        missing_either = missing_first | missing_last
        
        rows_with_missing_names = missing_either.sum()
        
        if rows_with_missing_names > 0:
            print(f"\n{'='*80}")
            print("FILTERING RESULTS - Step 2: Remove rows with missing names")
            print(f"{'='*80}")
            print(f"  - Rows with missing first name: {missing_first.sum()}")
            print(f"  - Rows with missing last name: {missing_last.sum()}")
            print(f"  - Rows with missing either name: {rows_with_missing_names}")
            
            # Filter to keep only rows with both names
            df_cleaned = df_cleaned[~missing_either].copy()
            
            print(f"  - Rows after name filter: {len(df_cleaned)}")
            print(f"  - Additional rows removed: {rows_with_missing_names}")
        else:
            print(f"\n✓ All rows have both first and last names")
    
    print(f"\n{'='*80}")
    print("FINAL FILTERING SUMMARY")
    print(f"{'='*80}")
    print(f"  - Original rows: {len(df)}")
    print(f"  - Rows removed (ELECTED = 'no'): {(df[elected_col] == 'no').sum()}")
    print(f"  - Rows removed (missing names): {rows_with_missing_names}")
    print(f"  - Final rows kept: {len(df_cleaned)} ({len(df_cleaned)/len(df)*100:.1f}%)")
    print(f"  - Total rows removed: {len(df) - len(df_cleaned)}")
    
    # Check for duplicates (same person multiple times)
    if "mem_joi_PSUB__Person::PS_FirstNamePlusInitials" in df_cleaned.columns and "mem_joi_PSUB__Person::PS_LastName" in df_cleaned.columns:
        name_duplicates = df_cleaned.groupby([
            "mem_joi_PSUB__Person::PS_FirstNamePlusInitials",
            "mem_joi_PSUB__Person::PS_LastName"
        ]).size()
        
        multiple_rows = name_duplicates[name_duplicates > 1]
        if len(multiple_rows) > 0:
            print(f"\n⚠️  Found {len(multiple_rows)} authors with multiple rows:")
            print(f"   Total duplicate rows: {multiple_rows.sum() - len(multiple_rows)}")
            print(f"\n   Sample duplicates:")
            for (first, last), count in multiple_rows.head(10).items():
                print(f"     - {first} {last}: {count} rows")
        else:
            print(f"\n✓ No duplicate authors found (each author appears once)")
    
    # Check publication availability
    pub_col = "mem_joi_joi_ELC__Elections::PUBLICATIONS"
    if pub_col in df_cleaned.columns:
        has_pubs = df_cleaned[pub_col].notna().sum()
        print(f"\nPublication availability:")
        print(f"  - Members with publications: {has_pubs} ({has_pubs/len(df_cleaned)*100:.1f}%)")
        print(f"  - Members without publications: {len(df_cleaned) - has_pubs} ({(len(df_cleaned) - has_pubs)/len(df_cleaned)*100:.1f}%)")
    
    # Check ORCID availability
    orcid_col = "mem_joi_PSUB__Person::PS_ORCID"
    if orcid_col in df_cleaned.columns:
        has_orcid = df_cleaned[orcid_col].notna().sum()
        print(f"\nORCID availability:")
        print(f"  - Members with ORCID: {has_orcid} ({has_orcid/len(df_cleaned)*100:.1f}%)")
        print(f"  - Members without ORCID: {len(df_cleaned) - has_orcid} ({(len(df_cleaned) - has_orcid)/len(df_cleaned)*100:.1f}%)")
    
    # Save cleaned file
    if output_file is None:
        output_file = input_file.parent / f"emboplanet_allmem_cleaned_{input_file.stem.split('_')[-1]}.xlsx"
    
    print(f"\n💾 Saving cleaned file to: {output_file}")
    df_cleaned.to_excel(output_file, index=False)
    print(f"✓ Successfully saved {len(df_cleaned)} rows")
    
    print(f"\n{'='*80}")
    print("✅ CLEANING COMPLETE")
    print(f"{'='*80}\n")
    
    return df_cleaned


def main():
    """CLI entry point."""
    import argparse
    
    parser = argparse.ArgumentParser(
        description="Clean EMBO members file to keep only elected members"
    )
    parser.add_argument(
        "--input",
        type=str,
        default="data/emboplanet_allmem_2026-01-23.xlsx",
        help="Input Excel file path"
    )
    parser.add_argument(
        "--output",
        type=str,
        default=None,
        help="Output Excel file path (auto-generated if not provided)"
    )
    
    args = parser.parse_args()
    
    input_file = Path(args.input)
    if not input_file.exists():
        print(f"❌ Error: Input file not found: {input_file}")
        sys.exit(1)
    
    output_file = Path(args.output) if args.output else None
    
    clean_embo_members_file(input_file, output_file)


if __name__ == "__main__":
    main()
