import { logger } from '../../utils/logger';
import axios from 'axios';

interface TikTokAdCampaign {
  campaignId: string;
  name: string;
  objective: 'AWARENESS' | 'CONSIDERATION' | 'CONVERSIONS';
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'COMPLETED';
  budget: {
    daily: number;
    lifetime?: number;
    currency: string;
  };
  schedule: {
    startTime: number;
    endTime?: number;
  };
}

interface TikTokAdGroup {
  adGroupId: string;
  campaignId: string;
  name: string;
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED';
  targeting: {
    ageMin?: number;
    ageMax?: number;
    genders?: string[];
    locations?: string[];
    interests?: string[];
    behaviors?: string[];
  };
  budget: {
    daily: number;
    currency: string;
  };
  bidStrategy: 'LOWEST_COST' | 'TARGET_COST' | 'BID_CAP';
  bidAmount?: number;
}

interface TikTokAd {
  adId: string;
  adGroupId: string;
  name: string;
  status: 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'REJECTED';
  creative: {
    type: 'VIDEO' | 'IMAGE';
    mediaUrl: string;
    thumbnailUrl?: string;
    headline: string;
    description?: string;
    callToAction: string;
    landingPageUrl: string;
  };
}

interface TikTokAdPerformance {
  adId: string;
  dateRange: {
    start: string;
    end: string;
  };
  metrics: {
    impressions: number;
    clicks: number;
    ctr: number;
    spend: number;
    cpc: number;
    cpm: number;
    conversions: number;
    conversionRate: number;
    costPerConversion: number;
    roas: number;
  };
}

export class TikTokAdsConnector {
  platformCode = 'TIKTOK_ADS';
  capabilities = {
    hasApi: true,
    supportsCampaignCreate: true,
    supportsAdCreate: true,
    supportsPerformanceReport: true,
    supportsAutoOptimization: true
  };

  private apiBaseUrl = 'https://business-api.tiktok.com/open_api/v1.3';
  private appId = process.env.TIKTOK_ADS_APP_ID || '';
  private appSecret = process.env.TIKTOK_ADS_APP_SECRET || '';
  private accessToken = process.env.TIKTOK_ADS_ACCESS_TOKEN || '';

  async authorize(advertiserId: string): Promise<boolean> {
    logger.info(`[TikTokAdsConnector] Authorizing advertiser: ${advertiserId}`);
    
    if (!this.appId || this.appId === '') {
      logger.warn('[TikTokAdsConnector] No API credentials configured, using mock mode');
      return true;
    }

    try {
      const response = await axios.get(`${this.apiBaseUrl}/advertiser/info/`, {
        params: { advertiser_id: advertiserId },
        headers: { 'Access-Token': this.accessToken }
      });
      return response.data?.code === 0;
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Authorization failed: ${error.message}`);
      return false;
    }
  }

  async createCampaign(advertiserId: string, campaign: Partial<TikTokAdCampaign>): Promise<TikTokAdCampaign> {
    logger.info(`[TikTokAdsConnector] Creating campaign: ${campaign.name}`);

    if (!this.appId || this.appId === '') {
      return this.getMockCampaign(campaign);
    }

    try {
      const response = await axios.post(
        `${this.apiBaseUrl}/campaign/create/`,
        {
          advertiser_id: advertiserId,
          campaign_name: campaign.name,
          objective_type: campaign.objective || 'CONVERSIONS',
          budget_mode: campaign.budget?.lifetime ? 'BUDGET_MODE_TOTAL' : 'BUDGET_MODE_DAY',
          budget: campaign.budget?.lifetime || campaign.budget?.daily || 0,
          operation_status: 'ENABLE'
        },
        { headers: { 'Access-Token': this.accessToken } }
      );

      return {
        campaignId: response.data?.data?.campaign_id,
        name: campaign.name || '',
        objective: campaign.objective || 'CONVERSIONS',
        status: 'DRAFT',
        budget: campaign.budget || { daily: 0, currency: 'USD' },
        schedule: campaign.schedule || { startTime: Date.now() }
      };
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Create campaign failed: ${error.message}`);
      throw error;
    }
  }

  async createAdGroup(advertiserId: string, adGroup: Partial<TikTokAdGroup>): Promise<TikTokAdGroup> {
    logger.info(`[TikTokAdsConnector] Creating ad group: ${adGroup.name}`);

    if (!this.appId || this.appId === '') {
      return this.getMockAdGroup(adGroup);
    }

    try {
      const response = await axios.post(
        `${this.apiBaseUrl}/adgroup/create/`,
        {
          advertiser_id: advertiserId,
          campaign_id: adGroup.campaignId,
          adgroup_name: adGroup.name,
          budget_mode: 'BUDGET_MODE_DAY',
          budget: adGroup.budget?.daily || 20,
          bid_strategy: adGroup.bidStrategy || 'LOWEST_COST',
          target_audience: {
            age_range: adGroup.targeting?.ageMin ? [
              { min: adGroup.targeting.ageMin, max: adGroup.targeting.ageMax || 55 }
            ] : undefined,
            gender: adGroup.targeting?.genders,
            location_ids: adGroup.targeting?.locations
          }
        },
        { headers: { 'Access-Token': this.accessToken } }
      );

      return {
        adGroupId: response.data?.data?.adgroup_id,
        campaignId: adGroup.campaignId || '',
        name: adGroup.name || '',
        status: 'DRAFT',
        targeting: adGroup.targeting || {},
        budget: adGroup.budget || { daily: 20, currency: 'USD' },
        bidStrategy: adGroup.bidStrategy || 'LOWEST_COST'
      };
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Create ad group failed: ${error.message}`);
      throw error;
    }
  }

  async createAd(advertiserId: string, ad: Partial<TikTokAd>): Promise<TikTokAd> {
    logger.info(`[TikTokAdsConnector] Creating ad: ${ad.name}`);

    if (!this.appId || this.appId === '') {
      return this.getMockAd(ad);
    }

    try {
      const response = await axios.post(
        `${this.apiBaseUrl}/ad/create/`,
        {
          advertiser_id: advertiserId,
          adgroup_id: ad.adGroupId,
          creatives: [{
            creative_type: ad.creative?.type || 'VIDEO',
            video_url: ad.creative?.mediaUrl,
            title: ad.creative?.headline,
            description: ad.creative?.description,
            call_to_action: ad.creative?.callToAction,
            landing_page_url: ad.creative?.landingPageUrl
          }]
        },
        { headers: { 'Access-Token': this.accessToken } }
      );

      return {
        adId: response.data?.data?.ad_id,
        adGroupId: ad.adGroupId || '',
        name: ad.name || '',
        status: 'DRAFT',
        creative: ad.creative || {
          type: 'VIDEO',
          mediaUrl: '',
          headline: '',
          callToAction: 'SHOP_NOW',
          landingPageUrl: ''
        }
      };
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Create ad failed: ${error.message}`);
      throw error;
    }
  }

  async getPerformance(advertiserId: string, params: {
    adIds?: string[];
    campaignIds?: string[];
    startDate: string;
    endDate: string;
  }): Promise<TikTokAdPerformance[]> {
    logger.info(`[TikTokAdsConnector] Getting performance for advertiser: ${advertiserId}`);

    if (!this.appId || this.appId === '') {
      return this.getMockPerformance(params);
    }

    try {
      const response = await axios.get(`${this.apiBaseUrl}/report/integrated/get/`, {
        params: {
          advertiser_id: advertiserId,
          report_type: 'BASIC',
          data_level: 'AUCTION_AD',
          dimensions: ['ad_id'],
          metrics: ['impressions', 'clicks', 'spend', 'conversions', 'conversion_rate'],
          start_date: params.startDate,
          end_date: params.endDate,
          filtering: params.adIds ? [{ field: 'ad_ids', operator: 'IN', value: params.adIds }] : undefined
        },
        headers: { 'Access-Token': this.accessToken }
      });

      return (response.data?.data?.list || []).map((item: any) => ({
        adId: item.dimensions.ad_id,
        dateRange: { start: params.startDate, end: params.endDate },
        metrics: {
          impressions: item.metrics.impressions || 0,
          clicks: item.metrics.clicks || 0,
          ctr: item.metrics.click_rate || 0,
          spend: item.metrics.spend || 0,
          cpc: item.metrics.cost_per_click || 0,
          cpm: item.metrics.cost_per_mille || 0,
          conversions: item.metrics.conversions || 0,
          conversionRate: item.metrics.conversion_rate || 0,
          costPerConversion: item.metrics.cost_per_conversion || 0,
          roas: item.metrics.roas || 0
        }
      }));
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Get performance failed: ${error.message}`);
      return this.getMockPerformance(params);
    }
  }

  async updateCampaignStatus(campaignId: string, status: 'ACTIVE' | 'PAUSED'): Promise<boolean> {
    logger.info(`[TikTokAdsConnector] Updating campaign ${campaignId} status to ${status}`);
    
    if (!this.appId || this.appId === '') {
      return true;
    }

    try {
      await axios.post(
        `${this.apiBaseUrl}/campaign/status/update/`,
        {
          campaign_id: campaignId,
          operation_status: status === 'ACTIVE' ? 'ENABLE' : 'DISABLE'
        },
        { headers: { 'Access-Token': this.accessToken } }
      );
      return true;
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Update campaign status failed: ${error.message}`);
      return false;
    }
  }

  async getCampaigns(advertiserId: string): Promise<TikTokAdCampaign[]> {
    logger.info(`[TikTokAdsConnector] Getting campaigns for advertiser: ${advertiserId}`);
    
    if (!this.appId || this.appId === '') {
      return [
        {
          campaignId: 'TK_CAMP_001',
          name: 'Summer Sale Campaign',
          objective: 'CONVERSIONS',
          status: 'ACTIVE',
          budget: { daily: 100, currency: 'USD' },
          schedule: { startTime: Date.now() - 86400 * 7 }
        },
        {
          campaignId: 'TK_CAMP_002',
          name: 'Brand Awareness Q1',
          objective: 'AWARENESS',
          status: 'PAUSED',
          budget: { daily: 50, currency: 'USD' },
          schedule: { startTime: Date.now() - 86400 * 30 }
        }
      ];
    }

    try {
      const response = await axios.get(`${this.apiBaseUrl}/campaign/get/`, {
        params: { advertiser_id: advertiserId },
        headers: { 'Access-Token': this.accessToken }
      });
      return response.data?.data?.list || [];
    } catch (error: any) {
      logger.error(`[TikTokAdsConnector] Get campaigns failed: ${error.message}`);
      return [];
    }
  }

  private getMockCampaign(campaign: Partial<TikTokAdCampaign>): TikTokAdCampaign {
    return {
      campaignId: `TK_CAMP_${Date.now()}`,
      name: campaign.name || 'New Campaign',
      objective: campaign.objective || 'CONVERSIONS',
      status: 'DRAFT',
      budget: campaign.budget || { daily: 50, currency: 'USD' },
      schedule: campaign.schedule || { startTime: Date.now() }
    };
  }

  private getMockAdGroup(adGroup: Partial<TikTokAdGroup>): TikTokAdGroup {
    return {
      adGroupId: `TK_AG_${Date.now()}`,
      campaignId: adGroup.campaignId || '',
      name: adGroup.name || 'New Ad Group',
      status: 'DRAFT',
      targeting: adGroup.targeting || { ageMin: 18, ageMax: 44, locations: ['US'] },
      budget: adGroup.budget || { daily: 20, currency: 'USD' },
      bidStrategy: adGroup.bidStrategy || 'LOWEST_COST'
    };
  }

  private getMockAd(ad: Partial<TikTokAd>): TikTokAd {
    return {
      adId: `TK_AD_${Date.now()}`,
      adGroupId: ad.adGroupId || '',
      name: ad.name || 'New Ad',
      status: 'DRAFT',
      creative: ad.creative || {
        type: 'VIDEO',
        mediaUrl: 'https://example.com/video.mp4',
        headline: 'Shop Now',
        callToAction: 'SHOP_NOW',
        landingPageUrl: 'https://example.com/shop'
      }
    };
  }

  private getMockPerformance(params: { startDate: string; endDate: string; adIds?: string[] }): TikTokAdPerformance[] {
    const adIds = params.adIds || ['TK_AD_001', 'TK_AD_002'];
    
    return adIds.map(adId => ({
      adId,
      dateRange: { start: params.startDate, end: params.endDate },
      metrics: {
        impressions: Math.floor(Math.random() * 100000) + 10000,
        clicks: Math.floor(Math.random() * 5000) + 500,
        ctr: Math.random() * 5 + 1,
        spend: Math.random() * 500 + 50,
        cpc: Math.random() * 2 + 0.5,
        cpm: Math.random() * 10 + 2,
        conversions: Math.floor(Math.random() * 100) + 10,
        conversionRate: Math.random() * 5 + 1,
        costPerConversion: Math.random() * 20 + 5,
        roas: Math.random() * 5 + 1
      }
    }));
  }
}

export default TikTokAdsConnector;
