from __future__ import annotations

import json
import logging
from typing import Optional

from sqlalchemy.orm import Session

from .alta_log_dto import (
    DodaAltaLogCreateDTO,
    DodaAltaLogListResponse,
    DodaAltaLogResponseDTO,
    DodaAltaLogUpdateDTO,
)
from .alta_log_models import DodaAltaLog
from .models import Doda

logger = logging.getLogger(__name__)


class DodaAltaLogService:

    @staticmethod
    def list(
        db: Session,
        company_id: int,
        tenant_id: int,
        page: int = 1,
        page_size: int = 50,
        doda_id: Optional[int] = None,
        search: Optional[str] = None,
    ) -> DodaAltaLogListResponse:
        query = (
            db.query(DodaAltaLog)
            .filter(
                DodaAltaLog.company_id == company_id,
                DodaAltaLog.tenant_id == tenant_id,
                DodaAltaLog.deleted_at.is_(None),
            )
        )
        if doda_id:
            query = query.filter(DodaAltaLog.doda_id == doda_id)
        if search:
            like = f"%{search}%"
            query = query.filter(
                DodaAltaLog.task_id.ilike(like)
                | DodaAltaLog.integration_number.ilike(like)
                | DodaAltaLog.patent.ilike(like)
                | DodaAltaLog.status.ilike(like)
            )
        total = query.count()
        items = (
            query.order_by(DodaAltaLog.id.desc())
            .offset((page - 1) * page_size)
            .limit(page_size)
            .all()
        )
        return DodaAltaLogListResponse(
            items=[DodaAltaLogResponseDTO.model_validate(r) for r in items],
            total=total,
            page=page,
            page_size=page_size,
        )

    @staticmethod
    def get(
        db: Session, record_id: int, company_id: int, tenant_id: int
    ) -> Optional[DodaAltaLog]:
        return (
            db.query(DodaAltaLog)
            .filter(
                DodaAltaLog.id == record_id,
                DodaAltaLog.company_id == company_id,
                DodaAltaLog.tenant_id == tenant_id,
                DodaAltaLog.deleted_at.is_(None),
            )
            .first()
        )

    @staticmethod
    def create(
        db: Session, dto: DodaAltaLogCreateDTO, company_id: int, tenant_id: int
    ) -> DodaAltaLog:
        record = DodaAltaLog(
            company_id=company_id,
            tenant_id=tenant_id,
            **dto.model_dump(exclude_none=False),
        )
        db.add(record)
        db.commit()
        db.refresh(record)
        return record

    @staticmethod
    def update(
        db: Session, record: DodaAltaLog, dto: DodaAltaLogUpdateDTO
    ) -> DodaAltaLog:
        for field, value in dto.model_dump(exclude_unset=True).items():
            setattr(record, field, value)
        db.commit()
        db.refresh(record)
        return record

    @staticmethod
    def delete(db: Session, record: DodaAltaLog) -> None:
        from datetime import datetime
        record.deleted_at = datetime.utcnow()
        db.commit()

    @staticmethod
    def create_from_alta_result(
        db: Session,
        doda: Doda,
        company_id: int,
        tenant_id: int,
        variant: str,
        ext_result: dict,
        action: str = "alta",
    ) -> DodaAltaLog:
        """
        Crea un registro de log a partir de la respuesta del servicio externo de alta.
        Llamado automáticamente al completar `POST /{doda_id}/alta`.
        """
        task_id = ext_result.get("task_id") or ext_result.get("id") or ""
        status = ext_result.get("status") or "pending"
        message = ext_result.get("message") or ""

        dto = DodaAltaLogCreateDTO(
            doda_id=doda.id,
            variant=variant,
            action=action,
            responsible=doda.responsible,
            patent=doda.patent,
            dispatch_customs=doda.dispatch_customs,
            operation_type=doda.operation_type,
            integration_number=doda.integration_number,
            task_id=task_id,
            status=status,
            message=message,
            result_json=json.dumps(ext_result),
        )
        return DodaAltaLogService.create(db, dto, company_id, tenant_id)
