#!/usr/bin/env python3
"""
Script de corrección puntual para el pedido S00651.
====================================================

PROBLEMA: El pedido S00651 fue editado en Shopify (GRIS TALAVERA FMG HAT: 5 → 6).
La orden de venta y la orden de entrega se actualizaron, pero el traslado interno
ALMA/INT/00083 ya estaba validado con 5 unidades.

SOLUCIÓN: Crear un traslado interno complementario de +1 unidad del ALMACÉN → OFICINA.

USO:
  python3 fix_transfer_s00651.py --dry-run    # Solo muestra lo que haría
  python3 fix_transfer_s00651.py --apply      # Crea el traslado complementario
"""

import xmlrpc.client
import sys
import logging
from datetime import datetime

# ─── Configuración ────────────────────────────────────────────────────────
ODOO_URL = 'http://localhost:16001'
ODOO_DB = 'hazard_new'
ODOO_USER = 'admin'
ODOO_PASS = 'admin'

# ─── Datos del pedido afectado ────────────────────────────────────────────
SALE_ORDER_NAME = 'S00651'
PRODUCT_SKU = 'HRS-HAT-FMG-U-GRY-OS'  # GRIS TALAVERA FMG HAT
QTY_FALTANTE = 1  # Diferencia: 6 - 5 = 1

# ─── Logging ──────────────────────────────────────────────────────────────
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger(__name__)


def connect():
    common = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/common')
    uid = common.authenticate(ODOO_DB, ODOO_USER, ODOO_PASS, {})
    if not uid:
        raise ConnectionError("No se pudo autenticar con Odoo")
    models = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/object')
    logger.info("Conectado a Odoo (uid=%s)", uid)
    return uid, models


def main():
    if len(sys.argv) < 2 or sys.argv[1] not in ('--dry-run', '--apply'):
        print(__doc__)
        sys.exit(1)

    mode = sys.argv[1]
    uid, models = connect()

    # 1. Buscar el pedido S00651
    sale_ids = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'sale.order', 'search', [[('name', '=', SALE_ORDER_NAME)]])
    if not sale_ids:
        logger.error("No se encontró el pedido %s", SALE_ORDER_NAME)
        sys.exit(1)
    sale_id = sale_ids[0]
    sale_records = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'sale.order', 'read', [sale_id],
        {'fields': ['name', 'state', 'warehouse_id']})
    sale = sale_records[0]
    logger.info("Pedido encontrado: %s (ID=%s, Estado=%s)", sale['name'], sale_id, sale['state'])

    # 2. Buscar el producto GRIS TALAVERA
    product_ids = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'product.product', 'search', [[('default_code', '=', PRODUCT_SKU)]])
    if not product_ids:
        logger.error("No se encontró el producto con SKU %s", PRODUCT_SKU)
        sys.exit(1)
    product_id = product_ids[0]
    product_records = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'product.product', 'read', [product_id],
        {'fields': ['name', 'display_name', 'default_code']})
    product = product_records[0]
    logger.info("Producto encontrado: %s (ID=%s)", product['display_name'], product_id)

    # 3. Buscar el traslado interno original (ALMA/INT/00083)
    internal_move_ids = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.move', 'search', [[
            '|', ('picking_id.sale_id', '=', sale_id), ('picking_id.origin', '=', SALE_ORDER_NAME),
            ('picking_id.picking_type_id.code', '=', 'internal'),
            ('product_id', '=', product_id),
            ('state', '=', 'done'),
        ]])
    if not internal_move_ids:
        logger.error("No se encontró movimiento interno completado para este producto en este pedido")
        sys.exit(1)

    move_records = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.move', 'read', [internal_move_ids[0]],
        {'fields': ['picking_id', 'product_uom_qty', 'product_uom', 'location_id', 'location_dest_id', 'warehouse_id']})
    move_data = move_records[0]

    picking_id = move_data['picking_id'][0]
    picking_records = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.picking', 'read', [picking_id],
        {'fields': ['name', 'state', 'picking_type_id', 'location_id', 'location_dest_id']})
    picking = picking_records[0]

    logger.info("Traslado original: %s (Estado=%s, Cantidad=%s)", picking['name'], picking['state'], move_data['product_uom_qty'])

    # 4. Verificar la orden de entrega
    delivery_move_ids = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.move', 'search', [[
            '|', ('picking_id.sale_id', '=', sale_id), ('picking_id.origin', '=', SALE_ORDER_NAME),
            ('picking_id.picking_type_id.code', '=', 'outgoing'),
            ('product_id', '=', product_id),
            ('state', '!=', 'cancel'),
        ]])
    if delivery_move_ids:
        del_move_records = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
            'stock.move', 'read', [delivery_move_ids[0]],
            {'fields': ['product_uom_qty', 'picking_id']})
        del_move = del_move_records[0]
        del_picking_records = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
            'stock.picking', 'read', [del_move['picking_id'][0]],
            {'fields': ['name', 'state']})
        del_picking = del_picking_records[0]
        logger.info("Orden de entrega: %s (Estado=%s, Demanda=%s)", del_picking['name'], del_picking['state'], del_move['product_uom_qty'])

    logger.info("")
    logger.info("═══════════════════════════════════════════════════")
    logger.info("  RESUMEN DE CORRECCIÓN")
    logger.info("═══════════════════════════════════════════════════")
    logger.info("  Pedido:     %s", SALE_ORDER_NAME)
    logger.info("  Producto:   %s (%s)", product['display_name'], PRODUCT_SKU)
    logger.info("  Traslado:   %s (ya completado con %s unidades)", picking['name'], int(move_data['product_uom_qty']))
    logger.info("  Faltante:   +%s unidad(es)", QTY_FALTANTE)
    logger.info("  Acción:     Crear traslado complementario ALMA → OFICINA")
    logger.info("═══════════════════════════════════════════════════")

    if mode == '--dry-run':
        logger.info("")
        logger.info("  🔍 DRY RUN - No se modificó nada")
        logger.info("  Para aplicar ejecutar: python3 fix_transfer_s00651.py --apply")
        return

    # 5. Crear traslado complementario
    logger.info("")
    logger.info("Creando traslado complementario...")

    new_picking_id = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.picking', 'create', [{
            'picking_type_id': picking['picking_type_id'][0],
            'location_id': picking['location_id'][0],
            'location_dest_id': picking['location_dest_id'][0],
            'origin': SALE_ORDER_NAME,
            'sale_id': sale_id,
            'move_type': 'direct',
        }])

    new_move_id = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.move', 'create', [{
            'name': f"[Complemento S00651] {product['display_name']}",
            'product_id': product_id,
            'product_uom_qty': QTY_FALTANTE,
            'product_uom': move_data['product_uom'][0],
            'picking_id': new_picking_id,
            'location_id': picking['location_id'][0],
            'location_dest_id': picking['location_dest_id'][0],
            'warehouse_id': move_data['warehouse_id'][0] if move_data['warehouse_id'] else False,
        }])

    # Confirmar y reservar
    models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.picking', 'action_confirm', [[new_picking_id]])
    models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.picking', 'action_assign', [[new_picking_id]])

    # Leer el nombre del nuevo traslado
    new_picking = models.execute_kw(ODOO_DB, uid, ODOO_PASS,
        'stock.picking', 'read', [new_picking_id],
        {'fields': ['name', 'state']})

    logger.info("")
    logger.info("✅ Traslado complementario creado: %s (Estado: %s)", new_picking['name'], new_picking['state'])
    logger.info("   Producto: %s", product['display_name'])
    logger.info("   Cantidad: +%s unidad(es)", QTY_FALTANTE)
    logger.info("   Ruta:     ALMA/Stock → OFFIC/Existencias")
    logger.info("")
    logger.info("⚡ SIGUIENTE PASO: Notifica a almacén para que valide el traslado %s", new_picking['name'])


if __name__ == '__main__':
    main()
