import logging
from django.utils.timezone import make_aware
from decimal import Decimal
from django.core.management.base import BaseCommand
from datetime import datetime
from django.utils.dateparse import parse_datetime

import json
import os

from finanzas.models import Cuenta, Movimiento, Categoria
from reymotausers.models import ReyMotaUser


logger = logging.getLogger('importar_movimientos_externos')

handler = logging.FileHandler('importar_movimientos.log')
consola = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
consola.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(consola)
logger.setLevel(logging.INFO)


class Command(BaseCommand):
    help = 'Importa movimientos externos desde un archivo JSON'

    def add_arguments(self, parser):
        parser.add_argument('archivo_json', type=str)

    def handle(self, *args, **options):
        ruta = options['archivo_json']
        if not os.path.exists(ruta):
            self.stdout.write(self.style.ERROR(f'Archivo no encontrado: {ruta}'))
            return

        with open(ruta, 'r', encoding='utf-8') as f:
            datos = json.load(f)

        for registro in datos:
            try:
                user = ReyMotaUser.objects.get(id=registro['user_id'])
            except ReyMotaUser.DoesNotExist:
                logger.warning(f"Usuario con id {registro['user_id']} no encontrado. Movimiento omitido.")
                continue

            nombre_origen = registro['source_name']
            nombre_destino = registro['destination_name']
            monto_raw = str(registro['amount']).replace(',', '.')

            try:
                monto = abs(Decimal(monto_raw))
            except:
                logger.warning(f"Error al convertir: {registro['amount']} a {monto}")
                continue

            if nombre_origen == nombre_destino:
                logger.info(f"Movimiento con cuentas iguales omitido: {nombre_origen}")
                continue

            cuenta_origen, _ = Cuenta.objects.get_or_create(nombre=nombre_origen, usuario=user, defaults={'saldo': Decimal('0.00'), 'tipo': 'ingreso'})
            cuenta_destino, _ = Cuenta.objects.get_or_create(nombre=nombre_destino, usuario=user, defaults={'saldo': Decimal('0.00'), 'tipo': 'gasto'})

            fecha = make_aware(datetime.fromisoformat(registro['date'][:19]))
            descripcion = registro.get('description', '')

            # Detección de duplicado
            duplicado = Movimiento.objects.filter(
                usuario=user,
                cuenta_origen=cuenta_origen,
                cuenta_destino=cuenta_destino,
                monto=monto,
                fecha=fecha,
                descripcion=descripcion
            ).exists()

            if duplicado:
                logger.info(f"Duplicado omitido: {descripcion} - {monto} ({fecha})")
                continue

            mov = Movimiento.objects.create(
                usuario=user,
                cuenta_origen=cuenta_origen,
                cuenta_destino=cuenta_destino,
                monto=monto,
                fecha=fecha,
                descripcion=descripcion
            )

            if cat := registro.get('category'):
                categoria, _ = Categoria.objects.get_or_create(nombre=cat)
                mov.categoria = categoria
                mov.save()

            try:
                cuenta_origen.saldo -= monto
                cuenta_origen.save()
            except:
                logger.warning(f"Monto inválido (origen): {registro['amount']} {registro['journal_id']}")
                continue

            try:
                cuenta_destino.saldo += monto
                cuenta_destino.save()
            except:
                logger.warning(f"Monto inválido (destino): {registro['amount']} {registro['journal_id']}")
                continue

            logger.info(f"Movimiento importado: De: {cuenta_origen} a { cuenta_destino} - {descripcion} - {monto} ({fecha})")

        self.stdout.write(self.style.SUCCESS('Importación finalizada. Ver "importar_movimientos.log" para detalles.'))
