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

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct User {
    pub id: Uuid,
    pub username: String,
    pub email: String,
    #[serde(skip_serializing)]
    pub password_hash: String,
    pub first_name: String,
    pub last_name: String,
    pub phone: Option<String>,
    pub is_active: bool,
    pub is_locked: bool,
    pub lock_reason: Option<String>,
    pub password_change_required: bool,
    pub email_verified_at: Option<DateTime<Utc>>,
    pub last_login_at: Option<DateTime<Utc>>,
    pub failed_login_attempts: i32,
    pub locked_until: Option<DateTime<Utc>>,
    pub preferences: Option<serde_json::Value>,
    pub created_by: Option<Uuid>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Role {
    pub id: Uuid,
    pub name: String,
    pub display_name: Option<String>,
    pub description: Option<String>,
    pub hierarchy_level: i32,
    pub is_system: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Permission {
    pub id: Uuid,
    pub resource: String,
    pub action: String,
    pub description: Option<String>,
    pub category: Option<String>,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct UserRole {
    pub user_id: Uuid,
    pub role_id: Uuid,
    pub assigned_by: Option<Uuid>,
    pub assigned_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Session {
    pub id: Uuid,
    pub user_id: Uuid,
    #[serde(skip_serializing)]
    pub token_hash: String,
    pub ip_address: Option<sqlx::types::ipnetwork::IpNetwork>,
    pub user_agent: Option<String>,
    pub is_active: bool,
    pub expires_at: DateTime<Utc>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Customer {
    pub id: Uuid,
    pub customer_type: String,
    pub status_id: Uuid,
    pub owner_id: Option<Uuid>,
    pub source: Option<String>,
    pub notes: Option<String>,
    pub tags: Option<Vec<String>>,
    pub score: i32,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct CustomerStatus {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub color: Option<String>,
    pub sort_order: i32,
    pub is_default: bool,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct IndividualCustomer {
    pub customer_id: Uuid,
    pub first_name: String,
    pub last_name: String,
    pub middle_name: Option<String>,
    pub date_of_birth: Option<chrono::NaiveDate>,
    pub gender: Option<String>,
    pub job_title: Option<String>,
    pub company_name: Option<String>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct CompanyCustomer {
    pub customer_id: Uuid,
    pub company_name: String,
    pub registration_number: Option<String>,
    pub tax_id: Option<String>,
    pub website: Option<String>,
    pub industry: Option<String>,
    pub company_size: Option<String>,
    pub annual_revenue: Option<rust_decimal::Decimal>,
    pub founded_date: Option<chrono::NaiveDate>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct ContactInformation {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub r#type: String,
    pub value: String,
    pub label: Option<String>,
    pub is_primary: bool,
    pub is_verified: bool,
    pub verified_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Address {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub address_type: String,
    pub address_line1: String,
    pub address_line2: Option<String>,
    pub city: String,
    pub state: Option<String>,
    pub postal_code: Option<String>,
    pub country: String,
    pub is_primary: bool,
    pub latitude: Option<rust_decimal::Decimal>,
    pub longitude: Option<rust_decimal::Decimal>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Lead {
    pub id: Uuid,
    pub source_id: Option<Uuid>,
    pub stage_id: Uuid,
    pub assigned_to: Option<Uuid>,
    pub company_name: Option<String>,
    pub contact_name: String,
    pub email: Option<String>,
    pub phone: Option<String>,
    pub job_title: Option<String>,
    pub budget_range: Option<String>,
    pub interest_level: Option<String>,
    pub notes: Option<String>,
    pub score: i32,
    pub converted_customer_id: Option<Uuid>,
    pub converted_at: Option<DateTime<Utc>>,
    pub converted_by: Option<Uuid>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct LeadSource {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct LeadStage {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub sort_order: i32,
    pub probability: i32,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Opportunity {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub lead_id: Option<Uuid>,
    pub stage_id: Uuid,
    pub owner_id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub estimated_revenue: Option<rust_decimal::Decimal>,
    pub probability: Option<i32>,
    pub expected_close_date: Option<chrono::NaiveDate>,
    pub actual_close_date: Option<chrono::NaiveDate>,
    pub loss_reason: Option<String>,
    pub is_won: Option<bool>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct DealStage {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub sort_order: i32,
    pub probability: i32,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Product {
    pub id: Uuid,
    pub category_id: Option<Uuid>,
    pub name: String,
    pub description: Option<String>,
    pub sku: Option<String>,
    pub unit_price: rust_decimal::Decimal,
    pub cost_price: Option<rust_decimal::Decimal>,
    pub currency: String,
    pub is_active: bool,
    pub is_service: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct ProductCategory {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub parent_id: Option<Uuid>,
    pub is_active: bool,
    pub sort_order: i32,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Communication {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub opportunity_id: Option<Uuid>,
    pub type_id: Uuid,
    pub subject: Option<String>,
    pub body: Option<String>,
    pub direction: String,
    pub created_by: Uuid,
    pub started_at: Option<DateTime<Utc>>,
    pub duration_minutes: Option<i32>,
    pub outcome: Option<String>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct CommunicationType {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub icon: Option<String>,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Task {
    pub id: Uuid,
    pub customer_id: Option<Uuid>,
    pub opportunity_id: Option<Uuid>,
    pub communication_id: Option<Uuid>,
    pub assigned_to: Option<Uuid>,
    pub assigned_by: Option<Uuid>,
    pub title: String,
    pub description: Option<String>,
    pub priority_id: Option<Uuid>,
    pub status: String,
    pub due_date: Option<DateTime<Utc>>,
    pub completed_at: Option<DateTime<Utc>>,
    pub reminder_at: Option<DateTime<Utc>>,
    pub reminder_sent: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct TaskPriority {
    pub id: Uuid,
    pub name: String,
    pub color: Option<String>,
    pub sort_order: i32,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Invoice {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub opportunity_id: Option<Uuid>,
    pub status_id: Uuid,
    pub invoice_number: String,
    pub subtotal: rust_decimal::Decimal,
    pub tax_percent: Option<rust_decimal::Decimal>,
    pub tax_amount: Option<rust_decimal::Decimal>,
    pub discount_percent: Option<rust_decimal::Decimal>,
    pub discount_amount: Option<rust_decimal::Decimal>,
    pub total_amount: rust_decimal::Decimal,
    pub currency: String,
    pub issued_date: chrono::NaiveDate,
    pub due_date: chrono::NaiveDate,
    pub paid_at: Option<DateTime<Utc>>,
    pub notes: Option<String>,
    pub created_by: Uuid,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct InvoiceStatus {
    pub id: Uuid,
    pub name: String,
    pub description: Option<String>,
    pub color: Option<String>,
    pub sort_order: i32,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct Payment {
    pub id: Uuid,
    pub invoice_id: Uuid,
    pub amount: rust_decimal::Decimal,
    pub payment_method: Option<String>,
    pub transaction_id: Option<String>,
    pub status: String,
    pub paid_at: Option<DateTime<Utc>>,
    pub notes: Option<String>,
    pub created_by: Uuid,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

#[derive(Debug, FromRow, serde::Serialize, serde::Deserialize)]
pub struct AuditLog {
    pub id: Uuid,
    pub table_name: String,
    pub record_id: Uuid,
    pub action: String,
    pub old_data: Option<serde_json::Value>,
    pub new_data: Option<serde_json::Value>,
    pub changed_by: Option<Uuid>,
    pub changed_at: DateTime<Utc>,
    pub ip_address: Option<sqlx::types::ipnetwork::IpNetwork>,
    pub user_agent: Option<String>,
    pub session_id: Option<Uuid>,
}
