import sys
from pathlib import Path

# Add parent directory to Python path so we can import helpers
parent_dir = Path(__file__).parent.parent
sys.path.insert(0, str(parent_dir))

import csv
from decimal import Decimal
from proteus import config, Model

from helpers.config import (
    PURCHASE_FEES_CSV, 
    connect_to_tryton)

from helpers.tryton_helpers import (
        find_party_by_name, 
        find_product_by_code, 
        find_purchase_contract_by_ref, 
        find_contract_line_by_sequence, 
        find_currency_by_code, 
        parse_decimal, 
        find_supplier_category,
        ensure_party_is_supplier,
        find_fee_mode_by_name,
        find_payable_receivable_by_name,
        get_existing_fees_for_line,
        fee_already_exists)


# CSV Configuration
CSV_FILE_PATH = PURCHASE_FEES_CSV


# Import options
AUTO_ENABLE_SUPPLIER = True  # Set to False to skip auto-enabling supplier flag
SKIP_NON_SUPPLIERS = False   # Set to True to skip parties that aren't suppliers


def import_purchase_contract_fees(csv_file):
    """Import purchase contract line fees from CSV"""
    
    print(f"{'='*70}")
    print("IMPORTING PURCHASE CONTRACT LINE FEES")
    print(f"{'='*70}\n")
    
    # Get models
    try:
        PurchaseLineFee = Model.get('fee.fee')
    except Exception as e:
        print(f"✗ Error: Could not load fee.fee model - {e}")
        print("Please ensure the model name is correct for your Tryton customization")
        return
    
    imported_count = 0
    skipped_count = 0
    error_count = 0
    errors = []
    
    try:
        with open(csv_file, 'r', encoding='utf-8-sig') as file:
            reader = csv.DictReader(file)
            
            current_contract_ref = None
            current_contract = None
            current_line_sequence = None
            current_line = None
            
            for row_num, row in enumerate(reader, start=2):  # Start at 2 (header is row 1)
                try:
                    # Extract data from CSV
                    contract_ref = row.get('contract_ref', '').strip()
                    line_sequence = row.get('line_sequence', '').strip()
                    product_code = row.get('product', '').strip()
                    supplier_name = row.get('supplier', '').strip()
                    currency_code = row.get('currency', '').strip()
                    p_r_value = row.get('p_r', '').strip()
                    mode_name = row.get('mode', '').strip()
                    price_value = row.get('price', '').strip()
                    unit_value = row.get('unit', '').strip()
                    
                    print(f"Processing row {row_num}: {contract_ref} - Line {line_sequence} - {product_code}")
                    
                    # Validate required fields
                    if not contract_ref:
                        print(f"  ✗ Skipping: Missing contract_ref\n")
                        skipped_count += 1
                        continue
                    
                    if not line_sequence:
                        print(f"  ✗ Skipping: Missing line_sequence\n")
                        skipped_count += 1
                        continue
                    
                    if not product_code:
                        print(f"  ✗ Skipping: Missing product\n")
                        skipped_count += 1
                        continue
                    
                    # Cache contract and line if same as previous row
                    if contract_ref != current_contract_ref:
                        current_contract = find_purchase_contract_by_ref(contract_ref)
                        current_contract_ref = contract_ref
                        current_line_sequence = None
                        current_line = None
                    
                    if not current_contract:
                        print(f"  ✗ Skipping: Contract not found\n")
                        skipped_count += 1
                        continue
                    
                    # Cache line if same as previous row
                    if line_sequence != current_line_sequence:
                        current_line = find_contract_line_by_sequence(current_contract, line_sequence)
                        current_line_sequence = line_sequence
                    
                    if not current_line:
                        print(f"  ✗ Skipping: Contract line not found\n")
                        skipped_count += 1
                        continue
                    
                    # Find related records
                    product = find_product_by_code(product_code)
                    if not product:
                        print(f"  ✗ Skipping: Product not found\n")
                        skipped_count += 1
                        continue
                    
                    supplier = find_party_by_name(supplier_name)
                    if not supplier:
                        print(f"  ✗ Skipping: Supplier not found\n")
                        skipped_count += 1
                        continue

                    # Ensure party has SUPPLIER category
                    supplier, is_supplier = ensure_party_is_supplier(supplier, auto_enable=AUTO_ENABLE_SUPPLIER)

                    if not is_supplier:
                        if SKIP_NON_SUPPLIERS:
                            print(f"  ⚠ Skipping purchase - party does not have SUPPLIER category\n")
                            skipped_count += 1
                            current_purchase = None
                            continue
                        else:
                            error_msg = f"Row {row_num}: Party '{supplier.rec_name}' does not have SUPPLIER category"
                            errors.append(error_msg)
                            error_count += 1
                            current_purchase = None
                            continue                    
                    
                    currency = find_currency_by_code(currency_code)
                    if not currency:
                        print(f"  ✗ Skipping: Currency not found\n")
                        skipped_count += 1
                        continue
                    
                    # Parse price
                    price = parse_decimal(price_value, 'price')
                    if price is None:
                        print(f"  ✗ Skipping: Invalid price\n")
                        skipped_count += 1
                        continue
                    
                    # Determine payable/receivable
                    payable_receivable = find_payable_receivable_by_name(p_r_value)
                    
                    # Find fee mode
                    mode = find_fee_mode_by_name(mode_name)
                    
                    # Check if fee already exists
                    existing_fees = get_existing_fees_for_line(current_line)
                    if fee_already_exists(existing_fees, product, supplier, price):
                        print(f"  ○ Fee already exists for this line\n")
                        skipped_count += 1
                        continue
                    
                    # Create the fee
                    fee = PurchaseLineFee()
                    fee.line = current_line
                    fee.product = product
                    fee.supplier = supplier
                    fee.currency = currency
                    fee.price = price

                    # Set type if found and field exists
                    if mode and hasattr(fee, 'type'):
                        fee.type = 'ordered'        # Assuming all imported fees are 'ordered'

                    # Set weight_type if found and field exists
                    if mode and hasattr(fee, 'weight_type'):
                        fee.weight_type = 'brut'                        

                    # Set p_r (payable or receivable) if found and field exists
                    if mode and hasattr(fee, 'p_r'):                    
                        fee.p_r = payable_receivable
                    
                    # Set mode if found and field exists
                    if mode and hasattr(fee, 'mode'):
                        fee.mode = mode
                    
                    # Set unit if field exists
                    if unit_value and hasattr(fee, 'unit'):
                        # Try to find the unit
                        Unit = Model.get('product.uom')
                        units = Unit.find([('symbol', '=', unit_value)])
                        if not units:
                            units = Unit.find([('name', '=', unit_value)])
                        if units:
                            fee.unit = units[0]
                    
                    # Save the fee
                    fee.save()
                    
                    print(f"  ✓ Fee created successfully")
                    print(f"    Product: {product.rec_name}")
                    print(f"    Supplier: {supplier.rec_name}")
                    print(f"    Price: {price} {currency.code}")
                    print(f"    Type: {payable_receivable}")
                    print()
                    
                    imported_count += 1
                    
                except Exception as e:
                    error_msg = f"Row {row_num} - {contract_ref}: {str(e)}"
                    errors.append(error_msg)
                    error_count += 1
                    print(f"✗ Error on row {row_num}: {e}\n")
                    import traceback
                    traceback.print_exc()
        
        # Summary
        print(f"{'='*70}")
        print("IMPORT SUMMARY")
        print(f"{'='*70}")
        print(f"Successfully imported: {imported_count} fees")
        print(f"Skipped (missing data or already exist): {skipped_count} fees")
        print(f"Errors: {error_count}")
        
        if errors:
            print(f"\nError details:")
            for error in errors:
                print(f"  - {error}")
        
        print(f"\n{'='*70}")
        
    except FileNotFoundError:
        print(f"✗ Error: CSV file not found at {csv_file}")
        print(f"Please update CSV_FILE_PATH in the script with the correct path.")
    except Exception as e:
        print(f"✗ Fatal error: {e}")
        import traceback
        traceback.print_exc()


def verify_import():
    """Verify imported purchase contract fees"""
    
    print(f"\n{'='*70}")
    print("VERIFICATION - Purchase Contract Line Fees")
    print(f"{'='*70}\n")
    
    try:
        PurchaseLineFee = Model.get('fee.fee')
        
        # Find all fees (or limit to recently created ones)
        fees = PurchaseLineFee.find([], order=[('id', 'DESC')])
        
        if fees:
            print(f"Found {len(fees)} fees (showing last 50):\n")
            print(f"{'ID':<8} {'Contract':<15} {'Product':<25} {'Supplier':<25} {'Price':<12} {'Type':<12}")
            print("-" * 105)
            
            for fee in fees[:50]:  # Show last 50 created
                fee_id = fee.id
                
                # Get contract reference
                contract_ref = 'N/A'
                if hasattr(fee, 'line') and fee.line:
                    line = fee.line
                    if hasattr(line, 'purchase') and line.purchase:
                        contract = line.purchase
                        if hasattr(contract, 'reference') and contract.reference:
                            contract_ref = str(contract.reference)[:14]
                
                product = fee.product.rec_name[:24] if hasattr(fee, 'product') and fee.product else 'N/A'
                supplier = fee.supplier.rec_name[:24] if hasattr(fee, 'supplier') and fee.supplier else 'N/A'
                price = f"{fee.price:.2f}" if hasattr(fee, 'price') and fee.price else 'N/A'
                
                # Get type (payable/receivable)
                fee_type = 'N/A'
                if hasattr(fee, 'type'):
                    fee_type = fee.type
                elif hasattr(fee, 'payable_receivable'):
                    fee_type = fee.payable_receivable
                
                print(f"{fee_id:<8} {contract_ref:<15} {product:<25} {supplier:<25} {price:<12} {fee_type:<12}")
        else:
            print("No fees found")
        
        print()
        
    except Exception as e:
        print(f"✗ Error during verification: {e}")
        import traceback
        traceback.print_exc()


def list_purchase_contracts():
    """List purchase contracts for debugging"""
    Purchase = Model.get('purchase.purchase')
    
    print(f"\n{'='*70}")
    print("AVAILABLE PURCHASE CONTRACTS (first 20)")
    print(f"{'='*70}")
    
    contracts = Purchase.find([], order=[('id', 'DESC')], limit=20)
    
    if contracts:
        print(f"{'ID':<8} {'Reference':<20} {'Party':<30} {'State':<12}")
        print("-" * 70)
        
        for contract in contracts:
            contract_id = contract.id
            reference = contract.reference[:19] if contract.reference else 'N/A'
            party = contract.party.rec_name[:29] if contract.party else 'N/A'
            state = contract.state if contract.state else 'N/A'
            
            print(f"{contract_id:<8} {reference:<20} {party:<30} {state:<12}")
            
            # Show number of lines
            if hasattr(contract, 'lines') and contract.lines:
                print(f"  Lines: {len(contract.lines)}")
    else:
        print("No purchase contracts found")
    
    print(f"{'='*70}\n")


def main():
    print("="*70)
    print("TRYTON PURCHASE CONTRACT FEE IMPORT SCRIPT")
    print("Using Proteus with XML-RPC Connection")
    print("="*70)
    print()
    
    # Connect to Tryton using XML-RPC
    if not connect_to_tryton():
        return 1
    
    # Optional: List purchase contracts for debugging
    # Uncomment the following line to see available contracts
    # list_purchase_contracts()
    
    # Import purchase contract fees
    import_purchase_contract_fees(CSV_FILE_PATH)
    
    # Verify import
    verify_import()
    
    return 0


if __name__ == '__main__':
    exit(main())