use chrono::{DateTime, Utc};
use rmcp::schemars;
use serde::{Deserialize, Serialize};

/// Business domain an approval workflow serves. Drives default templates and
/// the kind of agent operating on the request.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum Domain {
    Legal,
    MediaContent,
    General,
}

/// What kind of thing is being approved. Spans the legal and media-content
/// agents (board consents, contracts, policies, brand/QA sign-offs, rights
/// clearance, localization, social posts).
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum RequestType {
    /// Legal — board/written consent requiring director votes.
    BoardConsent,
    /// Legal — contract review and sign-off.
    ContractReview,
    /// Legal — policy compliance review.
    PolicyReview,
    /// Media — brand compliance sign-off.
    BrandCompliance,
    /// Media — localized content review.
    ContentLocalization,
    /// Media — publishing quality-assurance gate.
    PublishingQa,
    /// Media — rights/licensing clearance.
    RightsClearance,
    /// Media — social post review before publish.
    SocialPost,
    /// Anything else.
    General,
}

/// How a stage reaches a decision from its approvers' votes.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum StageRule {
    /// Every eligible approver must approve.
    AllOf,
    /// A single approval advances the stage.
    AnyOf,
    /// At least `quorum` approvals are required (set on the stage).
    Quorum,
}

/// Lifecycle of the whole request.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum RequestStatus {
    /// Created but not yet routed for approval.
    Draft,
    /// Actively moving through stages.
    InReview,
    /// A stage returned changes; awaiting resubmission.
    ChangesRequested,
    /// All stages approved.
    Approved,
    /// Rejected at some stage.
    Rejected,
    /// Withdrawn by the requester.
    Cancelled,
    /// Passed its expiry without resolution.
    Expired,
}

/// A single approver's decision on a stage.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum Decision {
    Approve,
    Reject,
    RequestChanges,
    Abstain,
}

/// Resolved state of a stage.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum StageStatus {
    /// Not yet reached.
    Pending,
    /// Currently collecting decisions.
    Active,
    /// Met its rule — approved.
    Approved,
    /// Rejected.
    Rejected,
    /// Changes requested at this stage.
    ChangesRequested,
    /// Skipped (e.g. conditional stage not needed).
    Skipped,
}

/// Definition of one stage in a workflow template.
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct StageDef {
    pub name: String,
    pub rule: StageRule,
    /// Required approvals when `rule = quorum`.
    #[serde(default)]
    pub quorum: u32,
    /// Eligible approver ids/roles for this stage.
    pub approvers: Vec<String>,
    /// Optional SLA for the stage in hours (informational; escalation hint).
    #[serde(default)]
    pub sla_hours: Option<i64>,
}

/// A reusable workflow template: an ordered list of stages for a request type.
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct WorkflowTemplate {
    pub id: String,
    pub name: String,
    pub domain: Domain,
    pub request_type: RequestType,
    pub stages: Vec<StageDef>,
    pub created_at: DateTime<Utc>,
}

/// A recorded vote/decision by one approver on a stage instance.
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Vote {
    pub approver: String,
    pub decision: Decision,
    pub comment: Option<String>,
    /// Set when this vote was cast on behalf of another approver (delegation).
    pub on_behalf_of: Option<String>,
    pub at: DateTime<Utc>,
}

/// A live stage within a request (instantiated from a StageDef).
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Stage {
    pub index: usize,
    pub name: String,
    pub rule: StageRule,
    pub quorum: u32,
    pub approvers: Vec<String>,
    pub status: StageStatus,
    pub votes: Vec<Vote>,
    pub sla_due: Option<DateTime<Utc>>,
    pub activated_at: Option<DateTime<Utc>>,
    pub resolved_at: Option<DateTime<Utc>>,
}

/// A free-text comment on the request thread.
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Comment {
    pub id: String,
    pub author: String,
    pub body: String,
    pub created_at: DateTime<Utc>,
}

/// An attachment/evidence reference (stored by URI, not bytes).
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Attachment {
    pub id: String,
    pub kind: String,
    pub description: String,
    pub uri: String,
    pub added_by: String,
    pub added_at: DateTime<Utc>,
}

/// A delegation of approval authority from one approver to another.
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Delegation {
    pub from: String,
    pub to: String,
    pub reason: Option<String>,
    pub created_at: DateTime<Utc>,
}

/// Immutable audit-trail entry — every mutation appends one. Essential for
/// board consents and legal sign-offs (defensible record of who did what).
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct AuditEntry {
    pub at: DateTime<Utc>,
    pub actor: String,
    pub action: String,
    pub detail: String,
}

/// Request priority/urgency.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum Priority {
    Critical,
    High,
    Medium,
    Low,
}

/// The central approval request, moving through its workflow's stages.
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ApprovalRequest {
    pub id: String,
    pub domain: Domain,
    pub request_type: RequestType,
    pub title: String,
    pub description: String,
    pub status: RequestStatus,
    pub requester: String,
    /// The subject under approval (opaque ref: contract id, asset id, post id…).
    pub subject_ref: String,
    pub workflow_id: String,
    pub workflow_name: String,
    pub stages: Vec<Stage>,
    /// Index of the currently active stage (if InReview).
    pub current_stage: Option<usize>,
    pub comments: Vec<Comment>,
    pub attachments: Vec<Attachment>,
    pub delegations: Vec<Delegation>,
    pub audit_trail: Vec<AuditEntry>,
    pub tags: Vec<String>,
    pub priority: Priority,
    pub expires_at: Option<DateTime<Utc>>,
    pub decided_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}
