import {
  IdType,
  generateId,
  WorkspaceCreateInput,
  WorkspaceOutput,
  WorkspaceStatus,
  UserStatus,
} from '@colanode/core';
import { database } from '@colanode/server/data/database';
import { SelectAccount } from '@colanode/server/data/schema';
import {
  generateInitialMessageBlocks,
  generateWelcomePageBlocks,
} from '@colanode/server/lib/blocks';
import { config } from '@colanode/server/lib/config';
import { createDocument } from '@colanode/server/lib/documents';
import { eventBus } from '@colanode/server/lib/event-bus';
import { createNode } from '@colanode/server/lib/nodes';

export const createWorkspace = async (
  account: SelectAccount,
  input: WorkspaceCreateInput
): Promise<WorkspaceOutput> => {
  const date = new Date();
  const workspaceId = generateId(IdType.Workspace);
  const userId = generateId(IdType.User);
  const spaceId = generateId(IdType.Space);

  const workspace = await database
    .insertInto('workspaces')
    .values({
      id: workspaceId,
      name: input.name,
      description: input.description,
      avatar: input.avatar,
      created_at: date,
      created_by: account.id,
      status: WorkspaceStatus.Active,
      storage_limit: config.workspace.storageLimit,
      max_file_size: config.workspace.maxFileSize,
    })
    .returningAll()
    .executeTakeFirst();

  if (!workspace) {
    throw new Error('Failed to create workspace.');
  }

  const user = await database
    .insertInto('users')
    .values({
      id: userId,
      account_id: account.id,
      workspace_id: workspaceId,
      role: 'owner',
      name: account.name,
      email: account.email,
      avatar: account.avatar,
      storage_limit: config.user.storageLimit,
      max_file_size: config.user.maxFileSize,
      created_at: date,
      created_by: account.id,
      status: UserStatus.Active,
    })
    .returningAll()
    .executeTakeFirst();

  if (!user) {
    throw new Error('Failed to create workspace user.');
  }

  const createSpaceOutput = await createNode({
    nodeId: spaceId,
    rootId: spaceId,
    attributes: {
      type: 'space',
      name: 'Home',
      description: 'This is your home space.',
      visibility: 'private',
      collaborators: {
        [userId]: 'admin',
      },
    },
    userId: userId,
    workspaceId: workspaceId,
  });

  if (createSpaceOutput) {
    const pageId = generateId(IdType.Page);
    await createNode({
      nodeId: pageId,
      rootId: spaceId,
      attributes: {
        type: 'page',
        name: 'Welcome',
        parentId: spaceId,
      },
      userId: userId,
      workspaceId: workspaceId,
    });

    await createDocument({
      content: {
        type: 'rich_text',
        blocks: generateWelcomePageBlocks(pageId),
      },
      nodeId: pageId,
      userId: userId,
      workspaceId: workspaceId,
    });

    const channelId = generateId(IdType.Channel);
    await createNode({
      nodeId: channelId,
      rootId: spaceId,
      attributes: {
        type: 'channel',
        name: 'Discussions',
        parentId: spaceId,
      },
      userId: userId,
      workspaceId: workspaceId,
    });

    const messageId = generateId(IdType.Message);
    await createNode({
      nodeId: messageId,
      rootId: spaceId,
      attributes: {
        type: 'message',
        parentId: channelId,
        subtype: 'standard',
        content: generateInitialMessageBlocks(messageId),
      },
      userId: userId,
      workspaceId: workspaceId,
    });
  }

  eventBus.publish({
    type: 'workspace.created',
    workspaceId: workspaceId,
  });

  eventBus.publish({
    type: 'user.created',
    userId: userId,
    workspaceId: workspaceId,
    accountId: account.id,
  });

  return {
    id: workspace.id,
    name: workspace.name,
    description: workspace.description,
    avatar: workspace.avatar,
    user: {
      id: user.id,
      accountId: user.account_id,
      role: user.role,
      storageLimit: user.storage_limit,
      maxFileSize: user.max_file_size,
    },
  };
};

export const createDefaultWorkspace = async (
  account: SelectAccount
): Promise<WorkspaceOutput> => {
  const input: WorkspaceCreateInput = {
    name: `${account.name}'s Workspace`,
    description: 'This is your personal workspace.',
    avatar: '',
  };

  return createWorkspace(account, input);
};
