import { z } from 'zod';
import type { ToolRegistry } from '../server.js';
import type {
  Campaign,
  CampaignStatus,
  MetaPaginatedResponse,
  CreateCampaignParams,
  UpdateCampaignParams,
} from '../types/meta-api.js';

/**
 * Register campaign management tools
 */
export function registerCampaignTools(registry: ToolRegistry): void {
  const client = registry.getClient();

  // List campaigns
  registry.registerTool({
    name: 'list_campaigns',
    description: 'List campaigns with optional filters for status and date range',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      status: z.enum(['ACTIVE', 'PAUSED', 'DELETED', 'ARCHIVED']).optional().describe('Filter by campaign status'),
      limit: z.number().optional().describe('Maximum number of campaigns to return (default: 100)'),
    }),
    annotations: {
      title: 'List Campaigns',
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { account_id, status, limit } = args as { account_id: string; status?: CampaignStatus; limit?: number };
        
        const params: Record<string, unknown> = {
          fields: 'id,name,objective,status,effective_status,buying_type,bid_strategy,budget_remaining,daily_budget,lifetime_budget,start_time,stop_time,created_time,updated_time,special_ad_categories,spend_cap',
          limit: limit || 100,
        };

        if (status) {
          params.filtering = JSON.stringify([{ field: 'status', operator: 'EQUAL', value: status }]);
        }

        const response = await client.get<MetaPaginatedResponse<Campaign>>(
          `${account_id}/campaigns`,
          params
        );

        return {
          content: [{
            type: 'text',
            text: JSON.stringify(response.data, null, 2),
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Get campaign
  registry.registerTool({
    name: 'get_campaign',
    description: 'Get detailed information about a single campaign',
    inputSchema: z.object({
      campaign_id: z.string().describe('Campaign ID'),
    }),
    annotations: {
      title: 'Get Campaign',
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { campaign_id } = args as { campaign_id: string };
        
        const campaign = await client.get<Campaign>(campaign_id, {
          fields: 'id,name,account_id,objective,status,effective_status,buying_type,bid_strategy,budget_remaining,daily_budget,lifetime_budget,start_time,stop_time,created_time,updated_time,special_ad_categories,spend_cap',
        });

        return {
          content: [{
            type: 'text',
            text: JSON.stringify(campaign, null, 2),
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Create campaign
  registry.registerTool({
    name: 'create_campaign',
    description: 'Create a new campaign with specified objective, budget, schedule, and special ad categories',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      name: z.string().describe('Campaign name'),
      objective: z.enum([
        'OUTCOME_APP_PROMOTION',
        'OUTCOME_AWARENESS',
        'OUTCOME_ENGAGEMENT',
        'OUTCOME_LEADS',
        'OUTCOME_SALES',
        'OUTCOME_TRAFFIC',
      ] as const).describe('Campaign objective'),
      status: z.enum(['ACTIVE', 'PAUSED']).optional().describe('Initial campaign status (default: PAUSED)'),
      daily_budget: z.string().optional().describe('Daily budget in cents (e.g., "5000" for $50)'),
      lifetime_budget: z.string().optional().describe('Lifetime budget in cents (e.g., "10000" for $100)'),
      bid_strategy: z.enum(['LOWEST_COST_WITHOUT_CAP', 'LOWEST_COST_WITH_BID_CAP', 'COST_CAP', 'LOWEST_COST_WITH_MIN_ROAS']).optional().describe('Bid strategy'),
      special_ad_categories: z.array(z.string()).optional().describe('Special ad categories (e.g., ["CREDIT", "EMPLOYMENT"])'),
      start_time: z.string().optional().describe('Start time in ISO 8601 format'),
      stop_time: z.string().optional().describe('Stop time in ISO 8601 format'),
    }),
    annotations: {
      title: 'Create Campaign',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "write",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const params = args as unknown as CreateCampaignParams & { account_id: string };
        const { account_id, ...campaignParams } = params;
        
        const response = await client.post<{ id: string }>(
          `${account_id}/campaigns`,
          campaignParams as Record<string, unknown>
        );

        return {
          content: [{
            type: 'text',
            text: `Campaign created successfully: ${response.id}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Update campaign
  registry.registerTool({
    name: 'update_campaign',
    description: 'Modify campaign settings including name, budget, bid strategy, and schedule',
    inputSchema: z.object({
      campaign_id: z.string().describe('Campaign ID'),
      name: z.string().optional().describe('New campaign name'),
      status: z.enum(['ACTIVE', 'PAUSED', 'DELETED', 'ARCHIVED']).optional().describe('Campaign status'),
      daily_budget: z.string().optional().describe('Daily budget in cents'),
      lifetime_budget: z.string().optional().describe('Lifetime budget in cents'),
      bid_strategy: z.enum(['LOWEST_COST_WITHOUT_CAP', 'LOWEST_COST_WITH_BID_CAP', 'COST_CAP', 'LOWEST_COST_WITH_MIN_ROAS']).optional().describe('Bid strategy'),
      start_time: z.string().optional().describe('Start time in ISO 8601 format'),
      stop_time: z.string().optional().describe('Stop time in ISO 8601 format'),
      spend_cap: z.string().optional().describe('Spend cap in cents'),
    }),
    annotations: {
      title: 'Update Campaign',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "write",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { campaign_id, ...updateParams } = args as unknown as UpdateCampaignParams & { campaign_id: string };
        
        await client.post<{ success: boolean }>(
          campaign_id,
          updateParams as Record<string, unknown>
        );

        return {
          content: [{
            type: 'text',
            text: `Campaign ${campaign_id} updated successfully`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Toggle campaign
  registry.registerTool({
    name: 'toggle_campaign',
    description: 'Pause or resume a campaign',
    inputSchema: z.object({
      campaign_id: z.string().describe('Campaign ID'),
      status: z.enum(['ACTIVE', 'PAUSED']).describe('Target status: ACTIVE to resume, PAUSED to pause'),
    }),
    annotations: {
      title: 'Toggle Campaign',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { campaign_id, status } = args as { campaign_id: string; status: 'ACTIVE' | 'PAUSED' };
        
        await client.post<{ success: boolean }>(campaign_id, { status });

        return {
          content: [{
            type: 'text',
            text: `Campaign ${campaign_id} ${status === 'ACTIVE' ? 'resumed' : 'paused'} successfully`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Duplicate campaign
  registry.registerTool({
    name: 'duplicate_campaign',
    description: 'Clone a campaign with optional modifications to name, status, and budget',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      campaign_id: z.string().describe('Source campaign ID to duplicate'),
      new_name: z.string().optional().describe('Name for the duplicated campaign (default: "<original> - Copy")'),
      status: z.enum(['ACTIVE', 'PAUSED']).optional().describe('Status for new campaign (default: PAUSED)'),
      daily_budget: z.string().optional().describe('Override daily budget in cents'),
      lifetime_budget: z.string().optional().describe('Override lifetime budget in cents'),
    }),
    annotations: {
      title: 'Duplicate Campaign',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { account_id, campaign_id, new_name, status, daily_budget, lifetime_budget } = args as {
          account_id: string;
          campaign_id: string;
          new_name?: string;
          status?: CampaignStatus;
          daily_budget?: string;
          lifetime_budget?: string;
        };
        
        // Get original campaign
        const original = await client.get<Campaign>(campaign_id, {
          fields: 'name,objective,buying_type,bid_strategy,daily_budget,lifetime_budget,start_time,stop_time,special_ad_categories',
        });

        // Create duplicate
        const duplicateParams: CreateCampaignParams = {
          name: new_name || `${original.name} - Copy`,
          objective: original.objective,
          status: status || 'PAUSED',
          buying_type: original.buying_type,
          bid_strategy: original.bid_strategy,
          daily_budget: daily_budget || original.daily_budget,
          lifetime_budget: lifetime_budget || original.lifetime_budget,
          start_time: original.start_time,
          stop_time: original.stop_time,
          special_ad_categories: original.special_ad_categories,
        };

        const response = await client.post<{ id: string }>(
          `${account_id}/campaigns`,
          duplicateParams as unknown as Record<string, unknown>
        );

        return {
          content: [{
            type: 'text',
            text: `Campaign duplicated successfully. New campaign ID: ${response.id}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Delete campaign
  registry.registerTool({
    name: 'delete_campaign',
    description: 'Archive or delete a campaign (WARNING: This action may be irreversible)',
    inputSchema: z.object({
      campaign_id: z.string().describe('Campaign ID to delete'),
      confirm: z.literal(true).describe('Must be set to true to confirm deletion'),
    }),
    annotations: {
      title: 'Delete Campaign',
      readOnlyHint: false,
      destructiveHint: true,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "campaigns",
        access: "delete",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { campaign_id, confirm } = args as { campaign_id: string; confirm: boolean };
        
        if (!confirm) {
          return {
            content: [{
              type: 'text',
              text: 'Deletion not confirmed. Set confirm=true to proceed.',
            }],
            isError: true,
          };
        }

        await client.delete<{ success: boolean }>(campaign_id);

        return {
          content: [{
            type: 'text',
            text: `Campaign ${campaign_id} deleted successfully`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });
}
