//! Scheduled Background Jobs
//!
//! Cron-based jobs that run on a schedule:
//! - EventCleanupJob: Daily at 2 AM - cleans up old non-critical events
//! - IncompleteWorkReminderJob: Daily at 8 AM - emails about incomplete work
//! - NightlyAssignmentsJob: Daily at 6 PM - emails about tonight's schedule

use chrono::{DateTime, Datelike, Duration, NaiveDate, Utc, Weekday};
use serde::{Deserialize, Serialize};
use serde_json::json;
use sqlx::PgPool;
use uuid::Uuid;

use crate::models::EventType;
use crate::services::gmail::{GmailService, SendEmailRequest};

// ==================== RESULT TYPES ====================

/// Result of event cleanup job
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EventCleanupResult {
    pub deleted_count: i64,
    pub cutoff_date: DateTime<Utc>,
    pub retention_days: i64,
}

/// Result of incomplete work reminder job
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IncompleteWorkReminderResult {
    pub team_members_notified: i32,
    pub services_count: i32,
    pub projects_count: i32,
    pub emails_sent: i32,
    pub errors: Vec<String>,
}

/// Result of nightly assignments job
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NightlyAssignmentsResult {
    pub team_members_notified: i32,
    pub services_count: i32,
    pub projects_count: i32,
    pub emails_sent: i32,
    pub errors: Vec<String>,
}

// ==================== MISSION CRITICAL EVENTS ====================

/// Event types that should never be deleted (audit trail)
const MISSION_CRITICAL_EVENTS: &[EventType] = &[
    // Session events
    EventType::ServiceSessionStarted,
    EventType::ServiceSessionEnded,
    EventType::ServiceSessionReverted,
    EventType::ProjectSessionStarted,
    EventType::ProjectSessionEnded,
    EventType::ProjectSessionReverted,
    // Task completions
    EventType::ServiceTaskCompleted,
    EventType::ServiceTaskUncompleted,
    EventType::ProjectTaskCompleted,
    EventType::ProjectTaskUncompleted,
    // Invoice events
    EventType::InvoiceCreated,
    EventType::InvoiceStatusChanged,
    EventType::InvoiceSent,
    EventType::InvoicePaid,
    EventType::InvoiceOverdue,
    EventType::InvoiceDeleted,
    // Report events
    EventType::ReportCreated,
    EventType::ReportSubmitted,
    EventType::ReportApproved,
    // Profile access events
    EventType::CustomerProfileAccessGranted,
    EventType::CustomerProfileAccessRevoked,
    EventType::TeamProfileCreated,
    EventType::TeamProfileDeleted,
    EventType::TeamProfileRoleChanged,
    // Financial events
    EventType::LaborCreated,
    EventType::LaborDeleted,
    EventType::LaborRateChanged,
    EventType::RevenueCreated,
    EventType::RevenueDeleted,
    EventType::RevenueAmountChanged,
    // Status changes for key entities
    EventType::ServiceStatusChanged,
    EventType::ProjectStatusChanged,
    EventType::CustomerStatusChanged,
    EventType::AccountStatusChanged,
];

// ==================== EVENT CLEANUP JOB ====================

/// Job to clean up old non-critical events
pub struct EventCleanupJob;

impl EventCleanupJob {
    /// Default retention period in days
    const RETENTION_DAYS: i64 = 90;

    /// Execute the cleanup job
    pub async fn execute(pool: &PgPool) -> anyhow::Result<EventCleanupResult> {
        let retention_days = Self::RETENTION_DAYS;
        let cutoff_date = Utc::now() - Duration::days(retention_days);

        tracing::info!(
            cutoff_date = %cutoff_date,
            retention_days = retention_days,
            "Starting event cleanup job"
        );

        // Build the list of event types to preserve
        let preserved_types: Vec<String> = MISSION_CRITICAL_EVENTS
            .iter()
            .map(|et| format!("{:?}", et).to_uppercase())
            .collect();

        // Delete old non-critical events
        let result = sqlx::query_scalar::<_, i64>(
            r#"
            WITH deleted AS (
                DELETE FROM events
                WHERE created_at < $1
                  AND event_type::text NOT IN (SELECT unnest($2::text[]))
                RETURNING id
            )
            SELECT COUNT(*) FROM deleted
            "#,
        )
        .bind(cutoff_date)
        .bind(&preserved_types)
        .fetch_one(pool)
        .await?;

        let deleted_count = result;

        tracing::info!(
            deleted_count = deleted_count,
            cutoff_date = %cutoff_date,
            "Event cleanup completed"
        );

        Ok(EventCleanupResult {
            deleted_count,
            cutoff_date,
            retention_days,
        })
    }
}

// ==================== INCOMPLETE WORK REMINDER JOB ====================

/// Team member with incomplete work
#[derive(Debug, Clone, sqlx::FromRow)]
struct TeamMemberWork {
    team_profile_id: Uuid,
    email: String,
    full_name: Option<String>,
}

/// Incomplete service info
#[derive(Debug, Clone, sqlx::FromRow)]
#[allow(dead_code)]
struct IncompleteService {
    id: Uuid,
    date: NaiveDate,
    status: String,
    account_name: Option<String>,
    address_line: Option<String>,
    notes: Option<String>,
    team_profile_id: Uuid,
}

/// Incomplete project info
#[derive(Debug, Clone, sqlx::FromRow)]
#[allow(dead_code)]
struct IncompleteProject {
    id: Uuid,
    name: String,
    date: Option<NaiveDate>,
    status: String,
    customer_name: Option<String>,
    address_line: Option<String>,
    team_profile_id: Uuid,
}

/// Job to send reminders about incomplete work
pub struct IncompleteWorkReminderJob;

impl IncompleteWorkReminderJob {
    /// Execute the reminder job
    pub async fn execute(
        pool: &PgPool,
        gmail_service: Option<&GmailService>,
    ) -> anyhow::Result<IncompleteWorkReminderResult> {
        let today = Utc::now().date_naive();
        let query_date = Self::get_query_date(today);

        tracing::info!(
            query_date = %query_date,
            today = %today,
            "Starting incomplete work reminder job"
        );

        let mut result = IncompleteWorkReminderResult {
            team_members_notified: 0,
            services_count: 0,
            projects_count: 0,
            emails_sent: 0,
            errors: Vec::new(),
        };

        // Query incomplete services
        let services: Vec<IncompleteService> = sqlx::query_as(
            r#"
            SELECT
                s.id,
                s.date,
                s.status::text as status,
                a.name as account_name,
                CONCAT_WS(', ',
                    COALESCE(NULLIF(aa.name, ''), 'Primary Service Address'),
                    aa.street_address,
                    aa.city,
                    aa.state
                ) as address_line,
                s.notes,
                stm.team_profile_id
            FROM services s
            JOIN service_team_members stm ON s.id = stm.service_id
            JOIN team_profiles tp ON stm.team_profile_id = tp.id
            LEFT JOIN accounts a ON s.account_id = a.id
            LEFT JOIN account_addresses aa ON s.account_address_id = aa.id
            WHERE s.date = $1
              AND s.status IN ('SCHEDULED', 'IN_PROGRESS')
              AND tp.role != 'ADMIN'
              AND tp.status = 'ACTIVE'
            ORDER BY stm.team_profile_id, s.date
            "#,
        )
        .bind(query_date)
        .fetch_all(pool)
        .await?;

        // Query incomplete projects
        let projects: Vec<IncompleteProject> = sqlx::query_as(
            r#"
            SELECT
                p.id,
                p.name,
                p.date,
                p.status::text as status,
                c.name as customer_name,
                CONCAT_WS(', ',
                    COALESCE(NULLIF(aa.name, ''), 'Primary Service Address'),
                    aa.street_address,
                    aa.city,
                    aa.state
                ) as address_line,
                ptm.team_profile_id
            FROM projects p
            JOIN project_team_members ptm ON p.id = ptm.project_id
            JOIN team_profiles tp ON ptm.team_profile_id = tp.id
            LEFT JOIN customers c ON p.customer_id = c.id
            LEFT JOIN account_addresses aa ON p.account_address_id = aa.id
            WHERE p.date = $1
              AND p.status IN ('SCHEDULED', 'IN_PROGRESS')
              AND tp.role != 'ADMIN'
              AND tp.status = 'ACTIVE'
            ORDER BY ptm.team_profile_id, p.date
            "#,
        )
        .bind(query_date)
        .fetch_all(pool)
        .await?;

        result.services_count = services.len() as i32;
        result.projects_count = projects.len() as i32;

        if services.is_empty() && projects.is_empty() {
            tracing::info!("No incomplete work found, skipping email notifications");
            return Ok(result);
        }

        // Get unique team members
        let team_member_ids: Vec<Uuid> = {
            let mut ids: Vec<Uuid> = services.iter().map(|s| s.team_profile_id).collect();
            ids.extend(projects.iter().map(|p| p.team_profile_id));
            ids.sort();
            ids.dedup();
            ids
        };

        // Fetch team member details
        let team_members: Vec<TeamMemberWork> = sqlx::query_as(
            r#"
            SELECT id as team_profile_id, email,
                   CONCAT(first_name, ' ', last_name) as full_name
            FROM team_profiles
            WHERE id = ANY($1)
            "#,
        )
        .bind(&team_member_ids)
        .fetch_all(pool)
        .await?;

        result.team_members_notified = team_members.len() as i32;

        // Send emails
        let Some(gmail) = gmail_service else {
            tracing::warn!("Gmail service not available, skipping email notifications");
            result.errors.push("Gmail service not available".to_string());
            return Ok(result);
        };

        for member in team_members {
            let member_services: Vec<&IncompleteService> = services
                .iter()
                .filter(|s| s.team_profile_id == member.team_profile_id)
                .collect();
            let member_projects: Vec<&IncompleteProject> = projects
                .iter()
                .filter(|p| p.team_profile_id == member.team_profile_id)
                .collect();

            if member_services.is_empty() && member_projects.is_empty() {
                continue;
            }

            let recipient_name = member
                .full_name
                .as_deref()
                .and_then(|n| n.split_whitespace().next())
                .unwrap_or("Team Member");

            // Check for weekend services (notes contain "Weekend service window")
            let has_weekend_services = member_services
                .iter()
                .any(|s| s.notes.as_ref().map_or(false, |n| n.contains("Weekend")));

            let html = Self::render_email(
                recipient_name,
                &member.email,
                &query_date,
                &member_services,
                &member_projects,
                has_weekend_services,
            );

            let date_str = query_date.format("%B %d, %Y").to_string();
            match gmail
                .send_email(SendEmailRequest {
                    to: vec![member.email.clone()],
                    cc: None,
                    bcc: None,
                    subject: format!("Incomplete Work Reminder - {}", date_str),
                    body: html,
                    content_type: Some("text/html".to_string()),
                    from_name: Some("Nexus".to_string()),
                    attachments: None,
                })
                .await
            {
                Ok(_) => {
                    result.emails_sent += 1;
                    tracing::info!(
                        email = %member.email,
                        services = member_services.len(),
                        projects = member_projects.len(),
                        "Sent incomplete work reminder"
                    );
                }
                Err(e) => {
                    let error = format!("Failed to send to {}: {}", member.email, e);
                    tracing::error!("{}", error);
                    result.errors.push(error);
                }
            }
        }

        // Publish audit event
        Self::publish_audit_event(pool, &result).await?;

        tracing::info!(
            emails_sent = result.emails_sent,
            errors = result.errors.len(),
            "Incomplete work reminder job completed"
        );

        Ok(result)
    }

    /// Get the date to query for incomplete work
    /// - Monday: Query Friday (to catch weekend services)
    /// - Saturday: Skip (don't remind on Saturday)
    /// - Other days: Query yesterday
    fn get_query_date(today: NaiveDate) -> NaiveDate {
        match today.weekday() {
            Weekday::Mon => today - Duration::days(3), // Friday
            Weekday::Sat => today - Duration::days(1), // Friday (but we typically skip Saturday runs)
            _ => today - Duration::days(1),            // Yesterday
        }
    }

    fn render_email(
        recipient_name: &str,
        recipient_email: &str,
        query_date: &NaiveDate,
        services: &[&IncompleteService],
        projects: &[&IncompleteProject],
        has_weekend_services: bool,
    ) -> String {
        let date_str = query_date.format("%B %d, %Y").to_string();
        let current_year = Utc::now().year();

        // Build services HTML
        let services_html = if services.is_empty() {
            String::new()
        } else {
            let items: String = services
                .iter()
                .enumerate()
                .map(|(i, s)| {
                    let account_name = s.account_name.as_deref().unwrap_or("Unknown");
                    let address = s.address_line.as_deref().unwrap_or("");
                    let is_weekend = s.notes.as_ref().map_or(false, |n| n.contains("Weekend"));
                    let weekend_badge = if is_weekend {
                        r#"<span style="background-color: #7c3aed20; color: #7c3aed; font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 3px; margin-left: 8px;">WEEKEND</span>"#
                    } else {
                        ""
                    };
                    let (status_bg, status_color, status_label) = if s.status == "IN_PROGRESS" {
                        ("#d8a01d20", "#d8a01d", "In Progress")
                    } else {
                        ("#3b78c420", "#3b78c4", "Scheduled")
                    };
                    let border = if i < services.len() - 1 { " border-bottom: 1px solid #e2e8f0;" } else { "" };
                    format!(
                        r#"<tr>
                            <td style="padding: 14px 16px;{border}">
                                <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                        <td>
                                            <span style="color: #0f172a; font-size: 14px; font-weight: 500;">{account_name}</span>
                                            {weekend_badge}
                                        </td>
                                        <td align="right">
                                            <span style="background-color: {status_bg}; color: {status_color}; font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 4px; text-transform: uppercase;">{status_label}</span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td colspan="2" style="padding-top: 4px;">
                                            <span style="color: #64748b; font-size: 13px;">{address}</span>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>"#
                    )
                })
                .collect();

            format!(
                r#"<tr>
                    <td style="padding: 24px 32px 0 32px;">
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                            <tr>
                                <td style="padding-bottom: 12px;">
                                    <span style="color: #458c5e; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Services ({count})</span>
                                </td>
                            </tr>
                        </table>
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;">
                            {items}
                        </table>
                    </td>
                </tr>"#,
                count = services.len(),
                items = items
            )
        };

        // Build projects HTML
        let projects_html = if projects.is_empty() {
            String::new()
        } else {
            let items: String = projects
                .iter()
                .enumerate()
                .map(|(i, p)| {
                    let customer = p.customer_name.as_deref().unwrap_or("Unknown");
                    let address = p.address_line.as_deref().unwrap_or("");
                    let address_part = if !address.is_empty() {
                        format!(" &bull; {}", address)
                    } else {
                        String::new()
                    };
                    let (status_bg, status_color, status_label) = if p.status == "IN_PROGRESS" {
                        ("#d8a01d20", "#d8a01d", "In Progress")
                    } else {
                        ("#3b78c420", "#3b78c4", "Scheduled")
                    };
                    let border = if i < projects.len() - 1 { " border-bottom: 1px solid #e2e8f0;" } else { "" };
                    format!(
                        r#"<tr>
                            <td style="padding: 14px 16px;{border}">
                                <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                        <td>
                                            <span style="color: #0f172a; font-size: 14px; font-weight: 500;">{name}</span>
                                        </td>
                                        <td align="right">
                                            <span style="background-color: {status_bg}; color: {status_color}; font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 4px; text-transform: uppercase;">{status_label}</span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td colspan="2" style="padding-top: 4px;">
                                            <span style="color: #64748b; font-size: 13px;">{customer}{address_part}</span>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>"#,
                        name = p.name,
                        customer = customer,
                        address_part = address_part,
                        border = border,
                        status_bg = status_bg,
                        status_color = status_color,
                        status_label = status_label
                    )
                })
                .collect();

            format!(
                r#"<tr>
                    <td style="padding: 24px 32px 0 32px;">
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                            <tr>
                                <td style="padding-bottom: 12px;">
                                    <span style="color: #e16a36; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Projects ({count})</span>
                                </td>
                            </tr>
                        </table>
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;">
                            {items}
                        </table>
                    </td>
                </tr>"#,
                count = projects.len(),
                items = items
            )
        };

        let body_text = if has_weekend_services {
            "The following work items are still incomplete and may need your attention. This includes weekend services from Friday that were not completed.".to_string()
        } else {
            format!(
                "The following work items from <strong>{}</strong> are still incomplete and may need your attention.",
                date_str
            )
        };

        format!(
            r##"<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Incomplete Work Reminder - {date_str}</title>
    <!--[if mso]>
    <noscript>
        <xml>
            <o:OfficeDocumentSettings>
                <o:PixelsPerInch>96</o:PixelsPerInch>
            </o:OfficeDocumentSettings>
        </xml>
    </noscript>
    <![endif]-->
</head>
<body style="margin: 0; padding: 0; background-color: #f8fafc; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc;">
    <tr>
        <td align="center" style="padding: 40px 20px;">
            <table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width: 600px; width: 100%;">
                <!-- Header with Logo -->
                <tr>
                    <td align="center" style="padding: 0 0 30px 0;">
                        <table role="presentation" cellpadding="0" cellspacing="0">
                            <tr>
                                <td style="background-color: #0f172a; padding: 16px 32px; border-radius: 8px;">
                                    <table role="presentation" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td style="vertical-align: middle; padding-right: 12px;">
                                                <img src="https://api.example.com/static/images/logo-white.png" alt="" width="32" height="32" style="display: block;">
                                            </td>
                                            <td style="vertical-align: middle;">
                                                <span style="color: #ffffff; font-size: 24px; font-weight: 700; letter-spacing: -0.5px;">Nexus</span>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>

                <!-- Content Card -->
                <tr>
                    <td>
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);">
                            <!-- Event Type Badge -->
                            <tr>
                                <td style="padding: 24px 32px 0 32px;">
                                    <table role="presentation" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td style="background-color: #d8a01d20; padding: 6px 12px; border-radius: 4px;">
                                                <span style="color: #d8a01d; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Action Required</span>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>

                            <!-- Title -->
                            <tr>
                                <td style="padding: 16px 32px 0 32px;">
                                    <h1 style="margin: 0; color: #0f172a; font-size: 22px; font-weight: 600; line-height: 1.4;">Incomplete Work Reminder</h1>
                                </td>
                            </tr>

                            <!-- Greeting -->
                            <tr>
                                <td style="padding: 16px 32px 0 32px;">
                                    <p style="margin: 0; color: #475569; font-size: 15px; line-height: 1.6;">Hi {recipient_name},</p>
                                </td>
                            </tr>

                            <!-- Body Content -->
                            <tr>
                                <td style="padding: 12px 32px 0 32px;">
                                    <p style="margin: 0; color: #334155; font-size: 15px; line-height: 1.7;">{body_text}</p>
                                </td>
                            </tr>

                            <!-- Services Section -->
                            {services_html}

                            <!-- Projects Section -->
                            {projects_html}

                            <!-- Call to Action -->
                            <tr>
                                <td style="padding: 24px 32px 0 32px;">
                                    <p style="margin: 0; color: #475569; font-size: 14px; line-height: 1.6;">Please visit your dashboard to update the status of these items or contact your team lead if assistance is needed.</p>
                                </td>
                            </tr>

                            <!-- Action Button -->
                            <tr>
                                <td align="center" style="padding: 32px 32px;">
                                    <table role="presentation" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td style="background-color: #3b78c4; border-radius: 8px;">
                                                <a href="https://app.example.com/team" style="display: inline-block; padding: 14px 28px; color: #ffffff; text-decoration: none; font-size: 15px; font-weight: 600;">Open Dashboard</a>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>

                <!-- Footer -->
                <tr>
                    <td style="padding: 32px 0 0 0;">
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                            <tr>
                                <td align="center" style="padding: 0 0 16px 0;">
                                    <p style="margin: 0; color: #94a3b8; font-size: 13px;">
                                        <a href="https://app.example.com" style="color: #3b78c4; text-decoration: none;">Visit Nexus</a>
                                        &nbsp;&bull;&nbsp;
                                        <a href="https://app.example.com/contact" style="color: #3b78c4; text-decoration: none;">Contact Us</a>
                                    </p>
                                </td>
                            </tr>
                            <tr>
                                <td align="center">
                                    <p style="margin: 0; color: #94a3b8; font-size: 12px;">&copy; {current_year} Your Company. All rights reserved.</p>
                                </td>
                            </tr>
                            <tr>
                                <td align="center" style="padding: 16px 0 0 0;">
                                    <p style="margin: 0; color: #cbd5e1; font-size: 11px;">
                                        This is an automated daily reminder sent to {recipient_email}.<br>
                                        You received this because you have incomplete work items assigned to you.
                                    </p>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>
</body>
</html>"##,
            date_str = date_str,
            recipient_name = recipient_name,
            recipient_email = recipient_email,
            body_text = body_text,
            services_html = services_html,
            projects_html = projects_html,
            current_year = current_year
        )
    }

    async fn publish_audit_event(
        pool: &PgPool,
        result: &IncompleteWorkReminderResult,
    ) -> anyhow::Result<()> {
        let event_id = Uuid::new_v4();
        let now = Utc::now();

        sqlx::query(
            r#"
            INSERT INTO events (id, event_type, entity_type, entity_id, actor_type, metadata, timestamp, created_at)
            VALUES ($1, 'MONITORING_TASK_RUN', 'system', $1, 'system', $2, $3, $3)
            "#,
        )
        .bind(event_id)
        .bind(json!({
            "job": "incomplete_work_reminder",
            "team_members_notified": result.team_members_notified,
            "services_count": result.services_count,
            "projects_count": result.projects_count,
            "emails_sent": result.emails_sent,
            "errors": result.errors,
        }))
        .bind(now)
        .execute(pool)
        .await?;

        Ok(())
    }
}

// ==================== NIGHTLY ASSIGNMENTS JOB ====================

/// Scheduled service info
#[derive(Debug, Clone, sqlx::FromRow)]
#[allow(dead_code)]
struct ScheduledService {
    id: Uuid,
    date: NaiveDate,
    account_name: Option<String>,
    address_line: Option<String>,
    notes: Option<String>,
    team_profile_id: Uuid,
}

/// Scheduled project info
#[derive(Debug, Clone, sqlx::FromRow)]
#[allow(dead_code)]
struct ScheduledProject {
    id: Uuid,
    name: String,
    date: Option<NaiveDate>,
    customer_name: Option<String>,
    address_line: Option<String>,
    team_profile_id: Uuid,
}

/// Job to send nightly assignment notifications
pub struct NightlyAssignmentsJob;

impl NightlyAssignmentsJob {
    /// Execute the assignments job
    pub async fn execute(
        pool: &PgPool,
        gmail_service: Option<&GmailService>,
    ) -> anyhow::Result<NightlyAssignmentsResult> {
        let today = Utc::now().date_naive();

        tracing::info!(
            date = %today,
            "Starting nightly assignments job"
        );

        let mut result = NightlyAssignmentsResult {
            team_members_notified: 0,
            services_count: 0,
            projects_count: 0,
            emails_sent: 0,
            errors: Vec::new(),
        };

        // Query scheduled services for today
        let services: Vec<ScheduledService> = sqlx::query_as(
            r#"
            SELECT
                s.id,
                s.date,
                a.name as account_name,
                CONCAT_WS(', ',
                    COALESCE(NULLIF(aa.name, ''), 'Primary Service Address'),
                    aa.street_address,
                    aa.city,
                    aa.state
                ) as address_line,
                s.notes,
                stm.team_profile_id
            FROM services s
            JOIN service_team_members stm ON s.id = stm.service_id
            JOIN team_profiles tp ON stm.team_profile_id = tp.id
            LEFT JOIN accounts a ON s.account_id = a.id
            LEFT JOIN account_addresses aa ON s.account_address_id = aa.id
            WHERE s.date = $1
              AND s.status = 'SCHEDULED'
              AND tp.role != 'ADMIN'
              AND tp.status = 'ACTIVE'
            ORDER BY stm.team_profile_id, s.date
            "#,
        )
        .bind(today)
        .fetch_all(pool)
        .await?;

        // Query scheduled projects for today
        let projects: Vec<ScheduledProject> = sqlx::query_as(
            r#"
            SELECT
                p.id,
                p.name,
                p.date,
                c.name as customer_name,
                CONCAT_WS(', ',
                    COALESCE(NULLIF(aa.name, ''), 'Primary Service Address'),
                    aa.street_address,
                    aa.city,
                    aa.state
                ) as address_line,
                ptm.team_profile_id
            FROM projects p
            JOIN project_team_members ptm ON p.id = ptm.project_id
            JOIN team_profiles tp ON ptm.team_profile_id = tp.id
            LEFT JOIN customers c ON p.customer_id = c.id
            LEFT JOIN account_addresses aa ON p.account_address_id = aa.id
            WHERE p.date = $1
              AND p.status = 'SCHEDULED'
              AND tp.role != 'ADMIN'
              AND tp.status = 'ACTIVE'
            ORDER BY ptm.team_profile_id, p.date
            "#,
        )
        .bind(today)
        .fetch_all(pool)
        .await?;

        result.services_count = services.len() as i32;
        result.projects_count = projects.len() as i32;

        if services.is_empty() && projects.is_empty() {
            tracing::info!("No scheduled work found, skipping email notifications");
            return Ok(result);
        }

        // Get unique team members
        let team_member_ids: Vec<Uuid> = {
            let mut ids: Vec<Uuid> = services.iter().map(|s| s.team_profile_id).collect();
            ids.extend(projects.iter().map(|p| p.team_profile_id));
            ids.sort();
            ids.dedup();
            ids
        };

        // Fetch team member details
        let team_members: Vec<TeamMemberWork> = sqlx::query_as(
            r#"
            SELECT id as team_profile_id, email,
                   CONCAT(first_name, ' ', last_name) as full_name
            FROM team_profiles
            WHERE id = ANY($1)
            "#,
        )
        .bind(&team_member_ids)
        .fetch_all(pool)
        .await?;

        result.team_members_notified = team_members.len() as i32;

        // Send emails
        let Some(gmail) = gmail_service else {
            tracing::warn!("Gmail service not available, skipping email notifications");
            result.errors.push("Gmail service not available".to_string());
            return Ok(result);
        };

        for member in team_members {
            let member_services: Vec<&ScheduledService> = services
                .iter()
                .filter(|s| s.team_profile_id == member.team_profile_id)
                .collect();
            let member_projects: Vec<&ScheduledProject> = projects
                .iter()
                .filter(|p| p.team_profile_id == member.team_profile_id)
                .collect();

            if member_services.is_empty() && member_projects.is_empty() {
                continue;
            }

            let recipient_name = member
                .full_name
                .as_deref()
                .and_then(|n| n.split_whitespace().next())
                .unwrap_or("Team Member");

            // Check for weekend services (notes contain "Weekend service window")
            let has_weekend_services = member_services
                .iter()
                .any(|s| s.notes.as_ref().map_or(false, |n| n.contains("Weekend")));

            let html = Self::render_email(
                recipient_name,
                &member.email,
                &today,
                &member_services,
                &member_projects,
                has_weekend_services,
            );

            let date_str = today.format("%B %d, %Y").to_string();
            match gmail
                .send_email(SendEmailRequest {
                    to: vec![member.email.clone()],
                    cc: None,
                    bcc: None,
                    subject: format!("Tonight's Assignments - {}", date_str),
                    body: html,
                    content_type: Some("text/html".to_string()),
                    from_name: Some("Nexus".to_string()),
                    attachments: None,
                })
                .await
            {
                Ok(_) => {
                    result.emails_sent += 1;
                    tracing::info!(
                        email = %member.email,
                        services = member_services.len(),
                        projects = member_projects.len(),
                        "Sent nightly assignments"
                    );
                }
                Err(e) => {
                    let error = format!("Failed to send to {}: {}", member.email, e);
                    tracing::error!("{}", error);
                    result.errors.push(error);
                }
            }
        }

        // Publish audit event
        Self::publish_audit_event(pool, &result).await?;

        tracing::info!(
            emails_sent = result.emails_sent,
            errors = result.errors.len(),
            "Nightly assignments job completed"
        );

        Ok(result)
    }

    fn render_email(
        recipient_name: &str,
        recipient_email: &str,
        date: &NaiveDate,
        services: &[&ScheduledService],
        projects: &[&ScheduledProject],
        has_weekend_services: bool,
    ) -> String {
        let date_str = date.format("%B %d, %Y").to_string();
        let current_year = Utc::now().year();

        // Build services HTML
        let services_html = if services.is_empty() {
            String::new()
        } else {
            let items: String = services
                .iter()
                .enumerate()
                .map(|(i, s)| {
                    let account_name = s.account_name.as_deref().unwrap_or("Unknown");
                    let address = s.address_line.as_deref().unwrap_or("");
                    let is_weekend = s.notes.as_ref().map_or(false, |n| n.contains("Weekend"));
                    let weekend_badge = if is_weekend {
                        r#"<span style="background-color: #7c3aed20; color: #7c3aed; font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 3px; margin-left: 8px;">WEEKEND</span>"#
                    } else {
                        ""
                    };
                    let border = if i < services.len() - 1 { " border-bottom: 1px solid #e2e8f0;" } else { "" };
                    format!(
                        r#"<tr>
                            <td style="padding: 14px 16px;{border}">
                                <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                        <td>
                                            <span style="color: #0f172a; font-size: 14px; font-weight: 500;">{account_name}</span>
                                            {weekend_badge}
                                        </td>
                                    </tr>
                                    <tr>
                                        <td style="padding-top: 4px;">
                                            <span style="color: #64748b; font-size: 13px;">{address}</span>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>"#
                    )
                })
                .collect();

            format!(
                r#"<tr>
                    <td style="padding: 24px 32px 0 32px;">
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                            <tr>
                                <td style="padding-bottom: 12px;">
                                    <span style="color: #458c5e; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Services ({count})</span>
                                </td>
                            </tr>
                        </table>
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;">
                            {items}
                        </table>
                    </td>
                </tr>"#,
                count = services.len(),
                items = items
            )
        };

        // Build projects HTML
        let projects_html = if projects.is_empty() {
            String::new()
        } else {
            let items: String = projects
                .iter()
                .enumerate()
                .map(|(i, p)| {
                    let customer = p.customer_name.as_deref().unwrap_or("Unknown");
                    let address = p.address_line.as_deref().unwrap_or("");
                    let address_part = if !address.is_empty() {
                        format!(" &bull; {}", address)
                    } else {
                        String::new()
                    };
                    let border = if i < projects.len() - 1 { " border-bottom: 1px solid #e2e8f0;" } else { "" };
                    format!(
                        r#"<tr>
                            <td style="padding: 14px 16px;{border}">
                                <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                        <td>
                                            <span style="color: #0f172a; font-size: 14px; font-weight: 500;">{name}</span>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td style="padding-top: 4px;">
                                            <span style="color: #64748b; font-size: 13px;">{customer}{address_part}</span>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>"#,
                        name = p.name,
                        customer = customer,
                        address_part = address_part,
                        border = border
                    )
                })
                .collect();

            format!(
                r#"<tr>
                    <td style="padding: 24px 32px 0 32px;">
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                            <tr>
                                <td style="padding-bottom: 12px;">
                                    <span style="color: #e16a36; font-size: 14px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Projects ({count})</span>
                                </td>
                            </tr>
                        </table>
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;">
                            {items}
                        </table>
                    </td>
                </tr>"#,
                count = projects.len(),
                items = items
            )
        };

        let body_text = if has_weekend_services {
            format!(
                "Here's your scheduled work for <strong>{}</strong>, including weekend services that can be completed through Sunday.",
                date_str
            )
        } else {
            format!("Here's your scheduled work for <strong>{}</strong>.", date_str)
        };

        let deadline_text = if has_weekend_services {
            "Regular services are due by 8:00am tomorrow morning. Weekend services are due by Monday morning."
        } else {
            "All of your completed work is due by 8:00am tomorrow morning."
        };

        format!(
            r##"<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Tonight's Assignments - {date_str}</title>
    <!--[if mso]>
    <noscript>
        <xml>
            <o:OfficeDocumentSettings>
                <o:PixelsPerInch>96</o:PixelsPerInch>
            </o:OfficeDocumentSettings>
        </xml>
    </noscript>
    <![endif]-->
</head>
<body style="margin: 0; padding: 0; background-color: #f8fafc; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc;">
    <tr>
        <td align="center" style="padding: 40px 20px;">
            <table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width: 600px; width: 100%;">
                <!-- Header with Logo -->
                <tr>
                    <td align="center" style="padding: 0 0 30px 0;">
                        <table role="presentation" cellpadding="0" cellspacing="0">
                            <tr>
                                <td style="background-color: #0f172a; padding: 16px 32px; border-radius: 8px;">
                                    <table role="presentation" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td style="vertical-align: middle; padding-right: 12px;">
                                                <img src="https://api.example.com/static/images/logo-white.png" alt="" width="32" height="32" style="display: block;">
                                            </td>
                                            <td style="vertical-align: middle;">
                                                <span style="color: #ffffff; font-size: 24px; font-weight: 700; letter-spacing: -0.5px;">Nexus</span>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>

                <!-- Content Card -->
                <tr>
                    <td>
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);">
                            <!-- Event Type Badge -->
                            <tr>
                                <td style="padding: 24px 32px 0 32px;">
                                    <table role="presentation" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td style="background-color: #3b78c420; padding: 6px 12px; border-radius: 4px;">
                                                <span style="color: #3b78c4; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Tonight's Schedule</span>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>

                            <!-- Title -->
                            <tr>
                                <td style="padding: 16px 32px 0 32px;">
                                    <h1 style="margin: 0; color: #0f172a; font-size: 22px; font-weight: 600; line-height: 1.4;">Your Assignments for Tonight</h1>
                                </td>
                            </tr>

                            <!-- Greeting -->
                            <tr>
                                <td style="padding: 16px 32px 0 32px;">
                                    <p style="margin: 0; color: #475569; font-size: 15px; line-height: 1.6;">Hi {recipient_name},</p>
                                </td>
                            </tr>

                            <!-- Body Content -->
                            <tr>
                                <td style="padding: 12px 32px 0 32px;">
                                    <p style="margin: 0; color: #334155; font-size: 15px; line-height: 1.7;">{body_text}</p>
                                </td>
                            </tr>

                            <!-- Services Section -->
                            {services_html}

                            <!-- Projects Section -->
                            {projects_html}

                            <!-- Deadline Text -->
                            <tr>
                                <td style="padding: 24px 32px 0 32px;">
                                    <p style="margin: 0; color: #475569; font-size: 14px; line-height: 1.6;">{deadline_text}</p>
                                    <p style="margin: 8px 0 0 0; color: #475569; font-size: 14px; line-height: 1.6;">Please visit your dashboard to get started.</p>
                                </td>
                            </tr>

                            <!-- Action Button -->
                            <tr>
                                <td align="center" style="padding: 32px 32px;">
                                    <table role="presentation" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td style="background-color: #3b78c4; border-radius: 8px;">
                                                <a href="https://app.example.com/team" style="display: inline-block; padding: 14px 28px; color: #ffffff; text-decoration: none; font-size: 15px; font-weight: 600;">View Dashboard</a>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>

                <!-- Footer -->
                <tr>
                    <td style="padding: 32px 0 0 0;">
                        <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
                            <tr>
                                <td align="center" style="padding: 0 0 16px 0;">
                                    <p style="margin: 0; color: #94a3b8; font-size: 13px;">
                                        <a href="https://app.example.com" style="color: #3b78c4; text-decoration: none;">Visit Nexus</a>
                                        &nbsp;&bull;&nbsp;
                                        <a href="https://app.example.com/contact" style="color: #3b78c4; text-decoration: none;">Contact Us</a>
                                    </p>
                                </td>
                            </tr>
                            <tr>
                                <td align="center">
                                    <p style="margin: 0; color: #94a3b8; font-size: 12px;">&copy; {current_year} Your Company. All rights reserved.</p>
                                </td>
                            </tr>
                            <tr>
                                <td align="center" style="padding: 16px 0 0 0;">
                                    <p style="margin: 0; color: #cbd5e1; font-size: 11px;">
                                        This is an automated notification sent to {recipient_email}.<br>
                                        You received this because you have work scheduled for tonight.
                                    </p>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>
</body>
</html>"##,
            date_str = date_str,
            recipient_name = recipient_name,
            recipient_email = recipient_email,
            body_text = body_text,
            deadline_text = deadline_text,
            services_html = services_html,
            projects_html = projects_html,
            current_year = current_year
        )
    }

    async fn publish_audit_event(
        pool: &PgPool,
        result: &NightlyAssignmentsResult,
    ) -> anyhow::Result<()> {
        let event_id = Uuid::new_v4();
        let now = Utc::now();

        sqlx::query(
            r#"
            INSERT INTO events (id, event_type, entity_type, entity_id, actor_type, metadata, timestamp, created_at)
            VALUES ($1, 'MONITORING_TASK_RUN', 'system', $1, 'system', $2, $3, $3)
            "#,
        )
        .bind(event_id)
        .bind(json!({
            "job": "nightly_assignments",
            "team_members_notified": result.team_members_notified,
            "services_count": result.services_count,
            "projects_count": result.projects_count,
            "emails_sent": result.emails_sent,
            "errors": result.errors,
        }))
        .bind(now)
        .execute(pool)
        .await?;

        Ok(())
    }
}
