use sqlx::PgPool;
use uuid::Uuid;
use anyhow::Result;
use chrono::{DateTime, Utc};
use serde::Serialize;

/// License record from the database
#[derive(Debug, Clone, sqlx::FromRow, Serialize)]
pub struct LicenseRow {
    pub id: Uuid,
    pub license_key: String,
    pub status: String,
    pub owner_user_id: Uuid,
    pub server_name: Option<String>,
    pub subdomain: Option<String>,
    pub custom_domain: Option<String>,
    pub modules_enabled: Option<Vec<String>>,
    pub webstore_active: bool,
    pub webstore_subscription_id: Option<String>,
    pub created_at: DateTime<Utc>,
    pub expires_at: Option<DateTime<Utc>>,
}

/// Create a new license.
pub async fn create_license(
    pool: &PgPool,
    license_key: &str,
    owner_user_id: Uuid,
) -> Result<Uuid> {
    let row: (Uuid,) = sqlx::query_as(
        "INSERT INTO licenses (license_key, owner_user_id) VALUES ($1, $2) RETURNING id",
    )
    .bind(license_key)
    .bind(owner_user_id)
    .fetch_one(pool)
    .await?;

    Ok(row.0)
}

/// Fetch a license by its key string.
pub async fn get_license_by_key(pool: &PgPool, key: &str) -> Result<Option<LicenseRow>> {
    let license = sqlx::query_as::<_, LicenseRow>(
        "SELECT id, license_key, status, owner_user_id, server_name, subdomain, \
         custom_domain, modules_enabled, webstore_active, webstore_subscription_id, \
         created_at, expires_at \
         FROM licenses WHERE license_key = $1",
    )
    .bind(key)
    .fetch_optional(pool)
    .await?;

    Ok(license)
}

/// Fetch a license by UUID.
pub async fn get_license_by_id(pool: &PgPool, id: Uuid) -> Result<Option<LicenseRow>> {
    let license = sqlx::query_as::<_, LicenseRow>(
        "SELECT id, license_key, status, owner_user_id, server_name, subdomain, \
         custom_domain, modules_enabled, webstore_active, webstore_subscription_id, \
         created_at, expires_at \
         FROM licenses WHERE id = $1",
    )
    .bind(id)
    .fetch_optional(pool)
    .await?;

    Ok(license)
}

/// Fetch a license by owner user ID.
pub async fn get_license_by_user(pool: &PgPool, user_id: Uuid) -> Result<Option<LicenseRow>> {
    let license = sqlx::query_as::<_, LicenseRow>(
        "SELECT id, license_key, status, owner_user_id, server_name, subdomain, \
         custom_domain, modules_enabled, webstore_active, webstore_subscription_id, \
         created_at, expires_at \
         FROM licenses WHERE owner_user_id = $1",
    )
    .bind(user_id)
    .fetch_optional(pool)
    .await?;

    Ok(license)
}

/// Activate a license (set status to 'active').
pub async fn activate_license(pool: &PgPool, license_id: Uuid) -> Result<()> {
    sqlx::query("UPDATE licenses SET status = 'active' WHERE id = $1")
        .bind(license_id)
        .execute(pool)
        .await?;
    Ok(())
}

/// Update license status.
pub async fn update_license_status(pool: &PgPool, license_id: Uuid, status: &str) -> Result<()> {
    sqlx::query("UPDATE licenses SET status = $1 WHERE id = $2")
        .bind(status)
        .bind(license_id)
        .execute(pool)
        .await?;
    Ok(())
}
