#!/usr/bin/env python3
"""
Import and Update Script for inventory_restructured.ods
Imports equipment and PC data from spreadsheet into shopdb database

This script will:
1. Import/update vendors and models
2. Import/update controller types and operating systems
3. Update existing machines with correct vendor/model/controller data
4. Update existing PCs with correct data
5. Import business unit information
6. Import compliance/security data
"""

import csv
import sys
import pymysql
from datetime import datetime

# Database connection settings
DB_CONFIG = {
    'host': 'localhost',
    'user': '570005354',
    'password': '570005354',
    'database': 'shopdb',
    'charset': 'utf8mb4',
    'cursorclass': pymysql.cursors.DictCursor
}

def connect_db():
    """Connect to the MySQL database"""
    try:
        conn = pymysql.connect(**DB_CONFIG)
        print(f"✓ Connected to database: {DB_CONFIG['database']}")
        return conn
    except Exception as e:
        print(f"✗ Database connection failed: {e}")
        sys.exit(1)

def get_or_create_vendor(cursor, vendor_name):
    """Get vendor ID or create if doesn't exist"""
    if not vendor_name or vendor_name.strip() == '':
        return None

    vendor_name = vendor_name.strip()

    # Check if vendor exists
    cursor.execute("SELECT vendorid FROM vendors WHERE vendor = %s", (vendor_name,))
    result = cursor.fetchone()

    if result:
        return result['vendorid']

    # Create new vendor
    cursor.execute(
        "INSERT INTO vendors (vendor, isactive) VALUES (%s, 1)",
        (vendor_name,)
    )
    vendor_id = cursor.lastrowid
    print(f"  + Created new vendor: {vendor_name} (ID: {vendor_id})")
    return vendor_id

def get_or_create_model(cursor, model_name, vendor_id):
    """Get model ID or create if doesn't exist"""
    if not model_name or model_name.strip() == '':
        return None

    model_name = model_name.strip()

    # Check if model exists for this vendor
    cursor.execute(
        "SELECT modelnumberid FROM models WHERE modelnumber = %s AND vendorid = %s",
        (model_name, vendor_id)
    )
    result = cursor.fetchone()

    if result:
        return result['modelnumberid']

    # Create new model
    cursor.execute(
        "INSERT INTO models (modelnumber, vendorid, isactive) VALUES (%s, %s, 1)",
        (model_name, vendor_id)
    )
    model_id = cursor.lastrowid
    print(f"  + Created new model: {model_name} (ID: {model_id})")
    return model_id

def get_or_create_os(cursor, os_name):
    """Get operating system ID or create if doesn't exist"""
    if not os_name or os_name.strip() == '':
        return None

    os_name = os_name.strip()

    # Check if OS exists
    cursor.execute("SELECT osid FROM operatingsystems WHERE operatingsystem = %s", (os_name,))
    result = cursor.fetchone()

    if result:
        return result['osid']

    # Create new OS (no isactive column in this table)
    cursor.execute(
        "INSERT INTO operatingsystems (operatingsystem) VALUES (%s)",
        (os_name,)
    )
    os_id = cursor.lastrowid
    print(f"  + Created new OS: {os_name} (ID: {os_id})")
    return os_id

def get_or_create_controller_type(cursor, controller_name, vendor_id=None):
    """Get controller type ID or create if doesn't exist"""
    if not controller_name or controller_name.strip() == '':
        return None

    controller_name = controller_name.strip()

    # Check if controller type exists
    cursor.execute(
        "SELECT controllertypeid FROM controllertypes WHERE controllertype = %s",
        (controller_name,)
    )
    result = cursor.fetchone()

    if result:
        return result['controllertypeid']

    # Create new controller type (without vendorid for now)
    cursor.execute(
        "INSERT INTO controllertypes (controllertype, isactive) VALUES (%s, 1)",
        (controller_name,)
    )
    controller_id = cursor.lastrowid
    print(f"  + Created new controller type: {controller_name} (ID: {controller_id})")
    return controller_id

def get_business_unit_id(cursor, business_unit_name):
    """Get business unit ID by name"""
    if not business_unit_name or business_unit_name.strip() == '':
        return None

    cursor.execute(
        "SELECT businessunitid FROM businessunits WHERE businessunit = %s",
        (business_unit_name.strip(),)
    )
    result = cursor.fetchone()
    return result['businessunitid'] if result else None

def update_machine(cursor, row, conn):
    """Update existing machine with inventory data"""
    machine_number = row.get('Machine_Number', '').strip()

    if not machine_number:
        return False

    # Get vendor and model
    vendor_name = row.get('Manufacturer', '').strip()
    model_name = row.get('Model', '').strip()

    vendor_id = get_or_create_vendor(cursor, vendor_name) if vendor_name else None
    model_id = get_or_create_model(cursor, model_name, vendor_id) if model_name and vendor_id else None

    # Get controller info
    controller_name = row.get('Controller_Type1', '').strip()
    controller_os_name = row.get('Controller_OS1', '').strip()

    controller_id = get_or_create_controller_type(cursor, controller_name, vendor_id) if controller_name else None
    controller_os_id = get_or_create_os(cursor, controller_os_name) if controller_os_name else None

    # Get business unit
    business_unit_name = row.get('Business_Unit', '').strip()
    business_unit_id = get_business_unit_id(cursor, business_unit_name) if business_unit_name else None

    # Get serial number
    serial_number = row.get('Serial #', '').strip()

    # Get IP addresses
    ip_address1 = row.get('IP Address', '').strip()
    ip_address2 = row.get('IP Address (interface 2)', '').strip()

    # Check if machine exists
    cursor.execute(
        "SELECT machineid FROM machines WHERE machinenumber = %s",
        (machine_number,)
    )
    result = cursor.fetchone()

    if not result:
        print(f"  ⚠️  Machine {machine_number} not found in database")
        return False

    machine_id = result['machineid']

    # Update machine
    update_fields = []
    update_values = []

    # Note: machines table doesn't have vendorid, it has modelnumberid which links to models (which has vendorid)
    if model_id:
        update_fields.append("modelnumberid = %s")
        update_values.append(model_id)

    if controller_id:
        update_fields.append("controllertypeid = %s")
        update_values.append(controller_id)

    if controller_os_id:
        update_fields.append("controllerosid = %s")
        update_values.append(controller_os_id)

    if business_unit_id:
        update_fields.append("businessunitid = %s")
        update_values.append(business_unit_id)

    if serial_number:
        update_fields.append("serialnumber = %s")
        update_values.append(serial_number)

    if ip_address1:
        update_fields.append("ipaddress1 = %s")
        update_values.append(ip_address1)

    if ip_address2:
        update_fields.append("ipaddress2 = %s")
        update_values.append(ip_address2)

    update_fields.append("lastupdated = NOW()")

    if update_fields:
        update_values.append(machine_id)
        sql = f"UPDATE machines SET {', '.join(update_fields)} WHERE machineid = %s"
        cursor.execute(sql, tuple(update_values))
        conn.commit()
        return True

    return False

def update_pc(cursor, row, conn):
    """Update existing PC (now in machines table) with inventory data"""
    hostname = row.get('Hostname', '').strip()

    if not hostname:
        return False

    # Get vendor and model
    vendor_name = row.get('Manufacturer', '').strip()
    model_name = row.get('Model', '').strip()

    vendor_id = get_or_create_vendor(cursor, vendor_name) if vendor_name else None
    model_id = get_or_create_model(cursor, model_name, vendor_id) if model_name and vendor_id else None

    # Get OS info
    os_name = row.get('OS Name', '').strip()
    os_id = get_or_create_os(cursor, os_name) if os_name else None

    # Get business unit
    business_unit_name = row.get('Business_Unit', '').strip()
    business_unit_id = get_business_unit_id(cursor, business_unit_name) if business_unit_name else None

    # Get serial number
    serial_number = row.get('Serial #', '').strip()

    # Get logged in user (if available)
    logged_in_user = row.get('Logged_In_User', '').strip()

    # Find machine by hostname (PCs were migrated with hostname as machinenumber)
    cursor.execute(
        "SELECT machineid FROM machines WHERE machinenumber = %s OR hostname = %s",
        (hostname, hostname)
    )
    result = cursor.fetchone()

    if not result:
        print(f"  ⚠️  PC {hostname} not found in machines table")
        return False

    machine_id = result['machineid']

    # Update machine (PC)
    update_fields = []
    update_values = []

    # Note: machines table doesn't have vendorid, it has modelnumberid which links to models (which has vendorid)
    if model_id:
        update_fields.append("modelnumberid = %s")
        update_values.append(model_id)

    if os_id:
        update_fields.append("osid = %s")
        update_values.append(os_id)

    if business_unit_id:
        update_fields.append("businessunitid = %s")
        update_values.append(business_unit_id)

    if serial_number:
        update_fields.append("serialnumber = %s")
        update_values.append(serial_number)

    if logged_in_user:
        update_fields.append("loggedinuser = %s")
        update_values.append(logged_in_user)

    update_fields.append("lastupdated = NOW()")

    if update_fields:
        update_values.append(machine_id)
        sql = f"UPDATE machines SET {', '.join(update_fields)} WHERE machineid = %s"
        cursor.execute(sql, tuple(update_values))
        conn.commit()
        return True

    return False

def main():
    """Main import process"""
    print("="*70)
    print("INVENTORY DATA IMPORT - Phase 2 Enhancement")
    print("="*70)
    print()

    # Connect to database
    conn = connect_db()
    cursor = conn.cursor()

    # Read CSV file
    csv_file = '/tmp/inventory_restructured.csv'
    print(f"📄 Reading inventory file: {csv_file}")

    try:
        with open(csv_file, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            rows = list(reader)
        print(f"✓ Loaded {len(rows)} rows from inventory")
        print()
    except Exception as e:
        print(f"✗ Failed to read CSV file: {e}")
        conn.close()
        sys.exit(1)

    # Separate PCs and Equipment
    pcs = [row for row in rows if row.get('Row_Type') == 'PC']
    equipment = [row for row in rows if row.get('Row_Type') == 'Equipment']

    print(f"📊 Inventory breakdown:")
    print(f"   - PCs: {len(pcs)}")
    print(f"   - Equipment: {len(equipment)}")
    print()

    # Process Equipment (Machines)
    print("="*70)
    print("UPDATING EQUIPMENT (MACHINES)")
    print("="*70)

    equipment_updated = 0
    equipment_failed = 0

    for idx, row in enumerate(equipment, 1):
        machine_number = row.get('Machine_Number', '').strip()
        equipment_name = row.get('Equipment_Name', '').strip()

        if machine_number:
            print(f"[{idx}/{len(equipment)}] Processing: {machine_number} - {equipment_name}")
            if update_machine(cursor, row, conn):
                equipment_updated += 1
                print(f"  ✓ Updated machine: {machine_number}")
            else:
                equipment_failed += 1
        print()

    # Process PCs
    print("="*70)
    print("UPDATING PCs")
    print("="*70)

    pcs_updated = 0
    pcs_failed = 0

    for idx, row in enumerate(pcs, 1):
        hostname = row.get('Hostname', '').strip()

        if hostname:
            print(f"[{idx}/{len(pcs)}] Processing PC: {hostname}")
            if update_pc(cursor, row, conn):
                pcs_updated += 1
                print(f"  ✓ Updated PC: {hostname}")
            else:
                pcs_failed += 1
        print()

    # Summary
    print("="*70)
    print("IMPORT SUMMARY")
    print("="*70)
    print(f"Equipment:")
    print(f"  ✓ Updated: {equipment_updated}")
    print(f"  ✗ Failed:  {equipment_failed}")
    print()
    print(f"PCs:")
    print(f"  ✓ Updated: {pcs_updated}")
    print(f"  ✗ Failed:  {pcs_failed}")
    print()
    print(f"Total records processed: {len(rows)}")
    print(f"Total records updated: {equipment_updated + pcs_updated}")
    print()

    # Close connection
    cursor.close()
    conn.close()
    print("✓ Import complete!")

if __name__ == '__main__':
    main()
