# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""GraphicalEditor models with Auto-prefix: AutoWorkflow, AutoVersion, AutoRun, AutoStepLog, AutoTask."""

from enum import Enum
from typing import Dict, Any, List, Optional
from pydantic import BaseModel, Field
from modules.datamodels.datamodelBase import PowerOnModel
from modules.shared.i18nRegistry import i18nModel
import uuid


# ---------------------------------------------------------------------------
# Enums
# ---------------------------------------------------------------------------

class AutoWorkflowStatus(str, Enum):
    DRAFT = "draft"
    PUBLISHED = "published"
    ARCHIVED = "archived"


class AutoRunStatus(str, Enum):
    RUNNING = "running"
    PAUSED = "paused"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"


class AutoStepStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    SKIPPED = "skipped"


class AutoTaskStatus(str, Enum):
    PENDING = "pending"
    COMPLETED = "completed"
    CANCELLED = "cancelled"
    EXPIRED = "expired"


class AutoTemplateScope(str, Enum):
    USER = "user"
    INSTANCE = "instance"
    MANDATE = "mandate"
    SYSTEM = "system"


# ---------------------------------------------------------------------------
# AutoWorkflow
# ---------------------------------------------------------------------------

@i18nModel("Workflow")
class AutoWorkflow(PowerOnModel):
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Primary key",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "ID"},
    )
    mandateId: str = Field(
        description="Mandate ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "label": "Mandanten-ID",
            "frontend_fk_source": "/api/mandates/",
            "frontend_fk_display_field": "label",
            "fk_model": "Mandate",
        },
    )
    featureInstanceId: str = Field(
        description="Feature instance ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "label": "Feature-Instanz-ID",
            "frontend_fk_source": "/api/features/instances",
            "frontend_fk_display_field": "label",
            "fk_model": "FeatureInstance",
        },
    )
    label: str = Field(
        description="User-friendly workflow name",
        json_schema_extra={"frontend_type": "text", "frontend_required": True, "label": "Bezeichnung"},
    )
    description: Optional[str] = Field(
        default=None,
        description="Workflow description",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Beschreibung"},
    )
    tags: List[str] = Field(
        default_factory=list,
        description="Tags for categorization",
        json_schema_extra={"frontend_type": "tags", "frontend_required": False, "label": "Tags"},
    )
    isTemplate: bool = Field(
        default=False,
        description="Whether this workflow is a template",
        json_schema_extra={"frontend_type": "checkbox", "frontend_required": False, "label": "Ist Vorlage"},
    )
    templateSourceId: Optional[str] = Field(
        default=None,
        description="ID of the template this workflow was created from",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Vorlagen-Quelle"},
    )
    templateScope: Optional[str] = Field(
        default=None,
        description="Template scope: user, instance, mandate, system (AutoTemplateScope)",
        json_schema_extra={"frontend_type": "select", "frontend_required": False, "label": "Vorlagen-Bereich"},
    )
    sharedReadOnly: bool = Field(
        default=False,
        description="If true, shared template is read-only for non-owners",
        json_schema_extra={"frontend_type": "checkbox", "frontend_required": False, "label": "Freigabe nur-lesen"},
    )
    currentVersionId: Optional[str] = Field(
        default=None,
        description="ID of the currently published AutoVersion",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Aktuelle Version"},
    )
    active: bool = Field(
        default=True,
        description="Whether workflow is active",
        json_schema_extra={"frontend_type": "checkbox", "frontend_required": False, "label": "Aktiv"},
    )
    eventId: Optional[str] = Field(
        default=None,
        description="Scheduler event ID for incremental sync",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Event-ID"},
    )
    notifyOnFailure: bool = Field(
        default=True,
        description="Send notification (in-app + email) when a run fails",
        json_schema_extra={"frontend_type": "checkbox", "frontend_required": False, "label": "Bei Fehler benachrichtigen"},
    )
    # Legacy fields kept for backward compatibility during transition
    graph: Dict[str, Any] = Field(
        default_factory=dict,
        description="Graph with nodes and connections (legacy; prefer AutoVersion.graph)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Graph"},
    )
    invocations: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="Entry points / starts (manual, form, schedule, webhook, ...)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Starts / Einstiegspunkte"},
    )


# ---------------------------------------------------------------------------
# AutoVersion
# ---------------------------------------------------------------------------

@i18nModel("Workflow-Version")
class AutoVersion(PowerOnModel):
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Primary key",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "ID"},
    )
    workflowId: str = Field(
        description="FK -> AutoWorkflow",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Workflow-ID"},
    )
    versionNumber: int = Field(
        default=1,
        description="Incrementing version number",
        json_schema_extra={"frontend_type": "number", "frontend_readonly": True, "frontend_required": False, "label": "Version"},
    )
    status: str = Field(
        default=AutoWorkflowStatus.DRAFT.value,
        description="Version status: draft, published, archived",
        json_schema_extra={"frontend_type": "select", "frontend_required": False, "label": "Status"},
    )
    graph: Dict[str, Any] = Field(
        default_factory=dict,
        description="Graph with nodes and connections (incl. node parameters)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": True, "label": "Graph"},
    )
    invocations: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="Entry points / starts for this version",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Einstiegspunkte"},
    )
    publishedAt: Optional[float] = Field(
        default=None,
        description="Timestamp when version was published",
        json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": False, "label": "Veröffentlicht am"},
    )
    publishedBy: Optional[str] = Field(
        default=None,
        description="User ID who published this version",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Veröffentlicht von"},
    )


# ---------------------------------------------------------------------------
# AutoRun
# ---------------------------------------------------------------------------

@i18nModel("Workflow-Ausführung")
class AutoRun(PowerOnModel):
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Primary key",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "ID"},
    )
    workflowId: str = Field(
        description="Workflow ID",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Workflow-ID"},
    )
    label: Optional[str] = Field(
        default=None,
        description="Human-readable run label, set at creation from workflow name or caller",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Bezeichnung"},
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID for cross-feature querying",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "label": "Mandanten-ID",
            "frontend_fk_source": "/api/mandates/",
            "frontend_fk_display_field": "label",
            "fk_model": "Mandate",
        },
    )
    ownerId: Optional[str] = Field(
        default=None,
        description="User ID who triggered this run",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Auslöser"},
    )
    versionId: Optional[str] = Field(
        default=None,
        description="AutoVersion ID used for this run",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Versions-ID"},
    )
    status: str = Field(
        default=AutoRunStatus.RUNNING.value,
        description="Status: running, paused, completed, failed, cancelled",
        json_schema_extra={"frontend_type": "text", "frontend_required": False, "label": "Status"},
    )
    trigger: Dict[str, Any] = Field(
        default_factory=dict,
        description="Trigger info (type, entryPointId, payload, etc.)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Auslöser"},
    )
    startedAt: Optional[float] = Field(
        default=None,
        description="Run start timestamp",
        json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": False, "label": "Gestartet am"},
    )
    completedAt: Optional[float] = Field(
        default=None,
        description="Run completion timestamp",
        json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": False, "label": "Abgeschlossen am"},
    )
    nodeOutputs: Dict[str, Any] = Field(
        default_factory=dict,
        description="Outputs from executed nodes",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Node-Ausgaben"},
    )
    currentNodeId: Optional[str] = Field(
        default=None,
        description="Node ID when paused (human task / email wait)",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "Aktueller Knoten"},
    )
    resumeContext: Dict[str, Any] = Field(
        default_factory=dict,
        description="Context for resume (connectionMap, inputSources, etc.)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Wiederaufnahme-Kontext"},
    )
    error: Optional[str] = Field(
        default=None,
        description="Error message if failed",
        json_schema_extra={"frontend_type": "textarea", "frontend_readonly": True, "frontend_required": False, "label": "Fehler"},
    )
    costTokens: int = Field(
        default=0,
        description="Total tokens consumed by AI nodes",
        json_schema_extra={"frontend_type": "number", "frontend_readonly": True, "frontend_required": False, "label": "Verbrauchte Tokens"},
    )
    costCredits: float = Field(
        default=0.0,
        description="Total credits consumed",
        json_schema_extra={"frontend_type": "number", "frontend_readonly": True, "frontend_required": False, "label": "Verbrauchte Credits"},
    )


# ---------------------------------------------------------------------------
# AutoStepLog
# ---------------------------------------------------------------------------

@i18nModel("Schritt-Protokoll")
class AutoStepLog(PowerOnModel):
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Primary key",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "ID"},
    )
    runId: str = Field(
        description="FK -> AutoRun",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Lauf-ID"},
    )
    nodeId: str = Field(
        description="Node ID in the graph",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Knoten-ID"},
    )
    nodeType: str = Field(
        description="Node type (e.g. ai.chat, email.send)",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Knotentyp"},
    )
    status: str = Field(
        default=AutoStepStatus.PENDING.value,
        description="Step status: pending, running, completed, failed, skipped",
        json_schema_extra={"frontend_type": "text", "frontend_required": False, "label": "Status"},
    )
    inputSnapshot: Dict[str, Any] = Field(
        default_factory=dict,
        description="Snapshot of inputs at execution time",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Eingabe-Snapshot"},
    )
    output: Dict[str, Any] = Field(
        default_factory=dict,
        description="Node output",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Ausgabe"},
    )
    error: Optional[str] = Field(
        default=None,
        description="Error message if step failed",
        json_schema_extra={"frontend_type": "textarea", "frontend_readonly": True, "frontend_required": False, "label": "Fehler"},
    )
    startedAt: Optional[float] = Field(
        default=None,
        description="Step start timestamp",
        json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": False, "label": "Gestartet am"},
    )
    completedAt: Optional[float] = Field(
        default=None,
        description="Step completion timestamp",
        json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": False, "label": "Abgeschlossen am"},
    )
    durationMs: Optional[int] = Field(
        default=None,
        description="Execution duration in milliseconds",
        json_schema_extra={"frontend_type": "number", "frontend_readonly": True, "frontend_required": False, "label": "Dauer (ms)"},
    )
    tokensUsed: int = Field(
        default=0,
        description="Tokens consumed by this step",
        json_schema_extra={"frontend_type": "number", "frontend_readonly": True, "frontend_required": False, "label": "Verbrauchte Tokens"},
    )
    retryCount: int = Field(
        default=0,
        description="Number of retries executed",
        json_schema_extra={"frontend_type": "number", "frontend_readonly": True, "frontend_required": False, "label": "Wiederholungen"},
    )


# ---------------------------------------------------------------------------
# AutoTask
# ---------------------------------------------------------------------------

@i18nModel("Aufgabe")
class AutoTask(PowerOnModel):
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Primary key",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False, "label": "ID"},
    )
    runId: str = Field(
        description="FK -> AutoRun",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Lauf-ID"},
    )
    workflowId: str = Field(
        description="Workflow ID",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Workflow-ID"},
    )
    nodeId: str = Field(
        description="Node ID in the graph",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Knoten-ID"},
    )
    nodeType: str = Field(
        description="Node type: form, approval, upload, comment, review, selection, confirmation",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "label": "Knotentyp"},
    )
    config: Dict[str, Any] = Field(
        default_factory=dict,
        description="Node config (form schema, approval text, etc.)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Konfiguration"},
    )
    assigneeId: Optional[str] = Field(
        default=None,
        description="User ID assigned to complete the task",
        json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": False, "label": "Zugewiesen an"},
    )
    status: str = Field(
        default=AutoTaskStatus.PENDING.value,
        description="Status: pending, completed, cancelled, expired",
        json_schema_extra={"frontend_type": "text", "frontend_required": False, "label": "Status"},
    )
    result: Optional[Dict[str, Any]] = Field(
        default=None,
        description="Task result (form data, approval decision, etc.)",
        json_schema_extra={"frontend_type": "textarea", "frontend_required": False, "label": "Ergebnis"},
    )
    expiresAt: Optional[float] = Field(
        default=None,
        description="Expiration timestamp for the task",
        json_schema_extra={"frontend_type": "datetime", "frontend_required": False, "label": "Läuft ab am"},
    )


# ---------------------------------------------------------------------------
# Backward-compatible aliases for transition period
# ---------------------------------------------------------------------------

Automation2Workflow = AutoWorkflow
Automation2WorkflowRun = AutoRun
Automation2HumanTask = AutoTask
