import { z } from 'zod'
import { createIntegrationTool } from '../../../tool'
import type { Tool } from '../../../../types'

// ============================================
// Core Methods - Direct API Operations
// ============================================

/**
 * Create Google Sheets read tool
 *
 * Reads data from a spreadsheet range using A1 notation.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that reads spreadsheet data
 *
 * @example
 * const readTool = createGoogleSheetsReadTool('elevasis-google-sheets')
 */
export function createGoogleSheetsReadTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_read',
    description: `Read data from a Google Sheets range. Returns 2D array of cell values.

USAGE:
Specify spreadsheet ID and range in A1 notation to retrieve cell values.

A1 NOTATION EXAMPLES:
- "Sheet1!A1:C10" - Cells A1 through C10 on Sheet1
- "Sheet1!A:A" - Entire column A on Sheet1
- "Sheet1!1:2" - Rows 1 and 2 on Sheet1
- "'Sheet Name'!A1:B2" - Sheet names with spaces need single quotes

OUTPUT:
Returns 2D array where each inner array is a row:
[["Name", "Id"], ["Alice", "1"], ["Bob", "2"]]

TIP: Get spreadsheet ID from URL:
https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/edit`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      range: z.string().describe('A1 notation range (e.g., "Sheet1!A1:C10")')
    }),

    outputSchema: z.object({
      values: z.array(z.array(z.string())).describe('2D array of cell values')
    }),

    integration: 'google-sheets' as const,
    method: 'readSheet' as const,
    credentialName
  })
}

/**
 * Create Google Sheets write tool
 *
 * Writes data to a spreadsheet range, overwriting existing data.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that writes spreadsheet data
 */
export function createGoogleSheetsWriteTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_write',
    description: `Write data to a Google Sheets range. Overwrites existing data in the range.

USAGE:
Provide 2D array of values to write to the specified range.

INPUT FORMAT:
Values must be a 2D array (array of rows):
[["Name", "Id"], ["Alice", "1"], ["Bob", "2"]]

FORMULAS:
Use USER_ENTERED format - formulas like "=SUM(A1:A10)" will execute.

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "range": "Sheet1!A1:B3",
  "values": [["Header1", "Header2"], ["Value1", "Value2"]]
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      range: z.string().describe('A1 notation range to write to'),
      values: z.array(z.array(z.string())).describe('2D array of values to write')
    }),

    outputSchema: z.object({
      updatedCells: z.number().describe('Number of cells updated')
    }),

    integration: 'google-sheets' as const,
    method: 'writeSheet' as const,
    credentialName
  })
}

/**
 * Create Google Sheets append tool
 *
 * Appends rows to the end of a table without overwriting existing data.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that appends rows to spreadsheet
 */
export function createGoogleSheetsAppendTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_append',
    description: `Append rows to the end of a Google Sheets table. Finds the first empty row and writes there.

USE CASES:
- Add new records to a data table
- Log entries to a tracking sheet
- Append items without knowing the last row

RANGE FORMAT:
Specify the table range (columns), e.g., "Sheet1!A:E" for a 5-column table.
The API finds the first empty row automatically.

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "range": "Sheet1!A:C",
  "values": [["NewItem", "123", "Description"]]
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      range: z.string().describe('Table range to append to (e.g., "Sheet1!A:E")'),
      values: z.array(z.array(z.string())).describe('Rows to append (2D array)')
    }),

    outputSchema: z.object({
      updatedRows: z.number().describe('Number of rows appended')
    }),

    integration: 'google-sheets' as const,
    method: 'appendRows' as const,
    credentialName
  })
}

/**
 * Create Google Sheets clear tool
 *
 * Clears values from a range while preserving formatting.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that clears spreadsheet range
 */
export function createGoogleSheetsClearTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_clear',
    description: `Clear all values from a Google Sheets range. Preserves formatting and data validation.

USE CASES:
- Clear data while keeping headers (e.g., clear A2:E100, keep row 1)
- Reset a section before writing new data
- Remove sensitive data while preserving structure

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "range": "Sheet1!A2:E100"
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      range: z.string().describe('A1 notation range to clear')
    }),

    outputSchema: z.object({
      clearedRange: z.string().describe('The range that was cleared')
    }),

    integration: 'google-sheets' as const,
    method: 'clearRange' as const,
    credentialName
  })
}

/**
 * Create Google Sheets metadata tool
 *
 * Gets spreadsheet metadata including title and list of sheets.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that retrieves spreadsheet metadata
 */
export function createGoogleSheetsMetadataTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_metadata',
    description: `Get spreadsheet metadata including title and list of sheets.

USE CASES:
- Discover available sheets before reading data
- Get sheet names for building ranges
- Verify spreadsheet access

OUTPUT:
Returns spreadsheet title and array of sheet info:
{
  "title": "My Spreadsheet",
  "sheets": [
    { "sheetId": 0, "title": "Sheet1", "index": 0 },
    { "sheetId": 123, "title": "Data", "index": 1 }
  ]
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL')
    }),

    outputSchema: z.object({
      title: z.string().describe('Spreadsheet title'),
      sheets: z.array(z.object({
        sheetId: z.number(),
        title: z.string(),
        index: z.number()
      })).describe('List of sheets in the spreadsheet')
    }),

    integration: 'google-sheets' as const,
    method: 'getSpreadsheetMetadata' as const,
    credentialName
  })
}

/**
 * Create Google Sheets batch update tool
 *
 * Updates multiple ranges in a single request for efficiency.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that batch updates spreadsheet
 */
export function createGoogleSheetsBatchUpdateTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_batch_update',
    description: `Update multiple ranges in a single request. More efficient than multiple write calls.

USE CASES:
- Update cells in multiple sheets at once
- Write to non-contiguous ranges
- Batch multiple small updates for efficiency

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "data": [
    { "range": "Sheet1!A1", "values": [["Updated"]] },
    { "range": "Sheet2!B2:C3", "values": [["X", "Y"], ["Z", "W"]] }
  ]
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      data: z.array(z.object({
        range: z.string().describe('A1 notation range'),
        values: z.array(z.array(z.string())).describe('2D array of values')
      })).describe('Array of range/values pairs to update')
    }),

    outputSchema: z.object({
      totalUpdatedCells: z.number().describe('Total number of cells updated'),
      totalUpdatedRows: z.number().describe('Total number of rows updated')
    }),

    integration: 'google-sheets' as const,
    method: 'batchUpdate' as const,
    credentialName
  })
}

// ============================================
// Workflow-Friendly Methods - Higher-Level Abstractions
// ============================================

/**
 * Create Google Sheets get headers tool
 *
 * Gets column headers from the first row of a sheet.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that retrieves headers
 */
export function createGoogleSheetsGetHeadersTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_get_headers',
    description: `Get column headers from the first row of a sheet.

USE CASES:
- Discover column structure before reading/writing
- Get column mapping for workflow operations
- Validate expected columns exist

OUTPUT:
Returns headers array and column map (header name to column letter):
{
  "headers": ["Name", "Id", "Description"],
  "columnCount": 3,
  "columnMap": { "Name": "A", "Id": "B", "Description": "C" }
}

TIP: Use columnMap to build ranges dynamically based on header names.`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name (e.g., "Sheet1")')
    }),

    outputSchema: z.object({
      headers: z.array(z.string()).describe('Column headers from first row'),
      columnCount: z.number().describe('Number of columns'),
      columnMap: z.record(z.string(), z.string()).describe('Map of header name to column letter')
    }),

    integration: 'google-sheets' as const,
    method: 'getHeaders' as const,
    credentialName
  })
}

/**
 * Create Google Sheets get last row tool
 *
 * Finds the last row with data in a column.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that finds last row
 */
export function createGoogleSheetsGetLastRowTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_get_last_row',
    description: `Find the last row with data in a sheet.

USE CASES:
- Determine where to write next row
- Check if sheet has any data
- Get row count for a column

OUTPUT:
{
  "lastRow": 50,
  "isEmpty": false
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name'),
      column: z.string().optional().describe('Column to check (default: "A")')
    }),

    outputSchema: z.object({
      lastRow: z.number().describe('Last row number with data'),
      isEmpty: z.boolean().describe('True if column is empty')
    }),

    integration: 'google-sheets' as const,
    method: 'getLastRow' as const,
    credentialName
  })
}

/**
 * Create Google Sheets find row tool
 *
 * Finds a row by searching for a value in a column.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that finds rows by value
 */
export function createGoogleSheetsFindRowTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_find_row',
    description: `Find a row by searching for a value in a specific column.

USE CASES:
- Look up a record by ID or name
- Find a row to update
- Check if a value exists in the sheet

OUTPUT (when found):
{
  "found": true,
  "rowNumber": 5,
  "rowData": ["John", "123", "john@example.com"],
  "headers": ["Name", "Id", "Email"]
}

OUTPUT (not found):
{
  "found": false,
  "rowNumber": null,
  "rowData": null,
  "headers": ["Name", "Id", "Email"]
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name'),
      searchColumn: z.string().describe('Column letter to search (e.g., "A", "B")'),
      searchValue: z.string().describe('Value to search for')
    }),

    outputSchema: z.object({
      found: z.boolean().describe('Whether the value was found'),
      rowNumber: z.number().nullable().describe('Row number if found'),
      rowData: z.array(z.string()).nullable().describe('Full row data if found'),
      headers: z.array(z.string()).describe('Column headers')
    }),

    integration: 'google-sheets' as const,
    method: 'getRowByValue' as const,
    credentialName
  })
}

/**
 * Create Google Sheets update row tool
 *
 * Updates a row found by searching for a value.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that updates rows by value
 */
export function createGoogleSheetsUpdateRowTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_update_row',
    description: `Update a row found by searching for a value in a column.

USE CASES:
- Update a record by ID
- Modify specific fields in a row
- Change status of an item

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "sheetName": "Sheet1",
  "searchColumn": "A",
  "searchValue": "John",
  "updates": { "Email": "newemail@example.com", "Status": "Active" }
}

NOTE: Updates use header names as keys, not column letters.`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name'),
      searchColumn: z.string().describe('Column letter to search'),
      searchValue: z.string().describe('Value to search for'),
      updates: z.record(z.string(), z.string()).describe('Map of header name to new value')
    }),

    outputSchema: z.object({
      found: z.boolean().describe('Whether the row was found'),
      rowNumber: z.number().nullable().describe('Row number if found'),
      updatedCells: z.number().describe('Number of cells updated')
    }),

    integration: 'google-sheets' as const,
    method: 'updateRowByValue' as const,
    credentialName
  })
}

/**
 * Create Google Sheets upsert row tool
 *
 * Inserts a new row or updates existing row based on key column.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that upserts rows
 */
export function createGoogleSheetsUpsertRowTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_upsert_row',
    description: `Insert or update a row based on a key column value.

BEHAVIOR:
- If key value exists: Updates the existing row
- If key value doesn't exist: Inserts a new row

USE CASES:
- Sync data where records may or may not exist
- Idempotent writes (safe to call multiple times)
- Create-or-update workflows

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "sheetName": "Sheet1",
  "keyColumn": "A",
  "keyValue": "user-123",
  "rowData": { "Name": "John", "Email": "john@example.com", "Status": "Active" }
}

OUTPUT:
{
  "action": "inserted" | "updated",
  "rowNumber": 10,
  "updatedCells": 3
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name'),
      keyColumn: z.string().describe('Column letter to match on'),
      keyValue: z.string().describe('Key value to find or create'),
      rowData: z.record(z.string(), z.string()).describe('Map of header name to value')
    }),

    outputSchema: z.object({
      action: z.enum(['inserted', 'updated']).describe('Whether row was inserted or updated'),
      rowNumber: z.number().describe('Row number'),
      updatedCells: z.number().describe('Number of cells written')
    }),

    integration: 'google-sheets' as const,
    method: 'upsertRow' as const,
    credentialName
  })
}

/**
 * Create Google Sheets filter rows tool
 *
 * Gets all rows matching a filter condition.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that filters rows
 */
export function createGoogleSheetsFilterRowsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_filter_rows',
    description: `Get all rows matching a filter condition.

OPERATORS:
- "equals" (default): Exact match
- "contains": Value contains the filter string
- "startsWith": Value starts with the filter string
- "endsWith": Value ends with the filter string

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "sheetName": "Sheet1",
  "filterColumn": "B",
  "filterValue": "Active",
  "operator": "equals"
}

OUTPUT:
{
  "rows": [
    { "rowNumber": 5, "data": ["John", "Active", "john@example.com"] },
    { "rowNumber": 8, "data": ["Jane", "Active", "jane@example.com"] }
  ],
  "matchCount": 2,
  "headers": ["Name", "Status", "Email"]
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name'),
      filterColumn: z.string().describe('Column letter to filter'),
      filterValue: z.string().describe('Value to filter by'),
      operator: z.enum(['equals', 'contains', 'startsWith', 'endsWith']).optional().describe('Filter operator (default: equals)')
    }),

    outputSchema: z.object({
      rows: z.array(z.object({
        rowNumber: z.number(),
        data: z.array(z.string())
      })).describe('Matching rows with row numbers'),
      matchCount: z.number().describe('Number of matching rows'),
      headers: z.array(z.string()).describe('Column headers')
    }),

    integration: 'google-sheets' as const,
    method: 'filterRows' as const,
    credentialName
  })
}

/**
 * Create Google Sheets delete row tool
 *
 * Deletes a row found by searching for a value.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that deletes rows by value
 */
export function createGoogleSheetsDeleteRowTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'google_sheets_delete_row',
    description: `Delete a row found by searching for a value in a column.

WARNING: This permanently removes the row. Other rows shift up.

USE CASES:
- Remove a record by ID
- Delete processed items
- Clean up test data

EXAMPLE:
{
  "spreadsheetId": "1abc...",
  "sheetName": "Sheet1",
  "searchColumn": "A",
  "searchValue": "user-to-delete"
}

OUTPUT:
{
  "found": true,
  "deletedRowNumber": 5
}`,

    inputSchema: z.object({
      spreadsheetId: z.string().describe('Spreadsheet ID from URL'),
      sheetName: z.string().describe('Sheet name'),
      searchColumn: z.string().describe('Column letter to search'),
      searchValue: z.string().describe('Value to search for')
    }),

    outputSchema: z.object({
      found: z.boolean().describe('Whether the row was found'),
      deletedRowNumber: z.number().nullable().describe('Row number that was deleted')
    }),

    integration: 'google-sheets' as const,
    method: 'deleteRowByValue' as const,
    credentialName
  })
}
