from flask import Blueprint, request, jsonify, session, make_response
from datetime import datetime, date
from src.models.user import db, User
from src.models.company import Company
from src.models.invoice import Invoice
from src.models.expense_type import ExpenseType
from src.routes.auth import require_auth
from src.services.report_606_service import Report606Service

reports_bp = Blueprint('reports', __name__)

@reports_bp.route('/reports/606', methods=['POST'])
@require_auth
def generate_606_report():
    """Generar reporte en formato 606 de la DGII"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        
        if user_role not in ['accountant', 'super_admin']:
            return jsonify({'error': 'No autorizado para generar reportes 606'}), 403
        
        data = request.get_json()
        
        # Validar campos requeridos
        if not data.get('year') or not data.get('month'):
            return jsonify({'error': 'Año y mes son requeridos'}), 400
        
        year = int(data.get('year'))
        month = int(data.get('month'))
        company_id = data.get('company_id', user_company_id)
        include_pending = data.get('include_pending', False)
        
        # Validar año y mes
        if not (2020 <= year <= 2030):
            return jsonify({'error': 'Año debe estar entre 2020 y 2030'}), 400
        
        if not (1 <= month <= 12):
            return jsonify({'error': 'Mes debe estar entre 1 y 12'}), 400
        
        # Verificar permisos para la empresa
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado para generar reportes de esta empresa'}), 403
        
        # Generar reporte
        report_service = Report606Service()
        result = report_service.generate_606_report(company_id, year, month, include_pending)
        
        if not result['success']:
            return jsonify({'error': result.get('message', 'Error al generar reporte')}), 400
        
        return jsonify(result), 200
        
    except ValueError as e:
        return jsonify({'error': f'Error en datos: {str(e)}'}), 400
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/606/download', methods=['POST'])
@require_auth
def download_606_report():
    """Descargar reporte 606 como archivo TXT"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        
        if user_role not in ['accountant', 'super_admin']:
            return jsonify({'error': 'No autorizado para descargar reportes 606'}), 403
        
        data = request.get_json()
        
        year = int(data.get('year'))
        month = int(data.get('month'))
        company_id = data.get('company_id', user_company_id)
        include_pending = data.get('include_pending', False)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        
        # Generar reporte
        report_service = Report606Service()
        result = report_service.generate_606_report(company_id, year, month, include_pending)
        
        if not result['success']:
            return jsonify({'error': result.get('message', 'Error al generar reporte')}), 400
        
        # Crear respuesta con archivo
        response = make_response(result['content'])
        response.headers['Content-Type'] = 'text/plain; charset=utf-8'
        response.headers['Content-Disposition'] = f'attachment; filename="{result["filename"]}"'
        
        return response
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/csv', methods=['POST'])
@require_auth
def generate_csv_report():
    """Generar reporte en formato CSV"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        
        data = request.get_json()
        
        year = int(data.get('year'))
        month = int(data.get('month'))
        company_id = data.get('company_id', user_company_id)
        include_pending = data.get('include_pending', False)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        elif user_role == 'employee':
            return jsonify({'error': 'No autorizado para generar reportes'}), 403
        
        # Generar reporte CSV
        report_service = Report606Service()
        result = report_service.generate_csv_report(company_id, year, month, include_pending)
        
        if not result['success']:
            return jsonify({'error': result.get('message', 'Error al generar reporte')}), 400
        
        return jsonify(result), 200
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/csv/download', methods=['POST'])
@require_auth
def download_csv_report():
    """Descargar reporte CSV"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        
        data = request.get_json()
        
        year = int(data.get('year'))
        month = int(data.get('month'))
        company_id = data.get('company_id', user_company_id)
        include_pending = data.get('include_pending', False)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        elif user_role == 'employee':
            return jsonify({'error': 'No autorizado'}), 403
        
        # Generar reporte CSV
        report_service = Report606Service()
        result = report_service.generate_csv_report(company_id, year, month, include_pending)
        
        if not result['success']:
            return jsonify({'error': result.get('message', 'Error al generar reporte')}), 400
        
        # Crear respuesta con archivo
        response = make_response(result['content'])
        response.headers['Content-Type'] = 'text/csv; charset=utf-8'
        response.headers['Content-Disposition'] = f'attachment; filename="{result["filename"]}"'
        
        return response
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/summary', methods=['GET'])
@require_auth
def get_period_summary():
    """Obtener resumen de un período para el dashboard"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        
        year = request.args.get('year', datetime.now().year, type=int)
        month = request.args.get('month', datetime.now().month, type=int)
        company_id = request.args.get('company_id', user_company_id, type=int)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        elif user_role == 'employee':
            return jsonify({'error': 'No autorizado para ver resúmenes'}), 403
        
        # Obtener resumen
        report_service = Report606Service()
        result = report_service.get_period_summary(company_id, year, month)
        
        if not result['success']:
            return jsonify({'error': result.get('error', 'Error al obtener resumen')}), 400
        
        return jsonify(result), 200
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/dashboard', methods=['GET'])
@require_auth
def get_dashboard_data():
    """Obtener datos para el dashboard principal"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        user_id = session.get('user_id')
        
        # Obtener parámetros
        company_id = request.args.get('company_id', user_company_id, type=int)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        
        # Construir query base
        query = Invoice.query
        
        if user_role == 'super_admin':
            if company_id:
                query = query.filter_by(company_id=company_id)
        elif user_role == 'accountant':
            query = query.filter_by(company_id=user_company_id)
        else:  # employee
            query = query.filter_by(created_by_user_id=user_id)
        
        # Estadísticas generales
        total_invoices = query.count()
        pending_invoices = query.filter_by(status='pending').count()
        approved_invoices = query.filter_by(status='approved').count()
        rejected_invoices = query.filter_by(status='rejected').count()
        
        # Totales de montos (solo aprobadas)
        approved_query = query.filter_by(status='approved')
        total_amount = db.session.query(db.func.sum(Invoice.invoiced_amount)).filter(
            Invoice.id.in_(approved_query.with_entities(Invoice.id))
        ).scalar() or 0
        
        total_itbis = db.session.query(db.func.sum(Invoice.itbis_invoiced)).filter(
            Invoice.id.in_(approved_query.with_entities(Invoice.id))
        ).scalar() or 0
        
        # Facturas recientes (últimas 10)
        recent_invoices = query.order_by(Invoice.created_at.desc()).limit(10).all()
        
        # Resumen por tipo de gasto (solo aprobadas)
        expense_summary = db.session.query(
            Invoice.expense_type,
            Invoice.expense_description,
            db.func.count(Invoice.id).label('count'),
            db.func.sum(Invoice.invoiced_amount).label('total_amount')
        ).filter(
            Invoice.id.in_(approved_query.with_entities(Invoice.id))
        ).group_by(Invoice.expense_type, Invoice.expense_description).all()
        
        expense_data = [
            {
                'type': exp.expense_type,
                'description': exp.expense_description,
                'count': exp.count,
                'amount': float(exp.total_amount or 0)
            }
            for exp in expense_summary
        ]
        
        # Datos del mes actual
        current_month = datetime.now().month
        current_year = datetime.now().year
        
        monthly_query = approved_query.filter(
            db.extract('year', Invoice.invoice_date) == current_year,
            db.extract('month', Invoice.invoice_date) == current_month
        )
        
        monthly_count = monthly_query.count()
        monthly_amount = db.session.query(db.func.sum(Invoice.invoiced_amount)).filter(
            Invoice.id.in_(monthly_query.with_entities(Invoice.id))
        ).scalar() or 0
        
        return jsonify({
            'success': True,
            'statistics': {
                'total_invoices': total_invoices,
                'pending_invoices': pending_invoices,
                'approved_invoices': approved_invoices,
                'rejected_invoices': rejected_invoices,
                'total_amount': float(total_amount),
                'total_itbis': float(total_itbis),
                'monthly_count': monthly_count,
                'monthly_amount': float(monthly_amount)
            },
            'recent_invoices': [invoice.to_dict() for invoice in recent_invoices],
            'expense_summary': expense_data,
            'period': f"{current_month:02d}/{current_year}"
        }), 200
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/suppliers', methods=['GET'])
@require_auth
def get_suppliers_report():
    """Obtener reporte de gastos por proveedor"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        user_id = session.get('user_id')
        
        # Parámetros de filtro
        company_id = request.args.get('company_id', user_company_id, type=int)
        year = request.args.get('year', type=int)
        month = request.args.get('month', type=int)
        limit = request.args.get('limit', 20, type=int)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        elif user_role == 'employee':
            return jsonify({'error': 'No autorizado'}), 403
        
        # Construir query
        query = Invoice.query.filter_by(status='approved')
        
        if user_role == 'super_admin':
            if company_id:
                query = query.filter_by(company_id=company_id)
        else:
            query = query.filter_by(company_id=user_company_id)
        
        # Filtros de período
        if year:
            query = query.filter(db.extract('year', Invoice.invoice_date) == year)
        if month:
            query = query.filter(db.extract('month', Invoice.invoice_date) == month)
        
        # Agrupar por proveedor
        suppliers_data = db.session.query(
            Invoice.supplier_name,
            Invoice.supplier_rnc,
            db.func.count(Invoice.id).label('invoice_count'),
            db.func.sum(Invoice.invoiced_amount).label('total_amount'),
            db.func.sum(Invoice.itbis_invoiced).label('total_itbis'),
            db.func.max(Invoice.invoice_date).label('last_invoice_date')
        ).filter(
            Invoice.id.in_(query.with_entities(Invoice.id))
        ).group_by(
            Invoice.supplier_name, Invoice.supplier_rnc
        ).order_by(
            db.func.sum(Invoice.invoiced_amount).desc()
        ).limit(limit).all()
        
        suppliers_report = [
            {
                'supplier_name': supplier.supplier_name or 'Sin nombre',
                'supplier_rnc': supplier.supplier_rnc or 'Sin RNC',
                'invoice_count': supplier.invoice_count,
                'total_amount': float(supplier.total_amount or 0),
                'total_itbis': float(supplier.total_itbis or 0),
                'last_invoice_date': supplier.last_invoice_date.strftime('%Y-%m-%d') if supplier.last_invoice_date else None
            }
            for supplier in suppliers_data
        ]
        
        return jsonify({
            'success': True,
            'suppliers': suppliers_report,
            'total_suppliers': len(suppliers_report),
            'filters': {
                'company_id': company_id,
                'year': year,
                'month': month,
                'limit': limit
            }
        }), 200
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

@reports_bp.route('/reports/expense-types', methods=['GET'])
@require_auth
def get_expense_types_report():
    """Obtener reporte de gastos por tipo"""
    try:
        user_role = session.get('user_role')
        user_company_id = session.get('company_id')
        
        # Parámetros de filtro
        company_id = request.args.get('company_id', user_company_id, type=int)
        year = request.args.get('year', type=int)
        month = request.args.get('month', type=int)
        
        # Verificar permisos
        if user_role == 'accountant' and company_id != user_company_id:
            return jsonify({'error': 'No autorizado'}), 403
        elif user_role == 'employee':
            return jsonify({'error': 'No autorizado'}), 403
        
        # Construir query
        query = Invoice.query.filter_by(status='approved')
        
        if user_role == 'super_admin':
            if company_id:
                query = query.filter_by(company_id=company_id)
        else:
            query = query.filter_by(company_id=user_company_id)
        
        # Filtros de período
        if year:
            query = query.filter(db.extract('year', Invoice.invoice_date) == year)
        if month:
            query = query.filter(db.extract('month', Invoice.invoice_date) == month)
        
        # Agrupar por tipo de gasto
        expense_data = db.session.query(
            Invoice.expense_type,
            Invoice.expense_description,
            db.func.count(Invoice.id).label('invoice_count'),
            db.func.sum(Invoice.invoiced_amount).label('total_amount'),
            db.func.sum(Invoice.itbis_invoiced).label('total_itbis')
        ).filter(
            Invoice.id.in_(query.with_entities(Invoice.id))
        ).group_by(
            Invoice.expense_type, Invoice.expense_description
        ).order_by(
            db.func.sum(Invoice.invoiced_amount).desc()
        ).all()
        
        expense_report = [
            {
                'expense_type': expense.expense_type or '06',
                'expense_description': expense.expense_description or 'Sin descripción',
                'invoice_count': expense.invoice_count,
                'total_amount': float(expense.total_amount or 0),
                'total_itbis': float(expense.total_itbis or 0)
            }
            for expense in expense_data
        ]
        
        return jsonify({
            'success': True,
            'expense_types': expense_report,
            'filters': {
                'company_id': company_id,
                'year': year,
                'month': month
            }
        }), 200
        
    except Exception as e:
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500

