import { DateTime, Duration } from 'luxon';
import { Pin, PlanetWithInfo, AccessToken } from '@/types';
import { StorageInfo } from '@/types/planet';
import { WebhookConfig, WebhookPayload } from '@/types/webhook';
import { STORAGE_IDS, LAUNCHPAD_IDS, PI_TYPES_MAP, STORAGE_CAPACITIES, PI_PRODUCT_VOLUMES } from '@/const';
import { shouldSendWebhook, markWebhookSent, resetExtractorWebhookStates } from './webhookTracker';

const sendWebhook = async (payload: WebhookPayload): Promise<boolean> => {
  try {
    console.log('🔔 Sending webhook:', payload);
    const response = await fetch('/api/webhook', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
    });
    
    if (response.ok) {
      const result = await response.json();
      console.log('✅ Webhook sent successfully:', result.message);
    } else {
      const error = await response.text();
      console.log('❌ Webhook failed:', response.status, response.statusText, error);
    }
    
    return response.ok;
  } catch (error) {
    console.error('❌ Failed to send webhook:', error);
    return false;
  }
};

export const checkExtractorExpiry = async (
  character: AccessToken,
  planet: PlanetWithInfo,
  extractors: Pin[],
  config: WebhookConfig
): Promise<void> => {
  if (!config.enabled) return;

  if (extractors.length === 0) {
    console.log(`📊 No extractors found on ${planet.infoUniverse.name}`);
    return;
  }

  console.log(`⏰ Checking ${extractors.length} extractors on ${planet.infoUniverse.name}`);
  const now = DateTime.now();
  const expiryThreshold = Duration.fromISO(config.expiryThreshold);

  for (const extractor of extractors) {
    if (!extractor.expiry_time || !extractor.extractor_details?.product_type_id) continue;

    const expiryTime = DateTime.fromISO(extractor.expiry_time);
    const timeUntilExpiry = expiryTime.diff(now);
    const hoursRemaining = timeUntilExpiry.as('hours');
    
    const productType = PI_TYPES_MAP[extractor.extractor_details.product_type_id];
    const extractorType = productType?.name || `Type ${extractor.extractor_details.product_type_id}`;

    // Check if extractor has expired
    if (expiryTime <= now) {
      console.log(`⏰ Extractor expired: ${extractorType} on ${planet.infoUniverse.name}`);
      if (shouldSendWebhook(character.character.characterId, planet.planet_id, 'extractor_expired', extractor.pin_id)) {
        const payload: WebhookPayload = {
          type: 'extractor_expired',
          message: `Extractor producing ${extractorType} has expired on ${planet.infoUniverse.name}`,
          characterName: character.character.name,
          planetName: planet.infoUniverse.name,
          details: {
            extractorType,
            hoursRemaining: 0
          },
          timestamp: now.toISO()
        };

        if (await sendWebhook(payload)) {
          markWebhookSent(character.character.characterId, planet.planet_id, 'extractor_expired', extractor.pin_id);
        }
      }
    }
    // Check if extractor is about to expire
    else if (timeUntilExpiry <= expiryThreshold) {
      console.log(`⚠️ Extractor expiring soon: ${extractorType} on ${planet.infoUniverse.name} (${hoursRemaining.toFixed(1)}h remaining)`);
      if (shouldSendWebhook(character.character.characterId, planet.planet_id, 'extractor_expiring', extractor.pin_id)) {
        const payload: WebhookPayload = {
          type: 'extractor_expiring',
          message: `Extractor producing ${extractorType} will expire in ${hoursRemaining.toFixed(1)} hours on ${planet.infoUniverse.name}`,
          characterName: character.character.name,
          planetName: planet.infoUniverse.name,
          details: {
            extractorType,
            hoursRemaining: Math.max(0, hoursRemaining)
          },
          timestamp: now.toISO()
        };

        if (await sendWebhook(payload)) {
          markWebhookSent(character.character.characterId, planet.planet_id, 'extractor_expiring', extractor.pin_id);
        }
      }
    }
    // If extractor has been reset (duration is "full" again), reset webhook states
    else if (timeUntilExpiry > expiryThreshold.plus({ hours: 1 })) {
      resetExtractorWebhookStates(character.character.characterId, planet.planet_id, extractor.pin_id);
    }
  }
};

export const checkStorageCapacity = async (
  character: AccessToken,
  planet: PlanetWithInfo,
  storageInfo: StorageInfo[],
  config: WebhookConfig
): Promise<void> => {
  if (!config.enabled) return;

  if (storageInfo.length === 0) {
    console.log(`📦 No storage facilities found on ${planet.infoUniverse.name}`);
    return;
  }

  console.log(`📦 Checking ${storageInfo.length} storage facilities on ${planet.infoUniverse.name}`);
  const now = DateTime.now();

  for (const storage of storageInfo) {
    const fillPercentage = (storage.used / storage.capacity) * 100;
    const isLaunchpad = LAUNCHPAD_IDS.includes(storage.type_id);
    const storageTypeName = PI_TYPES_MAP[storage.type_id]?.name || `Storage ${storage.type_id}`;

    // Check for critical (100%) storage
    if (fillPercentage >= config.storageCriticalThreshold) {
      const webhookType = isLaunchpad ? 'launchpad_full' : 'storage_full';
      console.log(`🚨 ${storageTypeName} is ${fillPercentage.toFixed(1)}% full on ${planet.infoUniverse.name}`);
      
      if (shouldSendWebhook(character.character.characterId, planet.planet_id, webhookType, undefined, storage.type_id)) {
        const payload: WebhookPayload = {
          type: webhookType,
          message: `${storageTypeName} is ${fillPercentage.toFixed(1)}% full on ${planet.infoUniverse.name}`,
          characterName: character.character.name,
          planetName: planet.infoUniverse.name,
          details: {
            storageUsed: storage.used,
            storageCapacity: storage.capacity,
            fillPercentage: fillPercentage
          },
          timestamp: now.toISO()
        };

        if (await sendWebhook(payload)) {
          markWebhookSent(character.character.characterId, planet.planet_id, webhookType, undefined, storage.type_id);
        }
      }
    }
    // Check for warning threshold
    else if (fillPercentage >= config.storageWarningThreshold) {
      const webhookType = isLaunchpad ? 'launchpad_almost_full' : 'storage_almost_full';
      console.log(`⚠️ ${storageTypeName} is ${fillPercentage.toFixed(1)}% full on ${planet.infoUniverse.name}`);
      
      if (shouldSendWebhook(character.character.characterId, planet.planet_id, webhookType, undefined, storage.type_id)) {
        const payload: WebhookPayload = {
          type: webhookType,
          message: `${storageTypeName} is ${fillPercentage.toFixed(1)}% full on ${planet.infoUniverse.name}`,
          characterName: character.character.name,
          planetName: planet.infoUniverse.name,
          details: {
            storageUsed: storage.used,
            storageCapacity: storage.capacity,
            fillPercentage: fillPercentage
          },
          timestamp: now.toISO()
        };

        if (await sendWebhook(payload)) {
          markWebhookSent(character.character.characterId, planet.planet_id, webhookType, undefined, storage.type_id);
        }
      }
    }
  }
};

const calculateStorageInfo = (planet: PlanetWithInfo): StorageInfo[] => {
  const storageFacilities = planet.info.pins.filter((pin: Pin) => 
    STORAGE_IDS().some(storage => storage.type_id === pin.type_id)
  );

  return storageFacilities.map((storage: Pin): StorageInfo => {
    const storageType = PI_TYPES_MAP[storage.type_id]?.name || 'Unknown';
    const storageCapacity = STORAGE_CAPACITIES[storage.type_id] || 0;
    
    const totalVolume = (storage.contents || [])
      .reduce((sum: number, item) => {
        const volume = PI_PRODUCT_VOLUMES[item.type_id] || 0;
        return sum + (item.amount * volume);
      }, 0);

    const fillRate = storageCapacity > 0 ? (totalVolume / storageCapacity) * 100 : 0;

    return {
      type: storageType,
      type_id: storage.type_id,
      capacity: storageCapacity,
      used: totalVolume,
      fillRate: fillRate,
      value: 0 // We don't need value for webhook checks
    };
  });
};

export const runWebhookChecks = async (
  character: AccessToken,
  planet: PlanetWithInfo,
  extractors: Pin[],
  config: WebhookConfig
): Promise<void> => {
  if (!config.enabled) {
    console.log('🔕 Webhooks disabled, skipping checks');
    return;
  }

  console.log(`🔍 Running webhook checks for ${character.character.name} - ${planet.infoUniverse.name}`);
  const storageInfo = calculateStorageInfo(planet);

  await Promise.all([
    checkExtractorExpiry(character, planet, extractors, config),
    checkStorageCapacity(character, planet, storageInfo, config)
  ]);
};
