"""Pydantic schemas used across routes."""
from datetime import datetime, timezone
from typing import Optional, List, Literal
from pydantic import BaseModel, EmailStr, Field, ConfigDict


Role = Literal[
    "ceo", "admin", "rh", "pm", "pmo",
    "sales", "marketing", "account_manager",
    "collaborator", "client",
]
TaskStatus = Literal["backlog", "todo", "in_progress", "review", "done"]
Priority = Literal["low", "medium", "high"]
ClientStatus = Literal["lead", "active", "inactive", "won", "lost"]
ProposalStatus = Literal["pending", "reviewing", "accepted", "rejected", "converted"]
NotificationType = Literal["message", "project_assigned", "project_unassigned", "proposal_new", "milestone_updated"]


# Roles that can manage client communications
CLIENT_CHAT_ROLES = {"ceo", "admin", "pm", "pmo", "sales", "account_manager"}
# Roles allowed to create users
USER_MGMT_ROLES = {"ceo", "admin", "rh"}
# Roles allowed to manage departments
DEPT_MGMT_ROLES = {"ceo", "admin"}
# Roles that can access marketing/CRM
MARKETING_ROLES = {"ceo", "admin", "sales", "marketing", "pmo", "account_manager"}


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


# ---------------- Auth ----------------
class LoginIn(BaseModel):
    email: EmailStr
    password: str


class UserOut(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str
    email: EmailStr
    name: str
    role: Role
    department_id: Optional[str] = None
    avatar_url: Optional[str] = None
    active: bool = True
    must_change_password: bool = False
    created_at: Optional[str] = None


# ---------------- Users ----------------
class CreateUserIn(BaseModel):
    email: EmailStr
    name: str
    role: Role
    department_id: Optional[str] = None
    send_invite: bool = True


class UpdateUserIn(BaseModel):
    name: Optional[str] = None
    role: Optional[Role] = None
    department_id: Optional[str] = None
    password: Optional[str] = None


class ActivateIn(BaseModel):
    token: str
    new_password: str = Field(min_length=8)


class ChangePasswordIn(BaseModel):
    current_password: str
    new_password: str = Field(min_length=8)


# ---------------- Departments ----------------
class DepartmentIn(BaseModel):
    name: str = Field(min_length=2)
    description: Optional[str] = ""
    color: Optional[str] = "#00E599"


# ---------------- CRM Clients ----------------
class CRMClientIn(BaseModel):
    name: str = Field(min_length=2)
    email: Optional[EmailStr] = None
    phone: Optional[str] = None
    company: Optional[str] = ""
    status: ClientStatus = "lead"
    owner_id: Optional[str] = None
    notes: Optional[str] = ""
    tags: List[str] = []


class CRMClientUpdate(BaseModel):
    name: Optional[str] = None
    email: Optional[EmailStr] = None
    phone: Optional[str] = None
    company: Optional[str] = None
    status: Optional[ClientStatus] = None
    owner_id: Optional[str] = None
    notes: Optional[str] = None
    tags: Optional[List[str]] = None


class CRMNoteIn(BaseModel):
    body: str = Field(min_length=1)


# ---------------- Email templates / campaigns ----------------
class EmailTemplateIn(BaseModel):
    name: str
    subject: str
    body_html: str
    description: Optional[str] = ""


class SendEmailIn(BaseModel):
    to: EmailStr
    subject: str
    body_html: str
    crm_client_id: Optional[str] = None
    template_id: Optional[str] = None


class CampaignIn(BaseModel):
    name: str
    subject: str
    body_html: str
    audience_status: Optional[ClientStatus] = None  # filter CRM by status
    audience_tags: Optional[List[str]] = None  # filter by any tag
    audience_emails: Optional[List[EmailStr]] = None  # ad-hoc


# ---------------- Projects ----------------
class ProjectIn(BaseModel):
    name: str
    description: Optional[str] = ""
    client_id: Optional[str] = None
    pm_id: Optional[str] = None
    collaborator_ids: List[str] = []
    status: Literal["discovery", "design", "development", "qa", "delivered"] = "discovery"


class ProjectUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    client_id: Optional[str] = None
    pm_id: Optional[str] = None
    collaborator_ids: Optional[List[str]] = None
    status: Optional[Literal["discovery", "design", "development", "qa", "delivered"]] = None


class MilestoneIn(BaseModel):
    label: str
    completed: bool = False


# ---------------- Tasks ----------------
class TaskIn(BaseModel):
    project_id: str
    title: str
    description: Optional[str] = ""
    status: TaskStatus = "backlog"
    priority: Priority = "medium"
    assignee_id: Optional[str] = None
    due_date: Optional[str] = None


class TaskUpdate(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    status: Optional[TaskStatus] = None
    priority: Optional[Priority] = None
    assignee_id: Optional[str] = None
    due_date: Optional[str] = None


# ---------------- CMS ----------------
class ServiceItem(BaseModel):
    title: str
    description: str
    icon: str = "Sparkles"
    order: int = 0


class TestimonialItem(BaseModel):
    name: str
    role: str
    company: str
    quote: str
    avatar_url: Optional[str] = None
    order: int = 0


class PortfolioItem(BaseModel):
    title: str
    category: str
    description: str
    image_url: str
    link: Optional[str] = None
    order: int = 0


class SiteCopyIn(BaseModel):
    hero_eyebrow: Optional[str] = None
    hero_title: Optional[str] = None
    hero_subtitle: Optional[str] = None
    hero_cta_label: Optional[str] = None
    about_title: Optional[str] = None
    about_body: Optional[str] = None
    values: Optional[List[dict]] = None


# ---------------- Contact ----------------
class ContactIn(BaseModel):
    name: str = Field(min_length=2)
    email: EmailStr
    company: Optional[str] = ""
    message: str = Field(min_length=10)


# ---------------- Chat ----------------
class MessageIn(BaseModel):
    channel_id: str
    body: str = Field(min_length=1, max_length=4000)


class ChannelCreateIn(BaseModel):
    name: str
    type: Literal["team", "department"] = "team"
    department_id: Optional[str] = None
    member_ids: List[str] = []


# ---------------- Proposals ----------------
class ProposalIn(BaseModel):
    """Submitted by clients via portal — request for new proposal."""
    title: str = Field(min_length=3)
    description: str = Field(min_length=10)
    budget_range: Optional[str] = ""
    timeline: Optional[str] = ""


class ProposalUpdate(BaseModel):
    status: Optional[ProposalStatus] = None
    response: Optional[str] = None
    assigned_to_id: Optional[str] = None
