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

// Zod schemas
const GetDatabaseSchema = z.object({
  database_id: z.string().describe('The ID of the database'),
});

const CreateDatabaseSchema = z.object({
  parent_page_id: z.string().describe('ID of the parent page'),
  title: z.string().describe('Database title'),
  description: z.string().optional().describe('Database description'),
  properties: z.record(z.any()).describe('Database schema properties as JSON object'),
  icon_type: z.enum(['emoji', 'external']).optional(),
  icon_value: z.string().optional(),
  cover_url: z.string().optional(),
  is_inline: z.boolean().optional().describe('Whether database is inline'),
});

const UpdateDatabaseSchema = z.object({
  database_id: z.string().describe('The ID of the database to update'),
  title: z.string().optional().describe('New database title'),
  description: z.string().optional().describe('New description'),
  properties: z.record(z.any()).optional().describe('Properties to add or update'),
  icon_type: z.enum(['emoji', 'external']).optional(),
  icon_value: z.string().optional(),
  cover_url: z.string().optional(),
});

const QueryDatabaseSchema = z.object({
  database_id: z.string().describe('The ID of the database to query'),
  filter: z.any().optional().describe('Filter object (compound or property filters)'),
  sorts: z.array(z.any()).optional().describe('Array of sort objects'),
  page_size: z.number().min(1).max(100).optional().describe('Results per page (max 100)'),
  start_cursor: z.string().optional().describe('Pagination cursor'),
});

const QueryDatabaseAllSchema = z.object({
  database_id: z.string().describe('The ID of the database to query'),
  filter: z.any().optional().describe('Filter object'),
  sorts: z.array(z.any()).optional().describe('Array of sort objects'),
});

export function getTools(client: NotionClient): Tool[] {
  return [
    {
      name: 'notion_get_database',
      description: 'Retrieve a database by ID. Returns the database schema, properties, title, and metadata.',
      inputSchema: {
        type: 'object',
        properties: {
          database_id: { type: 'string', description: 'The ID of the database' },
        },
        required: ['database_id'],
      },
    },
    {
      name: 'notion_create_database',
      description: 'Create a new database as a child of a page. Define the schema with properties object.',
      inputSchema: {
        type: 'object',
        properties: {
          parent_page_id: { type: 'string', description: 'ID of the parent page' },
          title: { type: 'string', description: 'Database title' },
          description: { type: 'string', description: 'Database description' },
          properties: {
            type: 'object',
            description:
              'Database schema. Each key is property name, value is property config (type, options, etc.)',
          },
          icon_type: { type: 'string', enum: ['emoji', 'external'] },
          icon_value: { type: 'string', description: 'Emoji or external URL' },
          cover_url: { type: 'string', description: 'Cover image URL' },
          is_inline: {
            type: 'boolean',
            description: 'Whether database appears inline on page',
          },
        },
        required: ['parent_page_id', 'title', 'properties'],
      },
    },
    {
      name: 'notion_update_database',
      description: 'Update database title, description, icon, cover, or add/modify properties in the schema.',
      inputSchema: {
        type: 'object',
        properties: {
          database_id: { type: 'string', description: 'The ID of the database' },
          title: { type: 'string', description: 'New database title' },
          description: { type: 'string', description: 'New description' },
          properties: {
            type: 'object',
            description: 'Properties to add or update in schema',
          },
          icon_type: { type: 'string', enum: ['emoji', 'external'] },
          icon_value: { type: 'string' },
          cover_url: { type: 'string' },
        },
        required: ['database_id'],
      },
    },
    {
      name: 'notion_query_database',
      description:
        'Query a database with filters and sorting. Returns a paginated list of pages. Use filters for conditions and sorts for ordering.',
      inputSchema: {
        type: 'object',
        properties: {
          database_id: { type: 'string', description: 'The ID of the database' },
          filter: {
            type: 'object',
            description:
              'Filter object. Can be compound (and/or) or property filter. Example: {"property": "Status", "select": {"equals": "Done"}}',
          },
          sorts: {
            type: 'array',
            description:
              'Array of sort objects. Example: [{"property": "Created", "direction": "descending"}]',
          },
          page_size: {
            type: 'number',
            description: 'Number of results to return (max 100)',
          },
          start_cursor: { type: 'string', description: 'Pagination cursor' },
        },
        required: ['database_id'],
      },
    },
    {
      name: 'notion_query_database_all',
      description:
        'Query a database and retrieve ALL results (auto-paginating). Use for comprehensive queries without manual pagination.',
      inputSchema: {
        type: 'object',
        properties: {
          database_id: { type: 'string', description: 'The ID of the database' },
          filter: {
            type: 'object',
            description: 'Filter object (same format as notion_query_database)',
          },
          sorts: {
            type: 'array',
            description: 'Array of sort objects',
          },
        },
        required: ['database_id'],
      },
    },
  ];
}

export async function handleDatabaseTool(
  toolName: string,
  args: any,
  client: NotionClient
): Promise<any> {
  switch (toolName) {
    case 'notion_get_database': {
      const validated = GetDatabaseSchema.parse(args);
      const database = await client.getDatabase(validated.database_id as DatabaseId);
      return database;
    }

    case 'notion_create_database': {
      const validated = CreateDatabaseSchema.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 title = validated.description
        ? [
            { type: 'text' as const, text: { content: validated.title } },
          ]
        : [{ type: 'text' as const, text: { content: validated.title } }];

      const description = validated.description
        ? [{ type: 'text' as const, text: { content: validated.description } }]
        : undefined;

      const database = await client.createDatabase({
        parent: { page_id: validated.parent_page_id as PageId },
        title,
        properties: validated.properties as Record<string, DatabaseProperty>,
        icon,
        cover,
        is_inline: validated.is_inline,
      });
      return database;
    }

    case 'notion_update_database': {
      const validated = UpdateDatabaseSchema.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 updateParams: any = {};
      if (validated.title) {
        updateParams.title = [{ type: 'text', text: { content: validated.title } }];
      }
      if (validated.description !== undefined) {
        updateParams.description = [
          { type: 'text', text: { content: validated.description } },
        ];
      }
      if (validated.properties) {
        updateParams.properties = validated.properties;
      }
      if (icon) updateParams.icon = icon;
      if (cover) updateParams.cover = cover;

      const database = await client.updateDatabase(
        validated.database_id as DatabaseId,
        updateParams
      );
      return database;
    }

    case 'notion_query_database': {
      const validated = QueryDatabaseSchema.parse(args);
      const results = await client.queryDatabase({
        database_id: validated.database_id as DatabaseId,
        filter: validated.filter as Filter | undefined,
        sorts: validated.sorts as Sort[] | undefined,
        page_size: validated.page_size,
        start_cursor: validated.start_cursor,
      });
      return results;
    }

    case 'notion_query_database_all': {
      const validated = QueryDatabaseAllSchema.parse(args);
      const allPages = [];
      for await (const page of client.queryDatabaseAll({
        database_id: validated.database_id as DatabaseId,
        filter: validated.filter as Filter | undefined,
        sorts: validated.sorts as Sort[] | undefined,
      })) {
        allPages.push(page);
      }
      return { object: 'list', results: allPages, has_more: false, next_cursor: null };
    }

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