import logging
from azbankgateways import (
    bankfactories,
    models as bank_models,
    default_settings as settings,
)
from .models import OrderModel
from account.models import PushSubscription
import ghasedak_sms
from product.models import ProductImageModel
from celery import shared_task

@shared_task
def udpate_bank_status():
    factory = bankfactories.BankFactory()

    bank_models.Bank.objects.update_expire_records()

    for item in bank_models.Bank.objects.filter_return_from_bank():
        bank = factory.create(
            bank_type=item.bank_type, identifier=item.bank_choose_identifier
        )
        bank.verify(item.tracking_code)
        bank_record = bank_models.Bank.objects.get(tracking_code=item.tracking_code)
        if bank_record.is_success:
            bank_record.order.cart.clear_cart()
            bank_record.order.is_paid = True
            bank_record.order.save()
            logging.debug("This record is verify now.", extra={"pk": bank_record.pk})
        else:
            order = bank_record.order
            order.rollback_stock()
    return 'update bank record is done'


@shared_task
def send_change_status_notif(instance_pk, new_status):
    instance = OrderModel.objects.get(pk=instance_pk)
    user_subs = PushSubscription.objects.filter(user=instance.user)
    for user_sub in user_subs:
        try:
            user_sub.send_notif(f'سفارش شما به {new_status} تغییر کرد', f'سفارش شما به {new_status} تغییر کرد', ProductImageModel.objects.all().first().image.url)
        except:
            print('log later send notif error')

@shared_task
def send_change_status_sms(instance_pk, new_status):
    instance = OrderModel.objects.get(pk=instance_pk)
    sms_api = ghasedak_sms.Ghasedak(api_key="8f7396f1e3c39e3a4621009c558d955336eea6d21cf257dd74ae262d6f22a458XdoDjH6egJsiZsy8")


    response = sms_api.send_single_sms(
        ghasedak_sms.SendSingleSmsInput(
            message=f'سفارش شما به {new_status} تغییر کرد',
            receptor=instance.user.phone,
            line_number='30005006004095',
            client_reference_id=str(instance.user.pk)
        )
    )
    if response['statusCode'] == 200: 
        return 'done log later'
    else:
        return f'error: {response}'


@shared_task
def generate_daily_shop_reports():
    """Generate daily shop reports for the previous day.
    
    This task aggregates ShopOrderModel entries from yesterday
    and creates/updates ShopDailyReport records for each shop.
    Scheduled to run daily at midnight.
    """
    from django.utils import timezone
    from datetime import timedelta
    from django.db.models import Sum
    from .models import ShopOrderModel, ShopDailyReport

    target_date = (timezone.now() - timedelta(days=1)).date()
    print(f'Generating shop reports for {target_date}')
    
    shop_orders = ShopOrderModel.objects.filter(created_at__date=target_date)
    if not shop_orders.exists():
        logging.warning(f'No shop orders found for {target_date}')
        return f'No shop orders for {target_date}'
    
    shops = shop_orders.values('shop').distinct()
    reports_created = 0
    reports_updated = 0
    
    for s in shops:
        shop_id = s['shop']
        aggr = shop_orders.filter(shop_id=shop_id).aggregate(
            total_sales=Sum('subtotal'),
            total_commission=Sum('commission_amount'),
            total_payable=Sum('payable_amount')
        )
        
        total_sales = aggr['total_sales'] or 0
        total_commission = aggr['total_commission'] or 0
        total_payable = aggr['total_payable'] or 0
        
        report, created = ShopDailyReport.objects.update_or_create(
            shop_id=shop_id,
            date=target_date,
            defaults={
                'total_sales': total_sales,
                'total_commission': total_commission,
                'total_payable': total_payable,
            }
        )
        
        # Link all shop orders for this shop and date to the daily report
        shop_orders.filter(shop_id=shop_id).update(daily_report=report)
        
        if created:
            reports_created += 1
        else:
            reports_updated += 1
        
        logging.info(f"Shop {shop_id}: sales={total_sales}, commission={total_commission}, payable={total_payable}")
    
    result = f'Generated reports for {target_date}: {reports_created} created, {reports_updated} updated'
    logging.info(result)
    return result


@shared_task
def send_shop_order_invoice_telegram_task(shop_order_id, chat_id, bot_token):
    """Send shop order invoice PDF to Telegram chat.
    
    Args:
        shop_order_id: ID of the ShopOrderModel
        chat_id: Telegram chat ID to send invoice to
        bot_token: Telegram bot token for authentication
        
    Returns:
        Success or error message
    """
    import telebot
    from .invoice_generator import generate_shop_order_invoice
    from .models import ShopOrderModel

    try:
        # Get the shop order
        shop_order = ShopOrderModel.objects.get(pk=shop_order_id)

        # Generate invoice PDF (should return a file-like object)
        pdf_buffer = generate_shop_order_invoice(shop_order_id)
        if hasattr(pdf_buffer, 'seek'):
            pdf_buffer.seek(0)

        caption = f'فاکتور سفارش #{shop_order_id}\n{shop_order.shop.shop_name}'

        # Initialize bot and send document
        bot = telebot.TeleBot(bot_token)
        bot.send_document(
            chat_id=chat_id,
            document=pdf_buffer,
            caption=caption,
            visible_file_name=f'invoice_shop_order_{shop_order_id}.pdf'
        )

        logging.info(f'Successfully sent shop order invoice {shop_order_id} to Telegram chat {chat_id}')
        return f'Invoice sent successfully to chat {chat_id}'

    except ShopOrderModel.DoesNotExist:
        error_msg = f'ShopOrderModel with id {shop_order_id} does not exist'
        logging.error(error_msg)
        return error_msg
    except telebot.apihelper.ApiException as e:
        error_msg = f'Telegram API error sending invoice {shop_order_id}: {str(e)}'
        logging.error(error_msg)
        return error_msg
    except Exception as e:
        error_msg = f'Error sending invoice {shop_order_id} to Telegram: {str(e)}'
        logging.error(error_msg)
        return error_msg
