from typing import Optional
from uuid import UUID
from datetime import datetime

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.core.module_framework.event_bus import event_bus

from app.modules.partners.domain.entities import Partner
from app.modules.partners.infrastructure.repositories import PartnerRepository

class CreatePartnerCommand(ICommand):
    name: str
    type: str
    tax_code: Optional[str] = None
    address: Optional[str] = None

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

    @log_execution
    @transactional
    def handle(self, command: CreatePartnerCommand) -> UUID:
        repo = PartnerRepository(self._conn)
        
        # 1. Tạo Entity (Logic Validate tự động chạy)
        partner = Partner(
            name=command.name,
            type=command.type,
            tax_code=command.tax_code,
            address=command.address
        )
        
        # 2. Lưu xuống Database (schema partners)
        repo.save(partner)
        
        # 3. Publish Event ra hệ thống (Ví dụ module Invoices cần biết để tạo hồ sơ công nợ)
        event_payload = {
            "partner_id": str(partner.id),
            "name": partner.name,
            "type": partner.type,
            "tax_code": partner.tax_code,
            "timestamp": datetime.utcnow().isoformat()
        }
        
        with self._conn.cursor() as cur:
            # Lưu sự kiện vào outbox
            event_bus.publish_outbox(cur, "PartnerCreatedIntegrationEvent", event_payload)
            
        return partner.id

class UpdatePartnerScoreCommand(ICommand):
    """[D6] Lệnh cập nhật điểm tín nhiệm đối tác."""
    tax_code: str
    deduct_points: int
    reason: str

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

    @log_execution
    @transactional
    def handle(self, command: UpdatePartnerScoreCommand) -> None:
        import logging
        logger = logging.getLogger(__name__)
        
        with self._conn.cursor() as cur:
            # Đọc điểm hiện tại
            cur.execute("""
                SELECT id, status, credit_score 
                FROM partners.partners 
                WHERE tax_code = %s FOR UPDATE
            """, (command.tax_code,))
            
            row = cur.fetchone()
            if not row:
                logger.warning(f"[Partners] Không tìm thấy đối tác với tax_code {command.tax_code}")
                return
                
            current_score = row.get('credit_score', 100)
            new_score = current_score - command.deduct_points
            new_status = row.get('status', 'ACTIVE')
            
            if new_score < 50:
                new_status = 'BLACKLISTED'
                logger.error(f"[Partners] CẢNH BÁO: Đối tác {command.tax_code} điểm tín nhiệm < 50. Đưa vào BLACKLIST!")
                
            cur.execute("""
                UPDATE partners.partners 
                SET credit_score = %s, status = %s
                WHERE tax_code = %s
            """, (new_score, new_status, command.tax_code))
            
        logger.info(f"[Partners] Đã trừ {command.deduct_points} điểm của {command.tax_code} vì {command.reason}")
