import { z } from 'zod';
import type { AirtableClient } from '../clients/airtable.js';
import { BaseIdSchema, TableIdSchema, FieldIdSchema, FieldTypeSchema } from '../types/index.js';

/**
 * Fields Tools
 * 
 * Tools for managing fields (columns) in Airtable tables.
 */

export function getTools(client: AirtableClient) {
  return [
    // ========================================================================
    // List Fields
    // ========================================================================
    {
      name: 'airtable_list_fields',
      description:
        'List all fields in a table. Returns field metadata including ID, name, type, description, and type-specific options.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
      }),
      execute: async (args: { baseId: string; tableId: string }) => {
        const fields = await client.listFields(args.baseId as any, args.tableId as any);
        return {
          fields: fields.map((f) => ({
            id: f.id,
            name: f.name,
            type: f.type,
            description: f.description,
            hasOptions: !!f.options,
          })),
          count: fields.length,
        };
      },
    },

    // ========================================================================
    // Get Field
    // ========================================================================
    {
      name: 'airtable_get_field',
      description:
        'Get detailed information about a specific field including its full configuration and type-specific options.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        fieldId: FieldIdSchema.describe('The ID of the field (starts with fld).'),
      }),
      execute: async (args: { baseId: string; tableId: string; fieldId: string }) => {
        const field = await client.getField(
          args.baseId as any,
          args.tableId as any,
          args.fieldId
        );
        return field;
      },
    },

    // ========================================================================
    // Create Field
    // ========================================================================
    {
      name: 'airtable_create_field',
      description:
        'Create a new field in a table. Specify the field type and any required options. Different field types require different option configurations.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        name: z.string().describe('The name of the new field.'),
        type: FieldTypeSchema.describe(
          'Field type (e.g., singleLineText, number, singleSelect, multipleSelects, date, checkbox, etc.).'
        ),
        description: z
          .string()
          .optional()
          .describe('Optional description for the field.'),
        options: z
          .record(z.unknown())
          .optional()
          .describe(
            'Type-specific options. For singleSelect/multipleSelects: {choices: [{name: "Option1"}, ...]}, for number/currency: {precision: 2}, for rating: {icon: "star", max: 5}, etc.'
          ),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        name: string;
        type: string;
        description?: string;
        options?: Record<string, unknown>;
      }) => {
        const payload: Record<string, unknown> = {
          name: args.name,
          type: args.type,
        };
        if (args.description) payload.description = args.description;
        if (args.options) payload.options = args.options;

        const response = await (client as any).metaClient.post(
          `/bases/${args.baseId}/tables/${args.tableId}/fields`,
          payload
        );
        return response.data;
      },
    },

    // ========================================================================
    // Update Field
    // ========================================================================
    {
      name: 'airtable_update_field',
      description:
        'Update an existing field\'s name, description, or options. Note: Not all field properties can be updated after creation (e.g., changing field type has restrictions).',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        fieldId: FieldIdSchema.describe('The ID of the field to update (starts with fld).'),
        name: z.string().optional().describe('New name for the field.'),
        description: z
          .string()
          .optional()
          .describe('New description for the field.'),
        options: z
          .record(z.unknown())
          .optional()
          .describe('Updated type-specific options.'),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        fieldId: string;
        name?: string;
        description?: string;
        options?: Record<string, unknown>;
      }) => {
        const updates: Record<string, unknown> = {};
        if (args.name !== undefined) updates.name = args.name;
        if (args.description !== undefined) updates.description = args.description;
        if (args.options !== undefined) updates.options = args.options;

        const response = await (client as any).metaClient.patch(
          `/bases/${args.baseId}/tables/${args.tableId}/fields/${args.fieldId}`,
          updates
        );
        return response.data;
      },
    },

    // ========================================================================
    // Create Single Select Field (Convenience)
    // ========================================================================
    {
      name: 'airtable_create_single_select_field',
      description:
        'Convenience tool to create a single select field with predefined choices. Automatically formats the options object.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        name: z.string().describe('The name of the field.'),
        choices: z
          .array(
            z.object({
              name: z.string().describe('Choice name/label.'),
              color: z
                .string()
                .optional()
                .describe(
                  'Optional color (e.g., blueLight2, greenBright, redLight1).'
                ),
            })
          )
          .min(1)
          .describe('Array of choice options.'),
        description: z.string().optional().describe('Optional field description.'),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        name: string;
        choices: Array<{ name: string; color?: string }>;
        description?: string;
      }) => {
        const payload: Record<string, unknown> = {
          name: args.name,
          type: 'singleSelect',
          options: {
            choices: args.choices,
          },
        };
        if (args.description) payload.description = args.description;

        const response = await (client as any).metaClient.post(
          `/bases/${args.baseId}/tables/${args.tableId}/fields`,
          payload
        );
        return response.data;
      },
    },

    // ========================================================================
    // Create Multiple Selects Field (Convenience)
    // ========================================================================
    {
      name: 'airtable_create_multiple_selects_field',
      description:
        'Convenience tool to create a multiple selects field with predefined choices.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        name: z.string().describe('The name of the field.'),
        choices: z
          .array(
            z.object({
              name: z.string().describe('Choice name/label.'),
              color: z.string().optional().describe('Optional color.'),
            })
          )
          .min(1)
          .describe('Array of choice options.'),
        description: z.string().optional().describe('Optional field description.'),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        name: string;
        choices: Array<{ name: string; color?: string }>;
        description?: string;
      }) => {
        const payload: Record<string, unknown> = {
          name: args.name,
          type: 'multipleSelects',
          options: {
            choices: args.choices,
          },
        };
        if (args.description) payload.description = args.description;

        const response = await (client as any).metaClient.post(
          `/bases/${args.baseId}/tables/${args.tableId}/fields`,
          payload
        );
        return response.data;
      },
    },

    // ========================================================================
    // Create Number Field (Convenience)
    // ========================================================================
    {
      name: 'airtable_create_number_field',
      description:
        'Convenience tool to create a number field with optional precision.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        name: z.string().describe('The name of the field.'),
        precision: z
          .number()
          .min(0)
          .max(8)
          .optional()
          .describe('Number of decimal places (0-8). Default: 0 (integer).'),
        description: z.string().optional().describe('Optional field description.'),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        name: string;
        precision?: number;
        description?: string;
      }) => {
        const payload: Record<string, unknown> = {
          name: args.name,
          type: 'number',
        };
        if (args.precision !== undefined) {
          payload.options = { precision: args.precision };
        }
        if (args.description) payload.description = args.description;

        const response = await (client as any).metaClient.post(
          `/bases/${args.baseId}/tables/${args.tableId}/fields`,
          payload
        );
        return response.data;
      },
    },

    // ========================================================================
    // Create Currency Field (Convenience)
    // ========================================================================
    {
      name: 'airtable_create_currency_field',
      description:
        'Convenience tool to create a currency field with symbol and precision.',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        name: z.string().describe('The name of the field.'),
        symbol: z
          .string()
          .optional()
          .describe('Currency symbol (e.g., $, €, £). Default: $.'),
        precision: z
          .number()
          .min(0)
          .max(5)
          .optional()
          .describe('Number of decimal places (0-5). Default: 2.'),
        description: z.string().optional().describe('Optional field description.'),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        name: string;
        symbol?: string;
        precision?: number;
        description?: string;
      }) => {
        const payload: Record<string, unknown> = {
          name: args.name,
          type: 'currency',
          options: {
            symbol: args.symbol || '$',
            precision: args.precision !== undefined ? args.precision : 2,
          },
        };
        if (args.description) payload.description = args.description;

        const response = await (client as any).metaClient.post(
          `/bases/${args.baseId}/tables/${args.tableId}/fields`,
          payload
        );
        return response.data;
      },
    },

    // ========================================================================
    // Create Linked Record Field
    // ========================================================================
    {
      name: 'airtable_create_linked_record_field',
      description:
        'Create a field that links to records in another table (relationships).',
      inputSchema: z.object({
        baseId: BaseIdSchema.describe('The ID of the base (starts with app).'),
        tableId: TableIdSchema.describe('The ID of the table (starts with tbl).'),
        name: z.string().describe('The name of the field.'),
        linkedTableId: TableIdSchema.describe(
          'The ID of the table to link to (starts with tbl).'
        ),
        prefersSingleRecordLink: z
          .boolean()
          .optional()
          .describe(
            'If true, restricts to a single linked record. Default: false (allows multiple).'
          ),
        description: z.string().optional().describe('Optional field description.'),
      }),
      execute: async (args: {
        baseId: string;
        tableId: string;
        name: string;
        linkedTableId: string;
        prefersSingleRecordLink?: boolean;
        description?: string;
      }) => {
        const payload: Record<string, unknown> = {
          name: args.name,
          type: 'multipleRecordLinks',
          options: {
            linkedTableId: args.linkedTableId,
          },
        };
        if (args.prefersSingleRecordLink !== undefined) {
          (payload.options as any).prefersSingleRecordLink = args.prefersSingleRecordLink;
        }
        if (args.description) payload.description = args.description;

        const response = await (client as any).metaClient.post(
          `/bases/${args.baseId}/tables/${args.tableId}/fields`,
          payload
        );
        return response.data;
      },
    },
  ];
}
