"""Workflow persistence for exported automation flows."""

from __future__ import annotations

import json
import uuid
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any

from database import Database
from logging_config import get_logger

log = get_logger(__name__)


@dataclass
class WorkflowEntry:
    """A stored workflow generated from a chat session."""

    id: str
    name: str
    summary: str
    session_id: str
    workflow: dict[str, Any]
    created_at: str
    updated_at: str
    metadata: dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> dict[str, Any]:
        """Serialize to API-friendly dict."""
        steps = self.workflow.get("steps")
        step_count = len(steps) if isinstance(steps, list) else 0
        return {
            "id": self.id,
            "name": self.name,
            "summary": self.summary,
            "session_id": self.session_id,
            "step_count": step_count,
            "created_at": self.created_at,
            "updated_at": self.updated_at,
            "metadata": self.metadata,
            "workflow": self.workflow,
        }

    def to_summary_dict(self) -> dict[str, Any]:
        """Serialize summary list item."""
        steps = self.workflow.get("steps")
        step_count = len(steps) if isinstance(steps, list) else 0
        return {
            "id": self.id,
            "name": self.name,
            "summary": self.summary,
            "session_id": self.session_id,
            "step_count": step_count,
            "created_at": self.created_at,
            "updated_at": self.updated_at,
            "metadata": self.metadata,
        }


class WorkflowStore:
    """SQLite-backed workflow store."""

    def __init__(self, db: Database) -> None:
        self._db = db
        self._log = log.bind(component="workflow_store")

    @staticmethod
    def _row_to_entry(row: Any) -> WorkflowEntry:
        return WorkflowEntry(
            id=row["id"],
            name=row["name"],
            summary=row["summary"],
            session_id=row["session_id"],
            workflow=json.loads(row["workflow_json"]),
            created_at=row["created_at"],
            updated_at=row["updated_at"],
            metadata=json.loads(row["metadata"]),
        )

    def add(
        self,
        name: str,
        summary: str,
        session_id: str,
        workflow: dict[str, Any],
        metadata: dict[str, Any] | None = None,
    ) -> WorkflowEntry:
        """Create and persist a workflow."""
        now = datetime.now(timezone.utc).isoformat()
        entry = WorkflowEntry(
            id=uuid.uuid4().hex[:12],
            name=name.strip() or "Untitled Workflow",
            summary=summary.strip(),
            session_id=session_id,
            workflow=workflow,
            created_at=now,
            updated_at=now,
            metadata=metadata or {},
        )

        self._db.conn.execute(
            """INSERT INTO workflows
               (id, name, summary, session_id, workflow_json, created_at, updated_at, metadata)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
            (
                entry.id,
                entry.name,
                entry.summary,
                entry.session_id,
                json.dumps(entry.workflow, ensure_ascii=False),
                entry.created_at,
                entry.updated_at,
                json.dumps(entry.metadata, ensure_ascii=False),
            ),
        )
        self._db.conn.commit()
        self._log.info(
            "workflow_added",
            workflow_id=entry.id,
            session_id=session_id,
            name=entry.name,
        )
        return entry

    def list_all(self, limit: int = 200) -> list[WorkflowEntry]:
        """List workflows newest-first."""
        rows = self._db.conn.execute(
            """SELECT * FROM workflows
               ORDER BY updated_at DESC
               LIMIT ?""",
            (limit,),
        ).fetchall()
        return [self._row_to_entry(row) for row in rows]

    def get(self, workflow_id: str) -> WorkflowEntry:
        """Load one workflow."""
        row = self._db.conn.execute(
            "SELECT * FROM workflows WHERE id = ?",
            (workflow_id,),
        ).fetchone()
        if row is None:
            raise FileNotFoundError(f"Workflow not found: {workflow_id}")
        return self._row_to_entry(row)

    def update(
        self,
        workflow_id: str,
        *,
        name: str | None = None,
        summary: str | None = None,
        workflow: dict[str, Any] | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> WorkflowEntry:
        """Update fields on an existing workflow and return the updated entry."""
        entry = self.get(workflow_id)
        now = datetime.now(timezone.utc).isoformat()

        if name is not None:
            entry.name = name.strip() or entry.name
        if summary is not None:
            entry.summary = summary.strip()
        if workflow is not None:
            entry.workflow = workflow
        if metadata is not None:
            entry.metadata = metadata
        entry.updated_at = now

        self._db.conn.execute(
            """UPDATE workflows
               SET name = ?, summary = ?, workflow_json = ?,
                   updated_at = ?, metadata = ?
               WHERE id = ?""",
            (
                entry.name,
                entry.summary,
                json.dumps(entry.workflow, ensure_ascii=False),
                entry.updated_at,
                json.dumps(entry.metadata, ensure_ascii=False),
                workflow_id,
            ),
        )
        self._db.conn.commit()
        self._log.info("workflow_updated", workflow_id=workflow_id)
        return entry

    def delete(self, workflow_id: str) -> bool:
        """Delete one workflow."""
        cursor = self._db.conn.execute(
            "DELETE FROM workflows WHERE id = ?",
            (workflow_id,),
        )
        self._db.conn.commit()
        deleted = cursor.rowcount > 0
        if deleted:
            self._log.info("workflow_deleted", workflow_id=workflow_id)
        return deleted
