from uuid import UUID
from datetime import date
from typing import Optional
from decimal import Decimal
import logging

from app.core.module_framework.cqrs import ICommand, ICommandHandler
from app.core.module_framework.decorators import transactional, log_execution
from app.core.postgres.base_pkg.base_client import BasePostgresClient
from app.modules.invoices.domain.entities import Invoice
from app.modules.invoices.infrastructure.repositories import InvoiceRepository

logger = logging.getLogger(__name__)

class RegisterInvoiceCommand(ICommand):
    invoice_no: str
    supplier_tax_code: str
    total_amount: Decimal
    tax_amount: Decimal
    issue_date: date
    project_id: Optional[UUID] = None

class RegisterInvoiceCommandHandler(ICommandHandler[RegisterInvoiceCommand, UUID]):
    def __init__(self, postgres_client: BasePostgresClient):
        self._postgres_client = postgres_client

    @log_execution
    @transactional
    def handle(self, command: RegisterInvoiceCommand) -> UUID:
        repo = InvoiceRepository(self._conn)
        from app.core.module_framework.event_bus import event_bus
        
        invoice = Invoice(
            invoice_no=command.invoice_no,
            supplier_tax_code=command.supplier_tax_code,
            total_amount=command.total_amount,
            tax_amount=command.tax_amount,
            issue_date=command.issue_date,
            project_id=command.project_id
        )
        
        # [D6] Backfill: Fraud Detection
        if command.total_amount > Decimal("500000000"):
            # Check Partner status (Cross-module Query simulation)
            with self._conn.cursor() as cur:
                cur.execute("SELECT created_at FROM partners.partners WHERE tax_code = %s", (command.supplier_tax_code,))
                partner_row = cur.fetchone()
                
                is_fraud = False
                if not partner_row:
                    is_fraud = True # Đối tác chưa từng tồn tại trong hệ thống
                else:
                    # Giả lập: Nếu đối tác tạo < 30 ngày => nghi ngờ
                    days_active = (datetime.utcnow().date() - partner_row['created_at'].date()).days
                    if days_active < 30:
                        is_fraud = True
                        
                if is_fraud:
                    logger.warning(f"[Invoices] CẢNH BÁO FRAUD: Hóa đơn {command.invoice_no} > 500tr từ NCC rủi ro cao.")
                    invoice.status = "SUSPENDED"
                    
                    event_payload = {
                        "invoice_no": command.invoice_no,
                        "supplier_tax_code": command.supplier_tax_code,
                        "amount": float(command.total_amount)
                    }
                    event_bus.publish_outbox(cur, "InvoiceFraudDetectedEvent", event_payload)
        
        repo.save(invoice)
        return invoice.id

class MarkInvoicePaidCommand(ICommand):
    invoice_id: UUID

class MarkInvoicePaidCommandHandler(ICommandHandler[MarkInvoicePaidCommand, None]):
    def __init__(self, postgres_client: BasePostgresClient):
        self._postgres_client = postgres_client

    @log_execution
    @transactional
    def handle(self, command: MarkInvoicePaidCommand) -> None:
        repo = InvoiceRepository(self._conn)
        
        invoice = repo.get_by_id(command.invoice_id)
        if not invoice:
            raise ValueError(f"Không tìm thấy hóa đơn {command.invoice_id}")
            
        invoice.status = "PAID"
        repo.save(invoice)
        logger.info(f"[Invoices] Hóa đơn {invoice.invoice_no} đã được cập nhật thành PAID")

