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

// Zod schemas for input validation
const ListPagesSchema = z.object({
  page_size: z.number().min(1).max(100).optional(),
  start_cursor: z.string().optional(),
});

const GetPageSchema = z.object({
  page_id: z.string().describe('The ID of the page to retrieve'),
});

const CreatePageSchema = z.object({
  parent_type: z.enum(['database_id', 'page_id']).describe('Type of parent'),
  parent_id: z.string().describe('ID of the parent database or page'),
  properties: z.record(z.any()).describe('Page properties as JSON object'),
  icon_type: z.enum(['emoji', 'external']).optional(),
  icon_value: z.string().optional().describe('Emoji character or external URL'),
  cover_url: z.string().optional().describe('Cover image URL'),
  children: z.array(z.any()).optional().describe('Array of block objects to append'),
});

const UpdatePageSchema = z.object({
  page_id: z.string().describe('The ID of the page to update'),
  properties: z.record(z.any()).optional().describe('Properties to update'),
  icon_type: z.enum(['emoji', 'external']).optional(),
  icon_value: z.string().optional(),
  cover_url: z.string().optional(),
  archived: z.boolean().optional().describe('Whether to archive the page'),
});

const ArchivePageSchema = z.object({
  page_id: z.string().describe('The ID of the page to archive'),
});

const RestorePageSchema = z.object({
  page_id: z.string().describe('The ID of the page to restore from archive'),
});

const GetPagePropertySchema = z.object({
  page_id: z.string().describe('The ID of the page'),
  property_id: z.string().describe('The ID or name of the property to retrieve'),
  page_size: z.number().min(1).max(100).optional(),
  start_cursor: z.string().optional(),
});

export function getTools(client: NotionClient): Tool[] {
  return [
    {
      name: 'notion_get_page',
      description: 'Retrieve a Notion page by ID. Returns the page object with all properties, metadata, and parent information.',
      inputSchema: {
        type: 'object',
        properties: {
          page_id: { type: 'string', description: 'The ID of the page to retrieve' },
        },
        required: ['page_id'],
      },
    },
    {
      name: 'notion_create_page',
      description: 'Create a new page in a database or as a child of another page. Can include properties, icon, cover, and initial content blocks.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_type: {
            type: 'string',
            enum: ['database_id', 'page_id'],
            description: 'Type of parent (database_id or page_id)',
          },
          parent_id: {
            type: 'string',
            description: 'ID of the parent database or page',
          },
          properties: {
            type: 'object',
            description: 'Page properties as JSON object. For database pages, must match schema. For page children, typically just a title.',
          },
          icon_type: {
            type: 'string',
            enum: ['emoji', 'external'],
            description: 'Type of icon',
          },
          icon_value: {
            type: 'string',
            description: 'Emoji character (e.g., "🚀") or external image URL',
          },
          cover_url: {
            type: 'string',
            description: 'Cover image URL',
          },
          children: {
            type: 'array',
            description: 'Array of block objects to add as page content',
          },
        },
        required: ['parent_type', 'parent_id', 'properties'],
      },
    },
    {
      name: 'notion_update_page',
      description: 'Update page properties, icon, cover, or archive status. Only specified properties are modified.',
      inputSchema: {
        type: 'object',
        properties: {
          page_id: { type: 'string', description: 'The ID of the page to update' },
          properties: {
            type: 'object',
            description: 'Properties to update (partial update)',
          },
          icon_type: {
            type: 'string',
            enum: ['emoji', 'external'],
            description: 'Type of icon',
          },
          icon_value: {
            type: 'string',
            description: 'Emoji character or external image URL',
          },
          cover_url: {
            type: 'string',
            description: 'Cover image URL',
          },
          archived: {
            type: 'boolean',
            description: 'Whether to archive the page',
          },
        },
        required: ['page_id'],
      },
    },
    {
      name: 'notion_archive_page',
      description: 'Archive a page. Archived pages are hidden but not deleted and can be restored.',
      inputSchema: {
        type: 'object',
        properties: {
          page_id: { type: 'string', description: 'The ID of the page to archive' },
        },
        required: ['page_id'],
      },
    },
    {
      name: 'notion_restore_page',
      description: 'Restore an archived page, making it visible again.',
      inputSchema: {
        type: 'object',
        properties: {
          page_id: { type: 'string', description: 'The ID of the page to restore' },
        },
        required: ['page_id'],
      },
    },
    {
      name: 'notion_get_page_property',
      description: 'Retrieve a specific property item from a page. Useful for paginated properties like rollups or relations.',
      inputSchema: {
        type: 'object',
        properties: {
          page_id: { type: 'string', description: 'The ID of the page' },
          property_id: {
            type: 'string',
            description: 'The ID or name of the property to retrieve',
          },
          page_size: {
            type: 'number',
            description: 'Number of property items to return (max 100)',
          },
          start_cursor: {
            type: 'string',
            description: 'Cursor for pagination',
          },
        },
        required: ['page_id', 'property_id'],
      },
    },
  ];
}

export async function handlePageTool(
  toolName: string,
  args: any,
  client: NotionClient
): Promise<any> {
  switch (toolName) {
    case 'notion_get_page': {
      const validated = GetPageSchema.parse(args);
      const page = await client.getPage(validated.page_id as PageId);
      return page;
    }

    case 'notion_create_page': {
      const validated = CreatePageSchema.parse(args);
      const parent =
        validated.parent_type === 'database_id'
          ? { database_id: validated.parent_id as DatabaseId }
          : { page_id: validated.parent_id as PageId };

      let icon = undefined;
      if (validated.icon_type && validated.icon_value) {
        icon =
          validated.icon_type === 'emoji'
            ? { type: 'emoji' as const, emoji: validated.icon_value }
            : { type: 'external' as const, external: { url: validated.icon_value } };
      }

      let cover = undefined;
      if (validated.cover_url) {
        cover = { type: 'external' as const, external: { url: validated.cover_url } };
      }

      const page = await client.createPage({
        parent,
        properties: validated.properties as Record<string, Partial<PageProperty>>,
        icon,
        cover,
        children: validated.children as Block[] | undefined,
      });
      return page;
    }

    case 'notion_update_page': {
      const validated = UpdatePageSchema.parse(args);

      let icon = undefined;
      if (validated.icon_type && validated.icon_value) {
        icon =
          validated.icon_type === 'emoji'
            ? { type: 'emoji' as const, emoji: validated.icon_value }
            : { type: 'external' as const, external: { url: validated.icon_value } };
      }

      let cover = undefined;
      if (validated.cover_url) {
        cover = { type: 'external' as const, external: { url: validated.cover_url } };
      }

      const page = await client.updatePage(validated.page_id as PageId, {
        properties: validated.properties as Record<string, Partial<PageProperty>> | undefined,
        icon,
        cover,
        archived: validated.archived,
      });
      return page;
    }

    case 'notion_archive_page': {
      const validated = ArchivePageSchema.parse(args);
      const page = await client.updatePage(validated.page_id as PageId, {
        archived: true,
      });
      return page;
    }

    case 'notion_restore_page': {
      const validated = RestorePageSchema.parse(args);
      const page = await client.updatePage(validated.page_id as PageId, {
        archived: false,
      });
      return page;
    }

    case 'notion_get_page_property': {
      const validated = GetPagePropertySchema.parse(args);
      // Note: Notion API has a separate endpoint for property items
      // For now, we'll return the page and extract the property
      const page = await client.getPage(validated.page_id as PageId);
      const property = page.properties[validated.property_id];
      return { property, page_id: validated.page_id };
    }

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