# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""
CommCoach Feature - Data Models.
Pydantic models for coaching contexts, sessions, messages, tasks, scores, and user profiles.
"""
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
from enum import Enum

from modules.datamodels.datamodelBase import PowerOnModel
import uuid


# ============================================================================
# Enums
# ============================================================================

class CoachingContextStatus(str, Enum):
    ACTIVE = "active"
    PAUSED = "paused"
    ARCHIVED = "archived"
    COMPLETED = "completed"


class CoachingContextCategory(str, Enum):
    LEADERSHIP = "leadership"
    CONFLICT = "conflict"
    NEGOTIATION = "negotiation"
    PRESENTATION = "presentation"
    FEEDBACK = "feedback"
    DELEGATION = "delegation"
    CHANGE_MANAGEMENT = "changeManagement"
    CUSTOM = "custom"


class CoachingSessionStatus(str, Enum):
    ACTIVE = "active"
    COMPLETED = "completed"
    CANCELLED = "cancelled"


class CoachingMessageRole(str, Enum):
    USER = "user"
    ASSISTANT = "assistant"
    SYSTEM = "system"


class CoachingMessageContentType(str, Enum):
    TEXT = "text"
    AUDIO_TRANSCRIPT = "audioTranscript"
    SYSTEM_NOTE = "systemNote"


class CoachingTaskStatus(str, Enum):
    OPEN = "open"
    IN_PROGRESS = "inProgress"
    DONE = "done"
    SKIPPED = "skipped"


class CoachingTaskPriority(str, Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"


class CoachingScoreTrend(str, Enum):
    IMPROVING = "improving"
    STABLE = "stable"
    DECLINING = "declining"


# ============================================================================
# Database Models
# ============================================================================

class CoachingContext(PowerOnModel):
    """A coaching context/dossier representing a topic the user is working on."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    userId: str = Field(description="Owner user ID (strict ownership)")
    mandateId: str = Field(description="Mandate ID")
    instanceId: str = Field(description="Feature instance ID")
    title: str = Field(description="Context title, e.g. 'Conflict with team lead'")
    description: Optional[str] = Field(default=None, description="Short description")
    category: CoachingContextCategory = Field(default=CoachingContextCategory.CUSTOM)
    status: CoachingContextStatus = Field(default=CoachingContextStatus.ACTIVE)
    goals: Optional[str] = Field(default=None, description="JSON array of goals [{id, text, status, createdAt}]")
    insights: Optional[str] = Field(default=None, description="JSON array of AI insights [{id, text, sessionId, createdAt}]")
    metadata: Optional[str] = Field(default=None, description="JSON object with flexible metadata")
    sessionCount: int = Field(default=0)
    taskCount: int = Field(default=0)
    lastSessionAt: Optional[str] = Field(default=None)
    rollingOverview: Optional[str] = Field(default=None, description="AI summary of older sessions for long context history")
    rollingOverviewUpToSessionCount: Optional[int] = Field(default=None, description="Session count covered by rollingOverview")


class CoachingSession(PowerOnModel):
    """A single coaching conversation session within a context."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    contextId: str = Field(description="FK to CoachingContext")
    userId: str = Field(description="Owner user ID")
    mandateId: str = Field(description="Mandate ID")
    instanceId: str = Field(description="Feature instance ID")
    status: CoachingSessionStatus = Field(default=CoachingSessionStatus.ACTIVE)
    personaId: Optional[str] = Field(default=None, description="FK to CoachingPersona (Iteration 2)")
    summary: Optional[str] = Field(default=None, description="AI-generated session summary")
    coachNotes: Optional[str] = Field(default=None, description="JSON: AI internal notes for continuity")
    compressedHistorySummary: Optional[str] = Field(default=None, description="AI summary of older messages for long sessions")
    compressedHistoryUpToMessageCount: Optional[int] = Field(default=None, description="Message count covered by compressedHistorySummary")
    keyTopics: Optional[str] = Field(default=None, description="JSON array of key topics extracted at session complete")
    durationSeconds: int = Field(default=0)
    messageCount: int = Field(default=0)
    competenceScore: Optional[float] = Field(default=None, ge=0.0, le=100.0)
    emailSent: bool = Field(default=False)
    startedAt: Optional[str] = Field(default=None)
    endedAt: Optional[str] = Field(default=None)


class CoachingMessage(PowerOnModel):
    """A single message in a coaching session."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    sessionId: str = Field(description="FK to CoachingSession")
    contextId: str = Field(description="FK to CoachingContext")
    userId: str = Field(description="Owner user ID")
    role: CoachingMessageRole = Field(description="Message author role")
    content: str = Field(description="Message content (Markdown)")
    contentType: CoachingMessageContentType = Field(default=CoachingMessageContentType.TEXT)
    audioRef: Optional[str] = Field(default=None, description="Reference to audio file")
    metadata: Optional[str] = Field(default=None, description="JSON: token count, voice info, etc.")


class CoachingTask(PowerOnModel):
    """A task/checklist item assigned within a coaching context."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    contextId: str = Field(description="FK to CoachingContext")
    sessionId: Optional[str] = Field(default=None, description="FK to originating session")
    userId: str = Field(description="Owner user ID")
    mandateId: str = Field(description="Mandate ID")
    title: str = Field(description="Task title")
    description: Optional[str] = Field(default=None)
    status: CoachingTaskStatus = Field(default=CoachingTaskStatus.OPEN)
    priority: CoachingTaskPriority = Field(default=CoachingTaskPriority.MEDIUM)
    dueDate: Optional[str] = Field(default=None)
    completedAt: Optional[str] = Field(default=None)


class CoachingScore(PowerOnModel):
    """A competence score for a dimension, recorded after a session."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    contextId: str = Field(description="FK to CoachingContext")
    sessionId: str = Field(description="FK to CoachingSession")
    userId: str = Field(description="Owner user ID")
    mandateId: str = Field(description="Mandate ID")
    dimension: str = Field(description="e.g. empathy, clarity, assertiveness, listening")
    score: float = Field(ge=0.0, le=100.0)
    trend: CoachingScoreTrend = Field(default=CoachingScoreTrend.STABLE)
    evidence: Optional[str] = Field(default=None, description="AI reasoning for the score")


class CoachingUserProfile(PowerOnModel):
    """Per-user coaching profile and preferences."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    userId: str = Field(description="Owner user ID")
    mandateId: str = Field(description="Mandate ID")
    instanceId: str = Field(description="Feature instance ID")
    dailyReminderTime: Optional[str] = Field(default=None, description="HH:MM format")
    dailyReminderEnabled: bool = Field(default=False)
    emailSummaryEnabled: bool = Field(default=True)
    streakDays: int = Field(default=0)
    longestStreak: int = Field(default=0)
    totalSessions: int = Field(default=0)
    totalMinutes: int = Field(default=0)
    lastSessionAt: Optional[str] = Field(default=None)


# ============================================================================
# Iteration 2: Personas
# ============================================================================

class CoachingPersona(PowerOnModel):
    """A roleplay persona for coaching sessions."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    userId: str = Field(description="Owner user ID ('system' for builtins)")
    mandateId: Optional[str] = Field(default=None)
    instanceId: Optional[str] = Field(default=None)
    key: str = Field(description="Unique key, e.g. 'critical_cfo_f'")
    label: str = Field(description="Display label, e.g. 'Kritische CFO'")
    description: str = Field(description="Detailed role description for the AI")
    systemPromptOverride: Optional[str] = Field(default=None, description="Full system prompt override for this persona")
    gender: Optional[str] = Field(default=None, description="m or f")
    category: str = Field(default="builtin", description="'builtin' or 'custom'")
    isActive: bool = Field(default=True)


# ============================================================================
# Iteration 2: Badges / Gamification
# ============================================================================

class CoachingBadge(PowerOnModel):
    """An achievement badge awarded to a user."""
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    userId: str = Field(description="Owner user ID")
    mandateId: str = Field(description="Mandate ID")
    instanceId: str = Field(description="Feature instance ID")
    badgeKey: str = Field(description="Badge identifier, e.g. 'streak_7'")
    awardedAt: Optional[str] = Field(default=None)


# ============================================================================
# API Request/Response Models
# ============================================================================

class CreateContextRequest(BaseModel):
    title: str = Field(description="Context title")
    description: Optional[str] = None
    category: Optional[CoachingContextCategory] = CoachingContextCategory.CUSTOM
    goals: Optional[List[str]] = None


class UpdateContextRequest(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    category: Optional[CoachingContextCategory] = None
    goals: Optional[str] = None


class SendMessageRequest(BaseModel):
    content: str = Field(description="User message text")
    contentType: Optional[CoachingMessageContentType] = CoachingMessageContentType.TEXT
    fileIds: Optional[List[str]] = Field(default=None, description="Attached file IDs for agent context")
    dataSourceIds: Optional[List[str]] = Field(default=None, description="Personal data source IDs")
    featureDataSourceIds: Optional[List[str]] = Field(default=None, description="Feature data source IDs")
    allowedProviders: Optional[List[str]] = Field(default=None, description="Allowed AI providers")


class CreateTaskRequest(BaseModel):
    title: str
    description: Optional[str] = None
    priority: Optional[CoachingTaskPriority] = CoachingTaskPriority.MEDIUM
    dueDate: Optional[str] = None


class UpdateTaskRequest(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    priority: Optional[CoachingTaskPriority] = None
    dueDate: Optional[str] = None


class UpdateTaskStatusRequest(BaseModel):
    status: CoachingTaskStatus


class UpdateProfileRequest(BaseModel):
    dailyReminderTime: Optional[str] = None
    dailyReminderEnabled: Optional[bool] = None
    emailSummaryEnabled: Optional[bool] = None


class StartSessionRequest(BaseModel):
    personaId: Optional[str] = None


class CreatePersonaRequest(BaseModel):
    label: str
    description: str
    gender: Optional[str] = None
    systemPromptOverride: Optional[str] = None


class UpdatePersonaRequest(BaseModel):
    label: Optional[str] = None
    description: Optional[str] = None
    gender: Optional[str] = None
    systemPromptOverride: Optional[str] = None
    isActive: Optional[bool] = None


class DashboardData(BaseModel):
    """Aggregated dashboard data for the user."""
    totalContexts: int = 0
    activeContexts: int = 0
    totalSessions: int = 0
    totalMinutes: int = 0
    streakDays: int = 0
    longestStreak: int = 0
    averageScore: Optional[float] = None
    recentScores: List[Dict[str, Any]] = Field(default_factory=list)
    openTasks: int = 0
    completedTasks: int = 0
    contexts: List[Dict[str, Any]] = Field(default_factory=list)
