import logging
import uuid
from datetime import datetime

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.content import Content
from app.models.distribution import DistributionSchedule
from app.services.distribution.formatter import ContentFormatter
from app.services.distribution.publishers import get_publisher
from app.services.distribution.publishers.base import PublishResult

logger = logging.getLogger(__name__)


class PublishEngine:
    def __init__(self):
        self._formatter = ContentFormatter()

    async def publish_content(
        self,
        content_id: str,
        platforms: list[str],
        db: AsyncSession,
        user_id: str,
        org_id: str,
    ) -> list[PublishResult]:
        stmt = select(Content).where(Content.id == uuid.UUID(content_id))
        result = await db.execute(stmt)
        content = result.scalar_one_or_none()

        if not content:
            raise ValueError(f"Content not found: {content_id}")

        results: list[PublishResult] = []
        platform_results: list[dict] = []

        for platform in platforms:
            publisher = get_publisher(platform)
            formatted = self._formatter.format_for_platform(content.body or "", platform)

            try:
                pub_result = await publisher.publish(
                    title=content.title,
                    content=formatted,
                )
                results.append(pub_result)
                platform_results.append({
                    "platform": platform,
                    "status": "published" if pub_result.success else "failed",
                    "article_id": pub_result.article_id,
                    "article_url": pub_result.article_url,
                    "error": pub_result.error,
                    "published_at": datetime.now().isoformat() if pub_result.success else None,
                })
            except Exception as e:
                logger.error(f"Publish to {platform} failed: {e}")
                fail_result = PublishResult(
                    success=False,
                    platform=platform,
                    error=str(e),
                )
                results.append(fail_result)
                platform_results.append({
                    "platform": platform,
                    "status": "failed",
                    "error": str(e),
                })

        schedule = DistributionSchedule(
            organization_id=uuid.UUID(org_id) if isinstance(org_id, str) else org_id,
            content_title=content.title,
            content_id=content.id,
            platforms=platform_results,
            status="published" if all(r.success for r in results) else "partial",
            created_by=user_id,
        )
        db.add(schedule)
        await db.commit()

        return results

    async def get_publish_status(
        self,
        content_id: str,
        db: AsyncSession,
    ) -> list[dict]:
        stmt = (
            select(DistributionSchedule)
            .where(DistributionSchedule.content_id == uuid.UUID(content_id))
            .order_by(DistributionSchedule.created_at.desc())
        )
        result = await db.execute(stmt)
        schedules = result.scalars().all()

        status_list: list[dict] = []
        for schedule in schedules:
            platforms = schedule.platforms or []
            for p in platforms:
                status_list.append({
                    "platform": p.get("platform", ""),
                    "status": p.get("status", "unknown"),
                    "article_url": p.get("article_url"),
                    "published_at": p.get("published_at"),
                })

        return status_list
