#!/usr/bin/env python3
"""
Nexus Autoparts — Import Strada TODO.st01 Inventory
Parses fixed-width report and imports into tenant DB using PostgreSQL COPY.

Usage:
    python3 import_estrada_st01.py --tenant=28 --file=/tmp/todo_st01.txt --branch=1
"""

import argparse
import csv
import io
import os
import sys
import tempfile
import time

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'pos'))
import psycopg2
from tenant_db import get_tenant_conn

# Margins applied to Cost A
MARGIN_PRICE_1 = 1.35   # mostrador / retail
MARGIN_PRICE_2 = 1.25   # taller / workshop
MARGIN_PRICE_3 = 1.15   # mayoreo / wholesale


def parse_number(val, default=0):
    """Parse a string that might be '$1,234.56' or '.000' or empty."""
    if not val:
        return default
    cleaned = str(val).replace('$', '').replace(',', '').replace(' ', '').strip()
    if cleaned == '.':
        return default
    try:
        return float(cleaned)
    except ValueError:
        return default


def parse_st01_line(line):
    """Parse a single line from TODO.st01 fixed-width format."""
    line = line.rstrip('\n')
    
    # Skip short lines
    if len(line) < 80:
        return None
    
    # Skip header/footer lines
    if 'Page:' in line or 'General Inventory' in line or 'STRADA AUTO' in line:
        return None
    if 'Tienda:' in line and 'Page:' in line:
        return None
    if line.strip().startswith('Line Part Number'):
        return None
    if line.strip().startswith('----'):
        return None
    
    # Fixed-width columns based on header:
    # Line Part Number      Description      Addl description Pcode   Instk  Min 1  Max 1     Cost A     Cost B codes[1]
    # ---- ---------------- ---------------- ---------------- ----- ------- ------ ------ ---------- ---------- --------
    marca = line[0:5].strip()
    part_number_raw = line[5:21].strip()
    description = line[22:39].strip()
    addl_desc = line[40:56].strip()
    pcode = line[56:61].strip()
    instk = line[62:70].strip()
    min1 = line[71:77].strip()
    max1 = line[78:84].strip()
    cost_a = line[85:95].strip()
    cost_b = line[96:106].strip()
    codes = line[107:].strip() if len(line) > 107 else ''
    
    if not part_number_raw:
        return None
    
    # Build composite part number: MARCA-NUMERO
    # Some marcas are empty (fallback to pcode or generic)
    marca_safe = marca if marca else 'GEN'
    part_number = f"{marca_safe}-{part_number_raw}"
    
    # Build name from description + additional description
    name = description
    if addl_desc and addl_desc != '?':
        name = f"{description} {addl_desc}".strip()
    
    if not name:
        return None
    
    cost = parse_number(cost_a, 0)
    stock = int(parse_number(instk, 0))
    min_stock = int(parse_number(min1, 0))
    max_stock = int(parse_number(max1, 0))
    
    # Calculate prices with margins
    price_1 = round(cost * MARGIN_PRICE_1, 2) if cost > 0 else 0
    price_2 = round(cost * MARGIN_PRICE_2, 2) if cost > 0 else 0
    price_3 = round(cost * MARGIN_PRICE_3, 2) if cost > 0 else 0
    
    return {
        'part_number': part_number,
        'name': name[:300],  # truncate to schema limit
        'brand': marca_safe,
        'cost': cost,
        'price_1': price_1,
        'price_2': price_2,
        'price_3': price_3,
        'stock': stock,
        'min_stock': min_stock,
        'max_stock': max_stock,
        'location': pcode,
        'unit': 'PZA',
        'tax_rate': 0.16,
    }


def import_st01(tenant_id, file_path, branch_id=1):
    print(f"=== Importing Strada inventory ===")
    print(f"Tenant: {tenant_id}")
    print(f"File:   {file_path}")
    print(f"Branch: {branch_id}")
    print()
    
    # Parse file
    print("Parsing fixed-width file...")
    parsed = []
    skipped = 0
    start_time = time.time()
    
    with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
        for line in f:
            row = parse_st01_line(line)
            if row is None:
                skipped += 1
                continue
            parsed.append(row)
    
    parse_time = time.time() - start_time
    print(f"  Parsed: {len(parsed):,} rows")
    print(f"  Skipped: {skipped:,} lines (headers/empty)")
    print(f"  Time: {parse_time:.1f}s")
    print()
    
    if not parsed:
        print("ERROR: No data rows found.")
        return
    
    # Show sample
    print("Sample rows:")
    for row in parsed[:5]:
        print(f"  {row['part_number']:20} | {row['name'][:40]:40} | stk={row['stock']:>4} | cost={row['cost']:>10.2f} | p1={row['price_1']:>10.2f}")
    print()
    
    # Connect to tenant DB
    conn = get_tenant_conn(tenant_id)
    cur = conn.cursor()
    
    # Ensure branch exists
    cur.execute("SELECT id FROM branches WHERE id = %s", (branch_id,))
    if not cur.fetchone():
        print(f"ERROR: Branch {branch_id} does not exist. Creating default branch...")
        cur.execute("INSERT INTO branches (name) VALUES ('Principal') RETURNING id")
        branch_id = cur.fetchone()[0]
        conn.commit()
        print(f"  Created branch id={branch_id}")
    
    # Step 1: Create temp table and COPY data
    print("Creating temp table...")
    cur.execute("""
        DROP TABLE IF EXISTS tmp_st01_import;
        CREATE TEMP TABLE tmp_st01_import (
            part_number VARCHAR(100),
            name VARCHAR(300),
            brand VARCHAR(100),
            cost NUMERIC(12,2),
            price_1 NUMERIC(12,2),
            price_2 NUMERIC(12,2),
            price_3 NUMERIC(12,2),
            stock INTEGER,
            min_stock INTEGER,
            max_stock INTEGER,
            location VARCHAR(50),
            unit VARCHAR(20),
            tax_rate NUMERIC(5,4)
        );
    """)
    conn.commit()
    
    print("COPY to temp table...")
    csv_buffer = io.StringIO()
    writer = csv.writer(csv_buffer, lineterminator='\n')
    for row in parsed:
        writer.writerow([
            row['part_number'],
            row['name'],
            row['brand'],
            row['cost'],
            row['price_1'],
            row['price_2'],
            row['price_3'],
            row['stock'],
            row['min_stock'],
            row['max_stock'],
            row['location'],
            row['unit'],
            row['tax_rate'],
        ])
    
    csv_buffer.seek(0)
    cur.copy_expert(
        """COPY tmp_st01_import (
            part_number, name, brand, cost, price_1, price_2, price_3,
            stock, min_stock, max_stock, location, unit, tax_rate
        ) FROM STDIN WITH (FORMAT CSV)""",
        csv_buffer
    )
    conn.commit()
    
    cur.execute("SELECT COUNT(*) FROM tmp_st01_import")
    copied = cur.fetchone()[0]
    print(f"  Copied: {copied:,} rows")
    print()
    
    # Step 2: Insert into inventory
    print("Inserting into inventory...")
    start_time = time.time()
    cur.execute("""
        INSERT INTO inventory (
            branch_id, part_number, name, brand,
            cost, price_1, price_2, price_3,
            min_stock, max_stock, location, unit, tax_rate, is_active
        )
        SELECT
            %s, part_number, name, brand,
            cost, price_1, price_2, price_3,
            min_stock, max_stock, location, unit, tax_rate, TRUE
        FROM tmp_st01_import
        ON CONFLICT (branch_id, part_number) DO UPDATE SET
            name = EXCLUDED.name,
            brand = EXCLUDED.brand,
            cost = EXCLUDED.cost,
            price_1 = EXCLUDED.price_1,
            price_2 = EXCLUDED.price_2,
            price_3 = EXCLUDED.price_3,
            min_stock = EXCLUDED.min_stock,
            max_stock = EXCLUDED.max_stock,
            location = EXCLUDED.location,
            is_active = TRUE
    """, (branch_id,))
    conn.commit()
    insert_time = time.time() - start_time
    
    cur.execute("SELECT COUNT(*) FROM inventory WHERE branch_id = %s", (branch_id,))
    total_inventory = cur.fetchone()[0]
    print(f"  Inventory rows: {total_inventory:,}")
    print(f"  Time: {insert_time:.1f}s")
    print()
    
    # Step 3: Create stock operations for items with stock > 0
    print("Creating initial stock operations...")
    start_time = time.time()
    cur.execute("""
        INSERT INTO inventory_operations (
            inventory_id, branch_id, operation_type, quantity,
            cost_at_time, reference_type, notes
        )
        SELECT
            i.id,
            i.branch_id,
            'INITIAL',
            t.stock,
            i.cost,
            'IMPORT',
            'Importado desde TODO.st01'
        FROM tmp_st01_import t
        JOIN inventory i ON i.part_number = t.part_number AND i.branch_id = %s
        WHERE t.stock > 0
    """, (branch_id,))
    conn.commit()
    ops_time = time.time() - start_time
    
    cur.execute("SELECT COUNT(*) FROM inventory_operations WHERE operation_type = 'INITIAL'")
    total_ops = cur.fetchone()[0]
    print(f"  Stock operations created: {total_ops:,}")
    print(f"  Time: {ops_time:.1f}s")
    print()
    
    # Cleanup
    cur.execute("DROP TABLE IF EXISTS tmp_st01_import")
    conn.commit()
    cur.close()
    conn.close()
    
    print("=== Import complete ===")
    print(f"Total inventory items: {total_inventory:,}")
    print(f"Items with stock > 0:  {total_ops:,}")


def main():
    parser = argparse.ArgumentParser(description='Import Strada TODO.st01 into Nexus tenant')
    parser.add_argument('--tenant', type=int, required=True, help='Tenant ID')
    parser.add_argument('--file', required=True, help='Path to TODO.st01 file')
    parser.add_argument('--branch', type=int, default=1, help='Branch ID (default: 1)')
    args = parser.parse_args()
    
    import_st01(args.tenant, args.file, args.branch)


if __name__ == '__main__':
    main()
