import { z } from 'zod';
import type { ToolRegistry } from '../server.js';
import type {
  Ad,
  AdCreative,
  AdStatus,
  MetaPaginatedResponse,
  ObjectStorySpec,
} from '../types/meta-api.js';

/**
 * Register ad and creative management tools
 */
export function registerAdTools(registry: ToolRegistry): void {
  const client = registry.getClient();

  // List ads
  registry.registerTool({
    name: 'list_ads',
    description: 'List ads by account, campaign, or ad set with optional status filters',
    inputSchema: z.object({
      parent_id: z.string().describe('Parent ID: ad account (act_XXXXX), campaign ID, or ad set ID'),
      parent_type: z.enum(['account', 'campaign', 'adset']).describe('Type of parent ID'),
      status: z.enum(['ACTIVE', 'PAUSED', 'DELETED', 'ARCHIVED']).optional().describe('Filter by ad status'),
      limit: z.number().optional().describe('Maximum number of ads to return (default: 100)'),
    }),
    annotations: {
      title: 'List Ads',
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { parent_id, status, limit } = args as {
          parent_id: string;
          parent_type: 'account' | 'campaign' | 'adset';
          status?: AdStatus;
          limit?: number;
        };
        
        const params: Record<string, unknown> = {
          fields: 'id,name,campaign_id,adset_id,status,effective_status,creative,created_time,updated_time,tracking_specs,conversion_specs',
          limit: limit || 100,
        };

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

        const endpoint = `${parent_id}/ads`;
        const response = await client.get<MetaPaginatedResponse<Ad>>(endpoint, 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 ad
  registry.registerTool({
    name: 'get_ad',
    description: 'Get detailed ad information including creative details',
    inputSchema: z.object({
      ad_id: z.string().describe('Ad ID'),
    }),
    annotations: {
      title: 'Get Ad',
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { ad_id } = args as { ad_id: string };
        
        const ad = await client.get<Ad>(ad_id, {
          fields: 'id,name,account_id,campaign_id,adset_id,status,effective_status,creative{id,name,body,title,image_url,video_id,thumbnail_url,object_story_spec},created_time,updated_time,tracking_specs',
        });

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

  // Create image ad
  registry.registerTool({
    name: 'create_image_ad',
    description: 'Create a single image ad with headline, body text, link, and call-to-action',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      adset_id: z.string().describe('Ad set ID to place this ad in'),
      name: z.string().describe('Ad name'),
      page_id: z.string().describe('Facebook Page ID'),
      image_hash: z.string().describe('Image hash (from upload_media)'),
      link: z.string().describe('Destination URL'),
      message: z.string().optional().describe('Ad body text'),
      headline: z.string().optional().describe('Ad headline'),
      description: z.string().optional().describe('Ad description'),
      call_to_action_type: z.enum(['LEARN_MORE', 'SHOP_NOW', 'SIGN_UP', 'DOWNLOAD', 'GET_QUOTE', 'CONTACT_US', 'APPLY_NOW', 'BOOK_TRAVEL', 'NO_BUTTON']).optional().describe('Call to action button type'),
      status: z.enum(['ACTIVE', 'PAUSED']).optional().describe('Initial ad status (default: PAUSED)'),
    }),
    annotations: {
      title: 'Create Image Ad',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "write",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const {
          account_id,
          adset_id,
          name,
          page_id,
          image_hash,
          link,
          message,
          headline,
          description,
          call_to_action_type,
          status,
        } = args as {
          account_id: string;
          adset_id: string;
          name: string;
          page_id: string;
          image_hash: string;
          link: string;
          message?: string;
          headline?: string;
          description?: string;
          call_to_action_type?: string;
          status?: AdStatus;
        };

        // First, create the creative
        const objectStorySpec: ObjectStorySpec = {
          page_id,
          link_data: {
            link,
            message,
            name: headline,
            description,
            image_hash,
            call_to_action: call_to_action_type
              ? { type: call_to_action_type }
              : undefined,
          },
        };

        const creativeResponse = await client.post<{ id: string }>(
          `${account_id}/adcreatives`,
          {
            name: `${name} - Creative`,
            object_story_spec: objectStorySpec,
          }
        );

        // Then create the ad
        const adResponse = await client.post<{ id: string }>(`${account_id}/ads`, {
          name,
          adset_id,
          creative: { creative_id: creativeResponse.id },
          status: status || 'PAUSED',
        });

        return {
          content: [{
            type: 'text',
            text: `Image ad created successfully. Ad ID: ${adResponse.id}, Creative ID: ${creativeResponse.id}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Create video ad
  registry.registerTool({
    name: 'create_video_ad',
    description: 'Create a video ad with headline, body text, and call-to-action',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      adset_id: z.string().describe('Ad set ID to place this ad in'),
      name: z.string().describe('Ad name'),
      page_id: z.string().describe('Facebook Page ID'),
      video_id: z.string().describe('Video ID (from upload_media)'),
      title: z.string().optional().describe('Video title'),
      message: z.string().optional().describe('Ad body text'),
      call_to_action_type: z.enum(['LEARN_MORE', 'SHOP_NOW', 'SIGN_UP', 'DOWNLOAD', 'WATCH_MORE', 'NO_BUTTON']).optional().describe('Call to action button type'),
      status: z.enum(['ACTIVE', 'PAUSED']).optional().describe('Initial ad status (default: PAUSED)'),
    }),
    annotations: {
      title: 'Create Video Ad',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "write",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const {
          account_id,
          adset_id,
          name,
          page_id,
          video_id,
          title,
          message,
          call_to_action_type,
          status,
        } = args as {
          account_id: string;
          adset_id: string;
          name: string;
          page_id: string;
          video_id: string;
          title?: string;
          message?: string;
          call_to_action_type?: string;
          status?: AdStatus;
        };

        const objectStorySpec: ObjectStorySpec = {
          page_id,
          video_data: {
            video_id,
            title,
            message,
            call_to_action: call_to_action_type
              ? { type: call_to_action_type }
              : undefined,
          },
        };

        const creativeResponse = await client.post<{ id: string }>(
          `${account_id}/adcreatives`,
          {
            name: `${name} - Creative`,
            object_story_spec: objectStorySpec,
          }
        );

        const adResponse = await client.post<{ id: string }>(`${account_id}/ads`, {
          name,
          adset_id,
          creative: { creative_id: creativeResponse.id },
          status: status || 'PAUSED',
        });

        return {
          content: [{
            type: 'text',
            text: `Video ad created successfully. Ad ID: ${adResponse.id}, Creative ID: ${creativeResponse.id}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Create carousel ad
  registry.registerTool({
    name: 'create_carousel_ad',
    description: 'Create a multi-card carousel ad with images or videos',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      adset_id: z.string().describe('Ad set ID to place this ad in'),
      name: z.string().describe('Ad name'),
      page_id: z.string().describe('Facebook Page ID'),
      message: z.string().optional().describe('Ad body text'),
      cards: z.array(z.object({
        image_hash: z.string().optional().describe('Image hash for this card'),
        video_id: z.string().optional().describe('Video ID for this card'),
        name: z.string().optional().describe('Card headline'),
        description: z.string().optional().describe('Card description'),
        link: z.string().describe('Card destination URL'),
        call_to_action_type: z.string().optional().describe('CTA button type'),
      })).describe('Carousel cards (2-10 cards)'),
      status: z.enum(['ACTIVE', 'PAUSED']).optional().describe('Initial ad status (default: PAUSED)'),
    }),
    annotations: {
      title: 'Create Carousel Ad',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "write",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { account_id, adset_id, name, page_id, message, cards, status } = args as {
          account_id: string;
          adset_id: string;
          name: string;
          page_id: string;
          message?: string;
          cards: Array<{
            image_hash?: string;
            video_id?: string;
            name?: string;
            description?: string;
            link: string;
            call_to_action_type?: string;
          }>;
          status?: AdStatus;
        };

        if (cards.length < 2 || cards.length > 10) {
          return {
            content: [{
              type: 'text',
              text: 'Carousel ads require between 2 and 10 cards',
            }],
            isError: true,
          };
        }

        const objectStorySpec: ObjectStorySpec = {
          page_id,
          link_data: {
            link: cards[0].link,
            message,
            child_attachments: cards.map(card => ({
              link: card.link,
              image_hash: card.image_hash,
              video_id: card.video_id,
              name: card.name,
              description: card.description,
              call_to_action: card.call_to_action_type
                ? { type: card.call_to_action_type }
                : undefined,
            })),
          },
        };

        const creativeResponse = await client.post<{ id: string }>(
          `${account_id}/adcreatives`,
          {
            name: `${name} - Creative`,
            object_story_spec: objectStorySpec,
          }
        );

        const adResponse = await client.post<{ id: string }>(`${account_id}/ads`, {
          name,
          adset_id,
          creative: { creative_id: creativeResponse.id },
          status: status || 'PAUSED',
        });

        return {
          content: [{
            type: 'text',
            text: `Carousel ad created successfully with ${cards.length} cards. Ad ID: ${adResponse.id}, Creative ID: ${creativeResponse.id}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Create dynamic ad
  registry.registerTool({
    name: 'create_dynamic_ad',
    description: 'Create a dynamic product catalog ad with asset feed',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      adset_id: z.string().describe('Ad set ID to place this ad in'),
      name: z.string().describe('Ad name'),
      page_id: z.string().describe('Facebook Page ID'),
      product_catalog_id: z.string().describe('Product catalog ID'),
      image_hashes: z.array(z.string()).optional().describe('Array of image hashes for dynamic creative'),
      titles: z.array(z.string()).optional().describe('Array of title variations'),
      descriptions: z.array(z.string()).optional().describe('Array of description variations'),
      link_url: z.string().describe('Destination URL'),
      call_to_action_types: z.array(z.string()).optional().describe('CTA variations'),
      status: z.enum(['ACTIVE', 'PAUSED']).optional().describe('Initial ad status (default: PAUSED)'),
    }),
    annotations: {
      title: 'Create Dynamic Ad',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "write",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const {
          account_id,
          adset_id,
          name,
          image_hashes,
          titles,
          descriptions,
          link_url,
          call_to_action_types,
          status,
        } = args as {
          account_id: string;
          adset_id: string;
          name: string;
          image_hashes?: string[];
          titles?: string[];
          descriptions?: string[];
          link_url: string;
          call_to_action_types?: string[];
          status?: AdStatus;
        };

        const assetFeedSpec = {
          images: image_hashes?.map(hash => ({ hash })),
          titles: titles?.map(text => ({ text })),
          descriptions: descriptions?.map(text => ({ text })),
          link_urls: [{ website_url: link_url }],
          call_to_action_types,
        };

        const creativeResponse = await client.post<{ id: string }>(
          `${account_id}/adcreatives`,
          {
            name: `${name} - Creative`,
            asset_feed_spec: assetFeedSpec,
          }
        );

        const adResponse = await client.post<{ id: string }>(`${account_id}/ads`, {
          name,
          adset_id,
          creative: { creative_id: creativeResponse.id },
          status: status || 'PAUSED',
        });

        return {
          content: [{
            type: 'text',
            text: `Dynamic ad created successfully. Ad ID: ${adResponse.id}, Creative ID: ${creativeResponse.id}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // Preview creative
  registry.registerTool({
    name: 'preview_creative',
    description: 'Generate preview URLs for an ad creative across different placements',
    inputSchema: z.object({
      creative_id: z.string().describe('Creative ID'),
      ad_format: z.enum([
        'DESKTOP_FEED_STANDARD',
        'MOBILE_FEED_STANDARD',
        'INSTAGRAM_STANDARD',
        'INSTAGRAM_STORY',
        'FACEBOOK_STORY_MOBILE',
        'RIGHT_COLUMN_STANDARD',
        'MESSENGER_MOBILE_INBOX_MEDIA',
        'AUDIENCE_NETWORK_OUTSTREAM_VIDEO',
      ]).optional().describe('Ad format/placement to preview (default: DESKTOP_FEED_STANDARD)'),
    }),
    annotations: {
      title: 'Preview Creative',
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { creative_id, ad_format } = args as { creative_id: string; ad_format?: string };
        
        const response = await client.get<{ data: Array<{ body: string }> }>(
          `${creative_id}/previews`,
          { ad_format: ad_format || 'DESKTOP_FEED_STANDARD' }
        );

        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,
        };
      }
    },
  });

  // Upload media (stub - actual implementation would need file handling)
  registry.registerTool({
    name: 'upload_media',
    description: 'Upload an image or video to the ad account (returns hash/ID for use in creatives). NOTE: This is a stub - actual file upload requires binary data handling.',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      file_path: z.string().describe('Path to image or video file'),
      media_type: z.enum(['image', 'video']).describe('Type of media to upload'),
    }),
    annotations: {
      title: 'Upload Media',
      readOnlyHint: false,
      destructiveHint: false,
      idempotentHint: false,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { account_id, file_path, media_type } = args as {
          account_id: string;
          file_path: string;
          media_type: 'image' | 'video';
        };

        // This is a stub. Real implementation would:
        // 1. Read file from file_path
        // 2. Call client.uploadMedia() with buffer
        // For now, return instructions
        return {
          content: [{
            type: 'text',
            text: `Upload stub for ${media_type} at ${file_path} to ${account_id}. Implement file reading and call client.uploadMedia(account_id, fileBuffer, filename, '${media_type}')`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`,
          }],
          isError: true,
        };
      }
    },
  });

  // List creatives
  registry.registerTool({
    name: 'list_creatives',
    description: 'List all ad creatives in an account',
    inputSchema: z.object({
      account_id: z.string().describe('Ad account ID (format: act_XXXXX)'),
      limit: z.number().optional().describe('Maximum number of creatives to return (default: 100)'),
    }),
    annotations: {
      title: 'List Creatives',
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
      openWorldHint: false,
    },
    _meta: {
      labels: {
        category: "general",
        access: "read",
        complexity: "simple"
      }
    },
    handler: async (args) => {
      try {
        const { account_id, limit } = args as { account_id: string; limit?: number };
        
        const response = await client.get<MetaPaginatedResponse<AdCreative>>(
          `${account_id}/adcreatives`,
          {
            fields: 'id,name,body,title,image_url,video_id,thumbnail_url,object_story_spec,status,effective_status',
            limit: limit || 100,
          }
        );

        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,
        };
      }
    },
  });
}
