use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;

// ==================== BASE FIELD GROUPS ====================

/// Base fields shared by all models (id + timestamps)
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct BaseFields {
    pub id: Uuid,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

impl Default for BaseFields {
    fn default() -> Self {
        let now = Utc::now();
        Self {
            id: Uuid::new_v4(),
            created_at: now,
            updated_at: now,
        }
    }
}

/// Address fields (street, city, state, zip)
#[derive(Debug, Clone, Serialize, Deserialize, FromRow, Default)]
pub struct AddressFields {
    pub street_address: String,
    pub city: String,
    pub state: String,
    pub zip_code: String,
}

impl AddressFields {
    /// Format as single-line address
    pub fn format_inline(&self) -> String {
        format!(
            "{}, {}, {} {}",
            self.street_address, self.city, self.state, self.zip_code
        )
    }

    /// Format as multi-line address
    pub fn format_multiline(&self) -> String {
        format!(
            "{}\n{}, {} {}",
            self.street_address, self.city, self.state, self.zip_code
        )
    }
}

/// Contact fields (first_name, last_name, phone)
#[derive(Debug, Clone, Serialize, Deserialize, FromRow, Default)]
pub struct ContactFields {
    pub first_name: String,
    pub last_name: String,
    pub phone: Option<String>,
}

impl ContactFields {
    pub fn full_name(&self) -> String {
        format!("{} {}", self.first_name, self.last_name)
    }
}

/// Media metadata fields (dimensions, content type, uploader)
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct MediaFields {
    pub content_type: String,
    pub width: Option<i32>,
    pub height: Option<i32>,
    pub uploaded_by_id: Uuid,
    pub notes: Option<String>,
    pub internal: bool,
}

/// Note fields (content, author, internal flag)
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct NoteFields {
    pub content: String,
    pub author_id: Uuid,
    pub internal: bool,
}

/// Status for entities with lifecycle
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "entity_status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum EntityStatus {
    Active,
    Inactive,
    Pending,
}

impl Default for EntityStatus {
    fn default() -> Self {
        Self::Active
    }
}

/// Work status for services and projects
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "work_status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum WorkStatus {
    Scheduled,
    InProgress,
    Completed,
    Cancelled,
}

impl Default for WorkStatus {
    fn default() -> Self {
        Self::Scheduled
    }
}

/// Invoice status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "invoice_status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum InvoiceStatus {
    Draft,
    Sent,
    Paid,
    Overdue,
    Cancelled,
}

impl Default for InvoiceStatus {
    fn default() -> Self {
        Self::Draft
    }
}

/// Report status for payroll workflow
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "report_status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ReportStatus {
    Draft,
    Finalized,
    Paid,
}

impl Default for ReportStatus {
    fn default() -> Self {
        Self::Draft
    }
}

/// Payment type for invoices
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "payment_type", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum PaymentType {
    Check,
    CreditCard,
    BankTransfer,
    Cash,
}

/// Task frequency
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "task_frequency", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TaskFrequency {
    Daily,
    Weekly,
    Monthly,
    Quarterly,
    Triannual,
    Annual,
    AsNeeded,
}

impl Default for TaskFrequency {
    fn default() -> Self {
        Self::Daily
    }
}

/// Team member role
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "team_role", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TeamRole {
    Admin,
    TeamLeader,
    TeamMember,
}

impl Default for TeamRole {
    fn default() -> Self {
        Self::TeamMember
    }
}

/// Conversation type
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "conversation_type", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ConversationType {
    Direct,
    Group,
    Support,
}

impl Default for ConversationType {
    fn default() -> Self {
        Self::Direct
    }
}

// ==================== NOTIFICATION ENUMS ====================

/// Notification delivery channel
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "notification_channel", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum NotificationChannel {
    InApp,
    Email,
    Sms,
}

/// Notification status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "notification_status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum NotificationStatus {
    Pending,
    Sent,
    Read,
    Failed,
}

impl Default for NotificationStatus {
    fn default() -> Self {
        Self::Pending
    }
}

/// Delivery attempt status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, sqlx::Type)]
#[sqlx(type_name = "delivery_status", rename_all = "SCREAMING_SNAKE_CASE")]
pub enum DeliveryStatus {
    Pending,
    Queued,
    Sending,
    Sent,
    Delivered,
    Failed,
    Bounced,
}

impl Default for DeliveryStatus {
    fn default() -> Self {
        Self::Pending
    }
}
