use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskManifest {
    pub id: String,
    pub app_name: String,
    pub description: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub status: ManifestStatus,
    pub current_status: CurrentStatus,
    pub sections: Vec<ManifestSection>,
    pub total_steps: u32,
    pub completed_steps: u32,
    pub runtime_seconds: u64,
    pub estimated_seconds: u64,
    pub terminal_output: Vec<TerminalLine>,
    pub processing_stats: ProcessingStats,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CurrentStatus {
    pub title: String,
    pub current_action: Option<String>,
    pub decision_point: Option<DecisionPoint>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DecisionPoint {
    pub step_current: u32,
    pub step_total: u32,
    pub message: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Default)]
pub enum ManifestStatus {
    #[default]
    Planning,
    Ready,
    Running,
    Paused,
    Completed,
    Failed,
}


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestSection {
    pub id: String,
    pub name: String,
    pub section_type: SectionType,
    pub status: SectionStatus,
    pub current_step: u32,
    pub total_steps: u32,
    pub global_step_start: u32,
    pub duration_seconds: Option<u64>,
    pub started_at: Option<DateTime<Utc>>,
    pub completed_at: Option<DateTime<Utc>>,
    pub items: Vec<ManifestItem>,
    pub item_groups: Vec<ItemGroup>,
    pub children: Vec<ManifestSection>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum SectionType {
    DatabaseModels,
    SchemaDesign,
    Tables,
    Files,
    Pages,
    Tools,
    Schedulers,
    Monitors,
    Validation,
    Deployment,
}

impl std::fmt::Display for SectionType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::DatabaseModels => write!(f, "Database & Models"),
            Self::SchemaDesign => write!(f, "Database Schema Design"),
            Self::Tables => write!(f, "Tables"),
            Self::Files => write!(f, "Files"),
            Self::Pages => write!(f, "Pages"),
            Self::Tools => write!(f, "Tools"),
            Self::Schedulers => write!(f, "Schedulers"),
            Self::Monitors => write!(f, "Monitors"),
            Self::Validation => write!(f, "Validation"),
            Self::Deployment => write!(f, "Deployment"),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Default)]
pub enum SectionStatus {
    #[default]
    Pending,
    Running,
    Completed,
    Failed,
    Skipped,
}


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestItem {
    pub id: String,
    pub name: String,
    pub item_type: ItemType,
    pub status: ItemStatus,
    pub details: Option<String>,
    pub duration_seconds: Option<u64>,
    pub started_at: Option<DateTime<Utc>>,
    pub completed_at: Option<DateTime<Utc>>,
    pub metadata: HashMap<String, serde_json::Value>,
}

/// Grouped items displayed as a single row (e.g., "email, password_hash, email_verified")
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ItemGroup {
    pub id: String,
    pub items: Vec<String>,
    pub status: ItemStatus,
    pub duration_seconds: Option<u64>,
    pub started_at: Option<DateTime<Utc>>,
    pub completed_at: Option<DateTime<Utc>>,
}

impl ItemGroup {
    pub fn new(items: Vec<String>) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            items,
            status: ItemStatus::Pending,
            duration_seconds: None,
            started_at: None,
            completed_at: None,
        }
    }

    pub fn display_name(&self) -> String {
        self.items.join(", ")
    }

    pub fn start(&mut self) {
        self.status = ItemStatus::Running;
        self.started_at = Some(Utc::now());
    }

    pub fn complete(&mut self) {
        self.status = ItemStatus::Completed;
        self.completed_at = Some(Utc::now());
        if let Some(started) = self.started_at {
            self.duration_seconds = Some((Utc::now() - started).num_seconds() as u64);
        }
    }
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum ItemType {
    Table,
    Field,
    Index,
    File,
    Page,
    Tool,
    Scheduler,
    Monitor,
    Config,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Default)]
pub enum ItemStatus {
    #[default]
    Pending,
    Running,
    Completed,
    Failed,
    Skipped,
}


#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TerminalLine {
    pub timestamp: DateTime<Utc>,
    pub content: String,
    pub line_type: TerminalLineType,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TerminalLineType {
    Info,
    Progress,
    Success,
    Error,
    Warning,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ProcessingStats {
    pub data_points_processed: u64,
    pub processing_speed: f64,
    pub sources_per_min: f64,
    pub estimated_remaining_seconds: u64,
}

impl TaskManifest {
    pub fn new(app_name: &str, description: &str) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            app_name: app_name.to_string(),
            description: description.to_string(),
            created_at: Utc::now(),
            updated_at: Utc::now(),
            status: ManifestStatus::Planning,
            current_status: CurrentStatus {
                title: description.to_string(),
                current_action: None,
                decision_point: None,
            },
            sections: Vec::new(),
            total_steps: 0,
            completed_steps: 0,
            runtime_seconds: 0,
            estimated_seconds: 0,
            terminal_output: Vec::new(),
            processing_stats: ProcessingStats::default(),
        }
    }

    pub fn set_current_action(&mut self, action: &str) {
        self.current_status.current_action = Some(action.to_string());
        self.updated_at = Utc::now();
    }

    pub fn set_decision_point(&mut self, current: u32, total: u32, message: &str) {
        self.current_status.decision_point = Some(DecisionPoint {
            step_current: current,
            step_total: total,
            message: message.to_string(),
        });
        self.updated_at = Utc::now();
    }

    pub fn add_section(&mut self, mut section: ManifestSection) {
        // Set global step start for this section
        section.global_step_start = self.total_steps;

        // Update global step starts for children
        let mut child_offset = self.total_steps;
        for child in &mut section.children {
            child.global_step_start = child_offset;
            child_offset += child.total_steps;
        }

        self.total_steps += section.total_steps;
        for child in &section.children {
            self.total_steps += child.total_steps;
        }
        self.sections.push(section);
        self.updated_at = Utc::now();
    }

    pub fn start(&mut self) {
        self.status = ManifestStatus::Running;
        self.updated_at = Utc::now();
    }

    pub fn complete(&mut self) {
        self.status = ManifestStatus::Completed;
        self.completed_steps = self.total_steps;
        self.updated_at = Utc::now();
    }

    /// Recalculate global_step_start for all sections after modifications
    pub fn recalculate_global_steps(&mut self) {
        let mut offset = 0u32;
        for section in &mut self.sections {
            section.global_step_start = offset;

            // Update children's global step starts
            let mut child_offset = offset;
            for child in &mut section.children {
                child.global_step_start = child_offset;
                child_offset += child.total_steps;
            }

            // Add this section's steps (including children)
            offset += section.total_steps;
            for child in &section.children {
                offset += child.total_steps;
            }
        }

        // Recalculate total
        self.total_steps = offset;
        self.updated_at = Utc::now();
    }

    pub fn fail(&mut self) {
        self.status = ManifestStatus::Failed;
        self.updated_at = Utc::now();
    }

    pub fn add_terminal_line(&mut self, content: &str, line_type: TerminalLineType) {
        self.terminal_output.push(TerminalLine {
            timestamp: Utc::now(),
            content: content.to_string(),
            line_type,
        });
        self.updated_at = Utc::now();
    }

    pub fn update_section_status(&mut self, section_id: &str, status: SectionStatus) {
        for section in &mut self.sections {
            if section.id == section_id {
                section.status = status.clone();
                if status == SectionStatus::Completed {
                    section.completed_at = Some(Utc::now());
                    self.completed_steps += section.total_steps;
                }
                break;
            }
            for child in &mut section.children {
                if child.id == section_id {
                    child.status = status.clone();
                    if status == SectionStatus::Completed {
                        child.completed_at = Some(Utc::now());
                        self.completed_steps += child.total_steps;
                    }
                    break;
                }
            }
        }
        self.updated_at = Utc::now();
    }

    pub fn update_item_status(&mut self, section_id: &str, item_id: &str, status: ItemStatus) {
        for section in &mut self.sections {
            if section.id == section_id {
                for item in &mut section.items {
                    if item.id == item_id {
                        item.status = status;
                        if status == ItemStatus::Completed {
                            item.completed_at = Some(Utc::now());
                        }
                        return;
                    }
                }
            }
            for child in &mut section.children {
                if child.id == section_id {
                    for item in &mut child.items {
                        if item.id == item_id {
                            item.status = status;
                            if status == ItemStatus::Completed {
                                item.completed_at = Some(Utc::now());
                            }
                            return;
                        }
                    }
                }
            }
        }
        self.updated_at = Utc::now();
    }

    pub fn update_processing_stats(&mut self, stats: ProcessingStats) {
        self.processing_stats = stats;
        self.updated_at = Utc::now();
    }

    pub fn progress_percentage(&self) -> f64 {
        if self.total_steps == 0 {
            return 0.0;
        }
        (self.completed_steps as f64 / self.total_steps as f64) * 100.0
    }

    pub fn to_markdown(&self) -> String {
        let mut md = String::new();

        md.push_str(&format!("# TASK.md - {}\n\n", self.app_name));
        md.push_str(&format!("**Description:** {}\n\n", self.description));
        md.push_str(&format!("**Status:** {:?}\n", self.status));
        md.push_str(&format!(
            "**Progress:** {}/{} steps ({}%)\n\n",
            self.completed_steps,
            self.total_steps,
            self.progress_percentage() as u32
        ));

        md.push_str("## Artifacts\n\n");

        for section in &self.sections {
            md.push_str(&format!(
                "### {} - {:?}\n",
                section.name, section.status
            ));
            md.push_str(&format!(
                "- Steps: {}/{}\n",
                section.current_step, section.total_steps
            ));

            if !section.items.is_empty() {
                md.push_str("- Items:\n");
                for item in &section.items {
                    md.push_str(&format!(
                        "  - {} ({:?}): {:?}\n",
                        item.name, item.item_type, item.status
                    ));
                }
            }

            for child in &section.children {
                md.push_str(&format!(
                    "  #### {} - {:?}\n",
                    child.name, child.status
                ));
                md.push_str(&format!(
                    "  - Steps: {}/{}\n",
                    child.current_step, child.total_steps
                ));

                if !child.items.is_empty() {
                    md.push_str("  - Items:\n");
                    for item in &child.items {
                        md.push_str(&format!(
                            "    - {} ({:?}): {:?}\n",
                            item.name, item.item_type, item.status
                        ));
                    }
                }
            }

            md.push('\n');
        }

        md
    }

    pub fn to_web_json(&self) -> serde_json::Value {
        serde_json::json!({
            "id": self.id,
            "app_name": self.app_name,
            "description": self.description,
            "status": {
                "title": self.current_status.title,
                "runtime_display": format_duration(self.runtime_seconds),
                "estimated_display": format_duration(self.estimated_seconds),
                "current_action": self.current_status.current_action,
                "decision_point": self.current_status.decision_point.as_ref().map(|dp| serde_json::json!({
                    "step_current": dp.step_current,
                    "step_total": dp.step_total,
                    "message": dp.message
                }))
            },
            "progress": {
                "current": self.completed_steps,
                "total": self.total_steps,
                "percentage": self.progress_percentage()
            },
            "sections": self.sections.iter().map(section_to_web_json).collect::<Vec<_>>(),
            "terminal": {
                "lines": self.terminal_output.iter().map(|l| serde_json::json!({
                    "content": l.content,
                    "type": format!("{:?}", l.line_type).to_lowercase(),
                    "timestamp": l.timestamp.to_rfc3339()
                })).collect::<Vec<_>>(),
                "stats": {
                    "processed": self.processing_stats.data_points_processed,
                    "speed": format!("{:.1} sources/min", self.processing_stats.sources_per_min),
                    "estimated_completion": format_duration(self.processing_stats.estimated_remaining_seconds)
                }
            }
        })
    }

    pub fn to_task_md(&self) -> String {
        let mut md = String::new();
        md.push_str(&format!("# TASK.md - {}\n\n", self.app_name));
        md.push_str("## STATUS\n");
        md.push_str(&format!("- {}\n", self.current_status.title));
        if let Some(ref action) = self.current_status.current_action {
            md.push_str(&format!("  - [>] {}\n", action));
        }
        if let Some(ref dp) = self.current_status.decision_point {
            md.push_str(&format!("  - [ ] Decision Point (Step {}/{}) - {}\n", dp.step_current, dp.step_total, dp.message));
        }
        md.push_str("\n## PROGRESS LOG\n");
        for section in &self.sections {
            let checkbox = match section.status {
                SectionStatus::Completed => "[x]",
                SectionStatus::Running => "[>]",
                _ => "[ ]",
            };
            let global_step = section.global_step_start + section.current_step;
            md.push_str(&format!("- {} {} (Step {}/{})\n", checkbox, section.name, global_step, self.total_steps));
            for child in &section.children {
                let child_checkbox = match child.status {
                    SectionStatus::Completed => "[x]",
                    SectionStatus::Running => "[>]",
                    _ => "[ ]",
                };
                md.push_str(&format!("  - {} {} (Step {}/{})\n", child_checkbox, child.name, child.current_step, child.total_steps));

                // Render item groups first
                for group in &child.item_groups {
                    let group_checkbox = match group.status {
                        ItemStatus::Completed => "[x]",
                        ItemStatus::Running => "[>]",
                        _ => "[ ]",
                    };
                    let duration = group.duration_seconds.map(|s| format!(" - Duration: {} min", s / 60)).unwrap_or_default();
                    md.push_str(&format!("    - {} {}{}\n", group_checkbox, group.display_name(), duration));
                }

                // Then individual items
                for item in &child.items {
                    let item_checkbox = match item.status {
                        ItemStatus::Completed => "[x]",
                        ItemStatus::Running => "[>]",
                        _ => "[ ]",
                    };
                    let duration = item.duration_seconds.map(|s| format!(" - Duration: {}s", s)).unwrap_or_default();
                    md.push_str(&format!("    - {} {}{}\n", item_checkbox, item.name, duration));
                }
            }

            // Render section-level item groups
            for group in &section.item_groups {
                let group_checkbox = match group.status {
                    ItemStatus::Completed => "[x]",
                    ItemStatus::Running => "[>]",
                    _ => "[ ]",
                };
                let duration = group.duration_seconds.map(|s| format!(" - Duration: {} min", s / 60)).unwrap_or_default();
                md.push_str(&format!("  - {} {}{}\n", group_checkbox, group.display_name(), duration));
            }

            for item in &section.items {
                let item_checkbox = match item.status {
                    ItemStatus::Completed => "[x]",
                    ItemStatus::Running => "[>]",
                    _ => "[ ]",
                };
                md.push_str(&format!("  - {} {}\n", item_checkbox, item.name));
            }
        }
        md
    }

}

impl ManifestSection {
    pub fn new(name: &str, section_type: SectionType) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            name: name.to_string(),
            section_type,
            status: SectionStatus::Pending,
            current_step: 0,
            total_steps: 0,
            global_step_start: 0,
            duration_seconds: None,
            started_at: None,
            completed_at: None,
            items: Vec::new(),
            item_groups: Vec::new(),
            children: Vec::new(),
        }
    }

    pub fn with_steps(mut self, total: u32) -> Self {
        self.total_steps = total;
        self
    }

    pub fn add_item(&mut self, item: ManifestItem) {
        self.total_steps += 1;
        self.items.push(item);
    }

    pub fn add_item_group(&mut self, group: ItemGroup) {
        self.total_steps += 1;
        self.item_groups.push(group);
    }

    pub fn add_child(&mut self, child: ManifestSection) {
        self.total_steps += child.total_steps;
        self.children.push(child);
    }

    pub fn start(&mut self) {
        self.status = SectionStatus::Running;
        self.started_at = Some(Utc::now());
    }

    pub fn complete(&mut self) {
        self.status = SectionStatus::Completed;
        self.completed_at = Some(Utc::now());
        self.current_step = self.total_steps;
        if let Some(started) = self.started_at {
            self.duration_seconds = Some((Utc::now() - started).num_seconds() as u64);
        }
    }

    pub fn increment_step(&mut self) {
        self.current_step += 1;
    }
}

impl ManifestItem {
    pub fn new(name: &str, item_type: ItemType) -> Self {
        Self {
            id: Uuid::new_v4().to_string(),
            name: name.to_string(),
            item_type,
            status: ItemStatus::Pending,
            details: None,
            duration_seconds: None,
            started_at: None,
            completed_at: None,
            metadata: HashMap::new(),
        }
    }

    pub fn with_details(mut self, details: &str) -> Self {
        self.details = Some(details.to_string());
        self
    }

    pub fn with_metadata(mut self, key: &str, value: serde_json::Value) -> Self {
        self.metadata.insert(key.to_string(), value);
        self
    }

    pub fn start(&mut self) {
        self.status = ItemStatus::Running;
        self.started_at = Some(Utc::now());
    }

    pub fn complete(&mut self) {
        self.status = ItemStatus::Completed;
        self.completed_at = Some(Utc::now());
        if let Some(started) = self.started_at {
            self.duration_seconds = Some((Utc::now() - started).num_seconds() as u64);
        }
    }
}

fn section_to_web_json(section: &ManifestSection) -> serde_json::Value {
    let checkbox = match section.status {
        SectionStatus::Completed => "[x]",
        SectionStatus::Running => "[>]",
        _ => "[ ]",
    };

    // Calculate global step display (e.g., "Step 24/60")
    let global_current = section.global_step_start + section.current_step;

    serde_json::json!({
        "id": section.id,
        "name": section.name,
        "checkbox": checkbox,
        "type": format!("{:?}", section.section_type),
        "status": format!("{:?}", section.status),
        "progress": {
            "current": section.current_step,
            "total": section.total_steps,
            "display": format!("Step {}/{}", section.current_step, section.total_steps),
            "global_current": global_current,
            "global_start": section.global_step_start
        },
        "duration": section.duration_seconds.map(format_duration),
        "duration_seconds": section.duration_seconds,
        "items": section.items.iter().map(|i| {
            let item_checkbox = match i.status {
                ItemStatus::Completed => "[x]",
                ItemStatus::Running => "[>]",
                _ => "[ ]",
            };
            serde_json::json!({
                "id": i.id,
                "name": i.name,
                "checkbox": item_checkbox,
                "type": format!("{:?}", i.item_type),
                "status": format!("{:?}", i.status),
                "details": i.details,
                "duration": i.duration_seconds.map(format_duration),
                "duration_seconds": i.duration_seconds
            })
        }).collect::<Vec<_>>(),
        "item_groups": section.item_groups.iter().map(|g| {
            let group_checkbox = match g.status {
                ItemStatus::Completed => "[x]",
                ItemStatus::Running => "[>]",
                _ => "[ ]",
            };
            serde_json::json!({
                "id": g.id,
                "name": g.display_name(),
                "items": g.items,
                "checkbox": group_checkbox,
                "status": format!("{:?}", g.status),
                "duration": g.duration_seconds.map(format_duration),
                "duration_seconds": g.duration_seconds
            })
        }).collect::<Vec<_>>(),
        "children": section.children.iter().map(section_to_web_json).collect::<Vec<_>>()
    })
}

fn format_duration(seconds: u64) -> String {
    if seconds < 60 {
        format!("{} sec", seconds)
    } else if seconds < 3600 {
        format!("{} min", seconds / 60)
    } else {
        let hours = seconds / 3600;
        let mins = (seconds % 3600) / 60;
        format!("{} hr {} min", hours, mins)
    }
}

pub struct ManifestBuilder {
    manifest: TaskManifest,
}

impl ManifestBuilder {
    pub fn new(app_name: &str, description: &str) -> Self {
        Self {
            manifest: TaskManifest::new(app_name, description),
        }
    }

    pub fn with_tables(mut self, tables: Vec<TableDefinition>) -> Self {
        if tables.is_empty() {
            return self;
        }

        let mut db_section = ManifestSection::new("Database & Models", SectionType::DatabaseModels);

        let mut schema_section =
            ManifestSection::new("Database Schema Design", SectionType::SchemaDesign);

        // Each table becomes an item in the schema section
        for table in &tables {
            let field_count = table.fields.len();
            let field_names: Vec<String> = table.fields.iter().take(4).map(|f| f.name.clone()).collect();
            let fields_preview = if field_count > 4 {
                format!("{}, +{} more", field_names.join(", "), field_count - 4)
            } else {
                field_names.join(", ")
            };

            let mut item = ManifestItem::new(&table.name, ItemType::Table);
            item.details = Some(format!("{} fields: {}", field_count, fields_preview));
            schema_section.add_item(item);
        }

        db_section.add_child(schema_section);
        self.manifest.add_section(db_section);
        self
    }

    pub fn with_files(mut self, files: Vec<FileDefinition>) -> Self {
        if files.is_empty() {
            return self;
        }

        let mut files_section = ManifestSection::new("Files", SectionType::Files);

        // Group files by type for better organization
        let html_files: Vec<_> = files.iter().filter(|f| f.filename.ends_with(".html")).collect();
        let css_files: Vec<_> = files.iter().filter(|f| f.filename.ends_with(".css")).collect();
        let js_files: Vec<_> = files.iter().filter(|f| f.filename.ends_with(".js")).collect();

        // Create child section for HTML pages
        if !html_files.is_empty() {
            let mut pages_child = ManifestSection::new("HTML Pages", SectionType::Pages);
            for file in &html_files {
                let item = ManifestItem::new(&file.filename, ItemType::Page);
                pages_child.add_item(item);
            }
            files_section.add_child(pages_child);
        }

        // Create child section for styles
        if !css_files.is_empty() {
            let mut styles_child = ManifestSection::new("Stylesheets", SectionType::Files);
            for file in &css_files {
                let item = ManifestItem::new(&file.filename, ItemType::File);
                styles_child.add_item(item);
            }
            files_section.add_child(styles_child);
        }

        // Create child section for scripts
        if !js_files.is_empty() {
            let mut scripts_child = ManifestSection::new("Scripts", SectionType::Files);
            for file in &js_files {
                let item = ManifestItem::new(&file.filename, ItemType::File);
                scripts_child.add_item(item);
            }
            files_section.add_child(scripts_child);
        }

        self.manifest.add_section(files_section);
        self
    }

    pub fn with_pages(self, _pages: Vec<PageDefinition>) -> Self {
        // Pages are now included in Files section as HTML Pages child
        self
    }

    pub fn with_tools(mut self, tools: Vec<ToolDefinition>) -> Self {
        if tools.is_empty() {
            return self;
        }

        let mut tools_section = ManifestSection::new("Tools & Automation", SectionType::Tools);

        let mut automation_child = ManifestSection::new("BASIC Scripts", SectionType::Tools);
        for tool in tools {
            let item = ManifestItem::new(&tool.name, ItemType::Tool)
                .with_details(&tool.filename);
            automation_child.add_item(item);
        }
        tools_section.add_child(automation_child);

        self.manifest.add_section(tools_section);
        self
    }

    pub fn with_schedulers(mut self, schedulers: Vec<SchedulerDefinition>) -> Self {
        if schedulers.is_empty() {
            return self;
        }

        let mut sched_section = ManifestSection::new("Scheduled Tasks", SectionType::Schedulers);

        let mut cron_child = ManifestSection::new("Cron Jobs", SectionType::Schedulers);
        for scheduler in schedulers {
            let item = ManifestItem::new(&scheduler.name, ItemType::Scheduler)
                .with_details(&scheduler.schedule);
            cron_child.add_item(item);
        }
        sched_section.add_child(cron_child);

        self.manifest.add_section(sched_section);
        self
    }

    pub fn with_monitors(mut self, monitors: Vec<MonitorDefinition>) -> Self {
        if monitors.is_empty() {
            return self;
        }

        let mut mon_section = ManifestSection::new("Monitoring", SectionType::Monitors);

        let mut alerts_child = ManifestSection::new("Alert Rules", SectionType::Monitors);
        for monitor in monitors {
            let item =
                ManifestItem::new(&monitor.name, ItemType::Monitor).with_details(&monitor.target);
            alerts_child.add_item(item);
        }
        mon_section.add_child(alerts_child);

        self.manifest.add_section(mon_section);
        self
    }

    pub fn with_estimated_time(mut self, seconds: u64) -> Self {
        self.manifest.estimated_seconds = seconds;
        self
    }

    pub fn build(mut self) -> TaskManifest {
        self.manifest.status = ManifestStatus::Ready;
        self.manifest
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TableDefinition {
    pub name: String,
    pub fields: Vec<FieldDefinition>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldDefinition {
    pub name: String,
    pub field_type: String,
    pub nullable: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileDefinition {
    pub filename: String,
    pub size_estimate: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PageDefinition {
    pub filename: String,
    pub page_type: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDefinition {
    pub name: String,
    pub filename: String,
    pub triggers: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchedulerDefinition {
    pub name: String,
    pub filename: String,
    pub schedule: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitorDefinition {
    pub name: String,
    pub target: String,
}

pub struct ManifestData {
    pub tables: Vec<TableDefinition>,
    pub files: Vec<FileDefinition>,
    pub pages: Vec<PageDefinition>,
    pub tools: Vec<ToolDefinition>,
    pub schedulers: Vec<SchedulerDefinition>,
    pub monitors: Vec<MonitorDefinition>,
}

pub fn create_manifest_from_llm_response(
    app_name: &str,
    description: &str,
    data: ManifestData,
) -> TaskManifest {
    let estimated_time = estimate_generation_time(&data.tables, &data.files, &data.tools, &data.schedulers);

    ManifestBuilder::new(app_name, description)
        .with_tables(data.tables)
        .with_files(data.files)
        .with_pages(data.pages)
        .with_tools(data.tools)
        .with_schedulers(data.schedulers)
        .with_estimated_time(estimated_time)
        .build()
}

fn estimate_generation_time(
    tables: &[TableDefinition],
    files: &[FileDefinition],
    tools: &[ToolDefinition],
    schedulers: &[SchedulerDefinition],
) -> u64 {
    let table_time: u64 = tables.iter().map(|t| 5 + t.fields.len() as u64).sum();
    let file_time: u64 = files.len() as u64 * 3;
    let tool_time: u64 = tools.len() as u64 * 10;
    let sched_time: u64 = schedulers.len() as u64 * 5;

    table_time + file_time + tool_time + sched_time + 30
}
