import {
  PrismaClient,
  TaskStatus,
  TaskPriority,
  ProjectStatus,
  WorkspaceMemberRole,
  EntryStatus,
  Visibility,
} from "@prisma/client";
import { seedAgentTemplates } from "../src/seed/agent-templates.seed";

const prisma = new PrismaClient();

async function main() {
  console.log("Seeding database...");

  // IMPORTANT: This seed script should not be run concurrently
  // If running in CI/CD, ensure serialization of seed operations
  // to prevent race conditions and data corruption

  // Create test user
  const user = await prisma.user.upsert({
    where: { email: "dev@mosaic.local" },
    update: {},
    create: {
      email: "dev@mosaic.local",
      name: "Development User",
      preferences: {
        theme: "system",
        notifications: true,
      },
    },
  });

  console.log(`Created user: ${user.email}`);

  // Create workspace
  const workspace = await prisma.workspace.upsert({
    where: { id: "00000000-0000-0000-0000-000000000001" },
    update: {},
    create: {
      id: "00000000-0000-0000-0000-000000000001",
      name: "Development Workspace",
      ownerId: user.id,
      settings: {
        timezone: "America/New_York",
      },
    },
  });

  console.log(`Created workspace: ${workspace.name}`);

  // Add user as workspace owner
  await prisma.workspaceMember.upsert({
    where: {
      workspaceId_userId: {
        workspaceId: workspace.id,
        userId: user.id,
      },
    },
    update: {},
    create: {
      workspaceId: workspace.id,
      userId: user.id,
      role: WorkspaceMemberRole.OWNER,
    },
  });

  // ============================================
  // WIDGET DEFINITIONS (global, not workspace-scoped)
  // ============================================
  const widgetDefs = [
    {
      name: "TasksWidget",
      displayName: "Tasks",
      description: "View and manage your tasks",
      component: "TasksWidget",
      defaultWidth: 2,
      defaultHeight: 2,
      minWidth: 1,
      minHeight: 2,
      maxWidth: 4,
      maxHeight: null,
      configSchema: {},
    },
    {
      name: "CalendarWidget",
      displayName: "Calendar",
      description: "View upcoming events and schedule",
      component: "CalendarWidget",
      defaultWidth: 2,
      defaultHeight: 2,
      minWidth: 2,
      minHeight: 2,
      maxWidth: 4,
      maxHeight: null,
      configSchema: {},
    },
    {
      name: "QuickCaptureWidget",
      displayName: "Quick Capture",
      description: "Quickly capture notes and tasks",
      component: "QuickCaptureWidget",
      defaultWidth: 2,
      defaultHeight: 1,
      minWidth: 2,
      minHeight: 1,
      maxWidth: 4,
      maxHeight: 2,
      configSchema: {},
    },
    {
      name: "AgentStatusWidget",
      displayName: "Agent Status",
      description: "Monitor agent activity and status",
      component: "AgentStatusWidget",
      defaultWidth: 2,
      defaultHeight: 2,
      minWidth: 1,
      minHeight: 2,
      maxWidth: 3,
      maxHeight: null,
      configSchema: {},
    },
    {
      name: "ActiveProjectsWidget",
      displayName: "Active Projects & Agent Chains",
      description: "View active projects and running agent sessions",
      component: "ActiveProjectsWidget",
      defaultWidth: 2,
      defaultHeight: 3,
      minWidth: 2,
      minHeight: 2,
      maxWidth: 4,
      maxHeight: null,
      configSchema: {},
    },
    {
      name: "TaskProgressWidget",
      displayName: "Task Progress",
      description: "Live progress of orchestrator agent tasks",
      component: "TaskProgressWidget",
      defaultWidth: 2,
      defaultHeight: 2,
      minWidth: 1,
      minHeight: 2,
      maxWidth: 3,
      maxHeight: null,
      configSchema: {},
    },
    {
      name: "OrchestratorEventsWidget",
      displayName: "Orchestrator Events",
      description: "Recent orchestration events with stream/Matrix visibility",
      component: "OrchestratorEventsWidget",
      defaultWidth: 2,
      defaultHeight: 2,
      minWidth: 1,
      minHeight: 2,
      maxWidth: 4,
      maxHeight: null,
      configSchema: {},
    },
  ];

  for (const wd of widgetDefs) {
    await prisma.widgetDefinition.upsert({
      where: { name: wd.name },
      update: {
        displayName: wd.displayName,
        description: wd.description,
        component: wd.component,
        defaultWidth: wd.defaultWidth,
        defaultHeight: wd.defaultHeight,
        minWidth: wd.minWidth,
        minHeight: wd.minHeight,
        maxWidth: wd.maxWidth,
        maxHeight: wd.maxHeight,
        configSchema: wd.configSchema,
      },
      create: {
        name: wd.name,
        displayName: wd.displayName,
        description: wd.description,
        component: wd.component,
        defaultWidth: wd.defaultWidth,
        defaultHeight: wd.defaultHeight,
        minWidth: wd.minWidth,
        minHeight: wd.minHeight,
        maxWidth: wd.maxWidth,
        maxHeight: wd.maxHeight,
        configSchema: wd.configSchema,
      },
    });
  }

  console.log(`Seeded ${widgetDefs.length} widget definitions`);

  // Use transaction for atomic seed data reset and creation
  await prisma.$transaction(async (tx) => {
    // Delete existing seed data for idempotency (avoids duplicates on re-run)
    await tx.task.deleteMany({ where: { workspaceId: workspace.id } });
    await tx.event.deleteMany({ where: { workspaceId: workspace.id } });
    await tx.project.deleteMany({ where: { workspaceId: workspace.id } });

    // Create sample project
    const project = await tx.project.create({
      data: {
        workspaceId: workspace.id,
        name: "Sample Project",
        description: "A sample project for development",
        status: ProjectStatus.ACTIVE,
        creatorId: user.id,
        color: "#3B82F6",
      },
    });

    console.log(`Created project: ${project.name}`);

    // Create sample tasks
    const tasks = [
      {
        title: "Set up development environment",
        status: TaskStatus.COMPLETED,
        priority: TaskPriority.HIGH,
      },
      {
        title: "Review project requirements",
        status: TaskStatus.IN_PROGRESS,
        priority: TaskPriority.MEDIUM,
      },
      {
        title: "Design database schema",
        status: TaskStatus.COMPLETED,
        priority: TaskPriority.HIGH,
      },
      {
        title: "Implement NestJS integration",
        status: TaskStatus.COMPLETED,
        priority: TaskPriority.HIGH,
      },
      {
        title: "Create seed data",
        status: TaskStatus.IN_PROGRESS,
        priority: TaskPriority.MEDIUM,
      },
    ];

    // Use createMany for batch insertion (better performance)
    await tx.task.createMany({
      data: tasks.map((taskData) => ({
        workspaceId: workspace.id,
        title: taskData.title,
        status: taskData.status,
        priority: taskData.priority,
        creatorId: user.id,
        projectId: project.id,
      })),
    });

    console.log(`Created ${tasks.length} sample tasks`);

    // Create sample event
    const tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate() + 1);
    tomorrow.setHours(10, 0, 0, 0);

    await tx.event.create({
      data: {
        workspaceId: workspace.id,
        title: "Morning standup",
        description: "Daily team sync",
        startTime: tomorrow,
        endTime: new Date(tomorrow.getTime() + 30 * 60000), // 30 minutes later
        creatorId: user.id,
        projectId: project.id,
      },
    });

    console.log("Created sample event");

    // ============================================
    // KNOWLEDGE MODULE SEED DATA
    // ============================================

    // Delete existing knowledge data
    await tx.knowledgeEmbedding.deleteMany({ where: { entry: { workspaceId: workspace.id } } });
    await tx.knowledgeEntryTag.deleteMany({ where: { entry: { workspaceId: workspace.id } } });
    await tx.knowledgeLink.deleteMany({ where: { source: { workspaceId: workspace.id } } });
    await tx.knowledgeEntryVersion.deleteMany({ where: { entry: { workspaceId: workspace.id } } });
    await tx.knowledgeEntry.deleteMany({ where: { workspaceId: workspace.id } });
    await tx.knowledgeTag.deleteMany({ where: { workspaceId: workspace.id } });

    // Create knowledge tags
    const tags = await Promise.all([
      tx.knowledgeTag.create({
        data: {
          workspaceId: workspace.id,
          name: "Architecture",
          slug: "architecture",
          color: "#3B82F6",
          description: "System architecture and design decisions",
        },
      }),
      tx.knowledgeTag.create({
        data: {
          workspaceId: workspace.id,
          name: "Development",
          slug: "development",
          color: "#10B981",
          description: "Development practices and guidelines",
        },
      }),
      tx.knowledgeTag.create({
        data: {
          workspaceId: workspace.id,
          name: "Getting Started",
          slug: "getting-started",
          color: "#F59E0B",
          description: "Onboarding and setup guides",
        },
      }),
    ]);

    console.log(`Created ${tags.length} knowledge tags`);

    // Create knowledge entries
    const entries = [
      {
        slug: "welcome",
        title: "Welcome to Mosaic Stack Knowledge Base",
        content: `# Welcome to Mosaic Stack

This is the knowledge base for the Mosaic Stack project. Here you'll find:

- **[[architecture-overview]]** - High-level system architecture
- **[[development-setup]]** - Getting started with development
- **[[database-schema]]** - Database design and conventions

## About This Knowledge Base

The Knowledge Module provides:
- Wiki-style linking between entries
- Full-text and semantic search
- Version history and change tracking
- Tag-based organization

Start exploring by following the links above!`,
        summary: "Introduction to the Mosaic Stack knowledge base and navigation guide",
        status: EntryStatus.PUBLISHED,
        visibility: Visibility.WORKSPACE,
        tags: ["getting-started"],
      },
      {
        slug: "architecture-overview",
        title: "Architecture Overview",
        content: `# Architecture Overview

The Mosaic Stack is built on a modern, scalable architecture:

## Stack Components

- **Frontend**: Next.js 15+ with React 19
- **Backend**: NestJS with Prisma ORM
- **Database**: PostgreSQL 17 with pgvector
- **Cache**: Valkey (Redis fork)

## Key Modules

1. **Task Management** - See [[development-setup]] for local setup
2. **Event Calendar** - Integrated scheduling
3. **Knowledge Base** - This module! See [[database-schema]]
4. **Agent Orchestration** - AI agent coordination

The database schema is documented in [[database-schema]].`,
        summary: "High-level overview of Mosaic Stack architecture and components",
        status: EntryStatus.PUBLISHED,
        visibility: Visibility.WORKSPACE,
        tags: ["architecture"],
      },
      {
        slug: "development-setup",
        title: "Development Setup Guide",
        content: `# Development Setup Guide

## Prerequisites

- Node.js 22+
- PostgreSQL 17
- pnpm 9+

## Quick Start

\`\`\`bash
# Clone the repository
git clone https://git.mosaicstack.dev/mosaic/stack.git

# Install dependencies
pnpm install

# Set up database
cd apps/api
pnpm prisma migrate dev
pnpm prisma:seed

# Start development servers
pnpm dev
\`\`\`

## Architecture

Before diving in, review the [[architecture-overview]] to understand the system design.

## Database

The database schema is documented in [[database-schema]]. All models use Prisma ORM.

## Next Steps

1. Read the [[architecture-overview]]
2. Explore the codebase
3. Check out the [[database-schema]] documentation`,
        summary: "Step-by-step guide to setting up the Mosaic Stack development environment",
        status: EntryStatus.PUBLISHED,
        visibility: Visibility.WORKSPACE,
        tags: ["development", "getting-started"],
      },
      {
        slug: "database-schema",
        title: "Database Schema Documentation",
        content: `# Database Schema Documentation

## Overview

Mosaic Stack uses PostgreSQL 17 with Prisma ORM. See [[architecture-overview]] for context.

## Key Conventions

- All IDs are UUIDs
- Timestamps use \`@db.Timestamptz\` (timezone-aware)
- Soft deletes via status fields (e.g., ARCHIVED)
- Relations enforce cascade deletes for data integrity

## Core Models

### Task Management
- \`Task\` - Individual work items
- \`Project\` - Task containers
- \`Domain\` - High-level categorization

### Knowledge Module
- \`KnowledgeEntry\` - Wiki pages
- \`KnowledgeLink\` - Page connections
- \`KnowledgeTag\` - Categorization
- \`KnowledgeEmbedding\` - Semantic search (pgvector)

### Agent System
- \`Agent\` - AI agent instances
- \`AgentSession\` - Conversation sessions

## Migrations

Migrations are managed via Prisma:

\`\`\`bash
# Create migration
pnpm prisma migrate dev --name my_migration

# Apply in production
pnpm prisma migrate deploy
\`\`\`

For setup instructions, see [[development-setup]].`,
        summary:
          "Comprehensive documentation of the Mosaic Stack database schema and Prisma conventions",
        status: EntryStatus.PUBLISHED,
        visibility: Visibility.WORKSPACE,
        tags: ["architecture", "development"],
      },
      {
        slug: "future-ideas",
        title: "Future Ideas and Roadmap",
        content: `# Future Ideas and Roadmap

## Planned Features

- Real-time collaboration (CRDT)
- Advanced graph visualizations
- AI-powered summarization
- Mobile app

## Research Areas

- Vector search optimization
- Knowledge graph algorithms
- Agent memory systems

This is a draft document. See [[architecture-overview]] for current state.`,
        summary: "Brainstorming document for future features and research directions",
        status: EntryStatus.DRAFT,
        visibility: Visibility.PRIVATE,
        tags: [],
      },
    ];

    // Create entries and track them for linking
    const createdEntries = new Map<string, any>();

    for (const entryData of entries) {
      const entry = await tx.knowledgeEntry.create({
        data: {
          workspaceId: workspace.id,
          slug: entryData.slug,
          title: entryData.title,
          content: entryData.content,
          summary: entryData.summary,
          status: entryData.status,
          visibility: entryData.visibility,
          createdBy: user.id,
          updatedBy: user.id,
        },
      });

      createdEntries.set(entryData.slug, entry);

      // Create initial version
      await tx.knowledgeEntryVersion.create({
        data: {
          entryId: entry.id,
          version: 1,
          title: entry.title,
          content: entry.content,
          summary: entry.summary,
          createdBy: user.id,
          changeNote: "Initial version",
        },
      });

      // Add tags
      for (const tagSlug of entryData.tags) {
        const tag = tags.find((t) => t.slug === tagSlug);
        if (tag) {
          await tx.knowledgeEntryTag.create({
            data: {
              entryId: entry.id,
              tagId: tag.id,
            },
          });
        }
      }
    }

    console.log(`Created ${entries.length} knowledge entries`);

    // Create wiki-links between entries
    const links = [
      { source: "welcome", target: "architecture-overview", text: "architecture-overview" },
      { source: "welcome", target: "development-setup", text: "development-setup" },
      { source: "welcome", target: "database-schema", text: "database-schema" },
      { source: "architecture-overview", target: "development-setup", text: "development-setup" },
      { source: "architecture-overview", target: "database-schema", text: "database-schema" },
      {
        source: "development-setup",
        target: "architecture-overview",
        text: "architecture-overview",
      },
      { source: "development-setup", target: "database-schema", text: "database-schema" },
      { source: "database-schema", target: "architecture-overview", text: "architecture-overview" },
      { source: "database-schema", target: "development-setup", text: "development-setup" },
      { source: "future-ideas", target: "architecture-overview", text: "architecture-overview" },
    ];

    for (const link of links) {
      const sourceEntry = createdEntries.get(link.source);
      const targetEntry = createdEntries.get(link.target);

      if (sourceEntry && targetEntry) {
        await tx.knowledgeLink.create({
          data: {
            sourceId: sourceEntry.id,
            targetId: targetEntry.id,
            linkText: link.text,
          },
        });
      }
    }

    console.log(`Created ${links.length} knowledge links`);
  });
  // Seed default agent templates (idempotent)
  await seedAgentTemplates(prisma);

  console.log("Seeding completed successfully!");
}

main()
  .catch((e) => {
    console.error("Error seeding database:", e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
