import { z } from 'zod';
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import type { NotionClient } from '../clients/notion.js';
import type { BlockId, Block } from '../types/index.js';

// Zod schemas
const GetBlockSchema = z.object({
  block_id: z.string().describe('The ID of the block'),
});

const GetBlockChildrenSchema = z.object({
  block_id: z.string().describe('The ID of the parent block'),
  page_size: z.number().min(1).max(100).optional(),
  start_cursor: z.string().optional(),
});

const GetBlockChildrenAllSchema = z.object({
  block_id: z.string().describe('The ID of the parent block'),
});

const AppendBlockChildrenSchema = z.object({
  block_id: z.string().describe('The ID of the parent block (page or block)'),
  children: z.array(z.any()).describe('Array of block objects to append'),
});

const UpdateBlockSchema = z.object({
  block_id: z.string().describe('The ID of the block to update'),
  block: z.any().describe('Block object with updates (type-specific properties)'),
});

const DeleteBlockSchema = z.object({
  block_id: z.string().describe('The ID of the block to delete'),
});

// Block creation helpers
const CreateParagraphSchema = z.object({
  parent_id: z.string().describe('ID of parent block or page'),
  text: z.string().describe('Paragraph text content'),
  color: z.string().optional().describe('Text color'),
});

const CreateHeadingSchema = z.object({
  parent_id: z.string(),
  level: z.number().min(1).max(3).describe('Heading level (1, 2, or 3)'),
  text: z.string().describe('Heading text'),
  color: z.string().optional(),
  is_toggleable: z.boolean().optional(),
});

const CreateToDoSchema = z.object({
  parent_id: z.string(),
  text: z.string().describe('To-do item text'),
  checked: z.boolean().optional().describe('Whether item is checked'),
  color: z.string().optional(),
});

const CreateBulletedListItemSchema = z.object({
  parent_id: z.string(),
  text: z.string().describe('List item text'),
  color: z.string().optional(),
});

const CreateNumberedListItemSchema = z.object({
  parent_id: z.string(),
  text: z.string().describe('List item text'),
  color: z.string().optional(),
});

const CreateToggleSchema = z.object({
  parent_id: z.string(),
  text: z.string().describe('Toggle block text'),
  color: z.string().optional(),
});

const CreateCodeSchema = z.object({
  parent_id: z.string(),
  code: z.string().describe('Code content'),
  language: z.string().describe('Programming language (e.g., javascript, python)'),
  caption: z.string().optional().describe('Code block caption'),
});

const CreateQuoteSchema = z.object({
  parent_id: z.string(),
  text: z.string().describe('Quote text'),
  color: z.string().optional(),
});

const CreateCalloutSchema = z.object({
  parent_id: z.string(),
  text: z.string().describe('Callout text'),
  icon_emoji: z.string().optional().describe('Emoji icon (e.g., "💡")'),
  color: z.string().optional(),
});

const CreateDividerSchema = z.object({
  parent_id: z.string(),
});

const CreateBookmarkSchema = z.object({
  parent_id: z.string(),
  url: z.string().describe('URL to bookmark'),
  caption: z.string().optional(),
});

const CreateImageSchema = z.object({
  parent_id: z.string(),
  url: z.string().describe('Image URL'),
  caption: z.string().optional(),
});

const CreateVideoSchema = z.object({
  parent_id: z.string(),
  url: z.string().describe('Video URL'),
  caption: z.string().optional(),
});

const CreateEmbedSchema = z.object({
  parent_id: z.string(),
  url: z.string().describe('Embed URL'),
  caption: z.string().optional(),
});

const CreateTableSchema = z.object({
  parent_id: z.string(),
  table_width: z.number().describe('Number of columns'),
  has_column_header: z.boolean().optional(),
  has_row_header: z.boolean().optional(),
  rows: z
    .array(z.array(z.string()))
    .optional()
    .describe('2D array of cell contents (rows of cells)'),
});

export function getTools(client: NotionClient): Tool[] {
  return [
    {
      name: 'notion_get_block',
      description: 'Retrieve a block by ID. Returns block type, content, and metadata.',
      inputSchema: {
        type: 'object',
        properties: {
          block_id: { type: 'string', description: 'The ID of the block' },
        },
        required: ['block_id'],
      },
    },
    {
      name: 'notion_get_block_children',
      description:
        'Retrieve children blocks of a block or page. Returns paginated list of child blocks.',
      inputSchema: {
        type: 'object',
        properties: {
          block_id: { type: 'string', description: 'The ID of the parent block or page' },
          page_size: { type: 'number', description: 'Number of results (max 100)' },
          start_cursor: { type: 'string', description: 'Pagination cursor' },
        },
        required: ['block_id'],
      },
    },
    {
      name: 'notion_get_block_children_all',
      description:
        'Retrieve ALL children blocks (auto-paginating). Returns complete list of child blocks.',
      inputSchema: {
        type: 'object',
        properties: {
          block_id: { type: 'string', description: 'The ID of the parent block or page' },
        },
        required: ['block_id'],
      },
    },
    {
      name: 'notion_append_block_children',
      description:
        'Append child blocks to a parent block or page. Accepts array of block objects.',
      inputSchema: {
        type: 'object',
        properties: {
          block_id: { type: 'string', description: 'Parent block or page ID' },
          children: {
            type: 'array',
            description: 'Array of block objects to append',
          },
        },
        required: ['block_id', 'children'],
      },
    },
    {
      name: 'notion_update_block',
      description: 'Update a block\'s content. Block type determines which properties can be updated.',
      inputSchema: {
        type: 'object',
        properties: {
          block_id: { type: 'string', description: 'The ID of the block to update' },
          block: {
            type: 'object',
            description:
              'Block object with type-specific properties (e.g., {paragraph: {rich_text: [...]}})',
          },
        },
        required: ['block_id', 'block'],
      },
    },
    {
      name: 'notion_delete_block',
      description: 'Delete (archive) a block. Deleted blocks are moved to trash and can be restored.',
      inputSchema: {
        type: 'object',
        properties: {
          block_id: { type: 'string', description: 'The ID of the block to delete' },
        },
        required: ['block_id'],
      },
    },

    // Block creation helpers
    {
      name: 'notion_create_paragraph',
      description: 'Create a paragraph block with text content.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string', description: 'Parent block or page ID' },
          text: { type: 'string', description: 'Paragraph text' },
          color: { type: 'string', description: 'Text color (e.g., "blue", "red_background")' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_heading',
      description: 'Create a heading block (H1, H2, or H3).',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string', description: 'Parent block or page ID' },
          level: {
            type: 'number',
            description: 'Heading level: 1, 2, or 3',
            enum: [1, 2, 3],
          },
          text: { type: 'string', description: 'Heading text' },
          color: { type: 'string' },
          is_toggleable: {
            type: 'boolean',
            description: 'Whether heading is toggleable',
          },
        },
        required: ['parent_id', 'level', 'text'],
      },
    },
    {
      name: 'notion_create_todo',
      description: 'Create a to-do checkbox item.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          text: { type: 'string', description: 'To-do item text' },
          checked: { type: 'boolean', description: 'Whether checked' },
          color: { type: 'string' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_bulleted_list_item',
      description: 'Create a bulleted list item.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          text: { type: 'string', description: 'List item text' },
          color: { type: 'string' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_numbered_list_item',
      description: 'Create a numbered list item.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          text: { type: 'string', description: 'List item text' },
          color: { type: 'string' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_toggle',
      description: 'Create a toggle block (collapsible section).',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          text: { type: 'string', description: 'Toggle text' },
          color: { type: 'string' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_code',
      description: 'Create a code block with syntax highlighting.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          code: { type: 'string', description: 'Code content' },
          language: {
            type: 'string',
            description: 'Programming language (javascript, python, etc.)',
          },
          caption: { type: 'string', description: 'Optional caption' },
        },
        required: ['parent_id', 'code', 'language'],
      },
    },
    {
      name: 'notion_create_quote',
      description: 'Create a quote block.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          text: { type: 'string', description: 'Quote text' },
          color: { type: 'string' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_callout',
      description: 'Create a callout block with icon and background.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          text: { type: 'string', description: 'Callout text' },
          icon_emoji: { type: 'string', description: 'Emoji icon (e.g., "💡")' },
          color: { type: 'string' },
        },
        required: ['parent_id', 'text'],
      },
    },
    {
      name: 'notion_create_divider',
      description: 'Create a horizontal divider line.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string', description: 'Parent block or page ID' },
        },
        required: ['parent_id'],
      },
    },
    {
      name: 'notion_create_bookmark',
      description: 'Create a bookmark block for a URL.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          url: { type: 'string', description: 'URL to bookmark' },
          caption: { type: 'string' },
        },
        required: ['parent_id', 'url'],
      },
    },
    {
      name: 'notion_create_image',
      description: 'Create an image block from a URL.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          url: { type: 'string', description: 'Image URL' },
          caption: { type: 'string' },
        },
        required: ['parent_id', 'url'],
      },
    },
    {
      name: 'notion_create_video',
      description: 'Create a video embed block.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          url: { type: 'string', description: 'Video URL (YouTube, Vimeo, etc.)' },
          caption: { type: 'string' },
        },
        required: ['parent_id', 'url'],
      },
    },
    {
      name: 'notion_create_embed',
      description: 'Create an embed block for external content.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          url: { type: 'string', description: 'URL to embed' },
          caption: { type: 'string' },
        },
        required: ['parent_id', 'url'],
      },
    },
    {
      name: 'notion_create_table',
      description: 'Create a table block with specified dimensions.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_id: { type: 'string' },
          table_width: { type: 'number', description: 'Number of columns' },
          has_column_header: { type: 'boolean' },
          has_row_header: { type: 'boolean' },
          rows: {
            type: 'array',
            description: '2D array of cell text (rows of cells)',
          },
        },
        required: ['parent_id', 'table_width'],
      },
    },
  ];
}

// Helper to create rich_text array from string
function textToRichText(text: string): any[] {
  return [{ type: 'text', text: { content: text } }];
}

export async function handleBlockTool(
  toolName: string,
  args: any,
  client: NotionClient
): Promise<any> {
  switch (toolName) {
    case 'notion_get_block': {
      const validated = GetBlockSchema.parse(args);
      const block = await client.getBlock(validated.block_id as BlockId);
      return block;
    }

    case 'notion_get_block_children': {
      const validated = GetBlockChildrenSchema.parse(args);
      const children = await client.getBlockChildren(
        validated.block_id as BlockId,
        validated.start_cursor,
        validated.page_size
      );
      return children;
    }

    case 'notion_get_block_children_all': {
      const validated = GetBlockChildrenAllSchema.parse(args);
      const allBlocks = [];
      for await (const block of client.getBlockChildrenAll(validated.block_id as BlockId)) {
        allBlocks.push(block);
      }
      return { object: 'list', results: allBlocks, has_more: false, next_cursor: null };
    }

    case 'notion_append_block_children': {
      const validated = AppendBlockChildrenSchema.parse(args);
      const result = await client.appendBlockChildren(
        validated.block_id as BlockId,
        validated.children as Block[]
      );
      return result;
    }

    case 'notion_update_block': {
      const validated = UpdateBlockSchema.parse(args);
      const block = await client.updateBlock(
        validated.block_id as BlockId,
        validated.block as Partial<Block>
      );
      return block;
    }

    case 'notion_delete_block': {
      const validated = DeleteBlockSchema.parse(args);
      const block = await client.deleteBlock(validated.block_id as BlockId);
      return block;
    }

    // Block creation helpers
    case 'notion_create_paragraph': {
      const validated = CreateParagraphSchema.parse(args);
      const block = {
        type: 'paragraph',
        paragraph: {
          rich_text: textToRichText(validated.text),
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_heading': {
      const validated = CreateHeadingSchema.parse(args);
      const type = `heading_${validated.level}` as 'heading_1' | 'heading_2' | 'heading_3';
      const block = {
        type,
        [type]: {
          rich_text: textToRichText(validated.text),
          color: validated.color || 'default',
          is_toggleable: validated.is_toggleable || false,
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_todo': {
      const validated = CreateToDoSchema.parse(args);
      const block = {
        type: 'to_do',
        to_do: {
          rich_text: textToRichText(validated.text),
          checked: validated.checked || false,
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_bulleted_list_item': {
      const validated = CreateBulletedListItemSchema.parse(args);
      const block = {
        type: 'bulleted_list_item',
        bulleted_list_item: {
          rich_text: textToRichText(validated.text),
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_numbered_list_item': {
      const validated = CreateNumberedListItemSchema.parse(args);
      const block = {
        type: 'numbered_list_item',
        numbered_list_item: {
          rich_text: textToRichText(validated.text),
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_toggle': {
      const validated = CreateToggleSchema.parse(args);
      const block = {
        type: 'toggle',
        toggle: {
          rich_text: textToRichText(validated.text),
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_code': {
      const validated = CreateCodeSchema.parse(args);
      const block = {
        type: 'code',
        code: {
          rich_text: textToRichText(validated.code),
          language: validated.language,
          caption: validated.caption ? textToRichText(validated.caption) : [],
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_quote': {
      const validated = CreateQuoteSchema.parse(args);
      const block = {
        type: 'quote',
        quote: {
          rich_text: textToRichText(validated.text),
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_callout': {
      const validated = CreateCalloutSchema.parse(args);
      const block = {
        type: 'callout',
        callout: {
          rich_text: textToRichText(validated.text),
          icon: validated.icon_emoji
            ? { type: 'emoji', emoji: validated.icon_emoji }
            : { type: 'emoji', emoji: '💡' },
          color: validated.color || 'default',
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_divider': {
      const validated = CreateDividerSchema.parse(args);
      const block = {
        type: 'divider',
        divider: {},
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_bookmark': {
      const validated = CreateBookmarkSchema.parse(args);
      const block = {
        type: 'bookmark',
        bookmark: {
          url: validated.url,
          caption: validated.caption ? textToRichText(validated.caption) : [],
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_image': {
      const validated = CreateImageSchema.parse(args);
      const block = {
        type: 'image',
        image: {
          type: 'external',
          external: { url: validated.url },
          caption: validated.caption ? textToRichText(validated.caption) : [],
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_video': {
      const validated = CreateVideoSchema.parse(args);
      const block = {
        type: 'video',
        video: {
          type: 'external',
          external: { url: validated.url },
          caption: validated.caption ? textToRichText(validated.caption) : [],
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_embed': {
      const validated = CreateEmbedSchema.parse(args);
      const block = {
        type: 'embed',
        embed: {
          url: validated.url,
          caption: validated.caption ? textToRichText(validated.caption) : [],
        },
      };
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);
      return result;
    }

    case 'notion_create_table': {
      const validated = CreateTableSchema.parse(args);
      const block = {
        type: 'table',
        table: {
          table_width: validated.table_width,
          has_column_header: validated.has_column_header || false,
          has_row_header: validated.has_row_header || false,
        },
      };

      // First create the table
      const result = await client.appendBlockChildren(validated.parent_id as BlockId, [
        block as any,
      ]);

      // Then add rows if provided
      if (validated.rows && validated.rows.length > 0 && result.results.length > 0) {
        const tableId = result.results[0].id;
        const rowBlocks = validated.rows.map((row: string[]) => ({
          type: 'table_row',
          table_row: {
            cells: row.map((cell) => textToRichText(cell)),
          },
        }));
        await client.appendBlockChildren(tableId as BlockId, rowBlocks as any);
      }

      return result;
    }

    default:
      throw new Error(`Unknown block tool: ${toolName}`);
  }
}
