"use client";
import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
import { memo, useCallback, useEffect, useState, Suspense } from "react";
import { AccessToken, CharacterUpdate, Env, PlanetWithInfo } from "../types";
import { MainGrid } from "./components/MainGrid";
import { refreshToken } from "@/esi-sso";
import {
  CharacterContext,
  ColorContext,
  ColorSelectionType,
  SessionContext,
  defaultColors,
} from "./context/Context";
import { useSearchParams } from "next/navigation";
import { EvePraisalResult, fetchAllPrices } from "@/eve-praisal";
import { getPlanet, getPlanetUniverse, getPlanets } from "@/planets";
import { PlanetConfig } from "@/types";
// Webhook service removed - using direct API calls
import { WebhookConfig } from "@/types/webhook";
import { cleanupOldWebhookStates } from "@/utils/webhookTracker";
import { planetCalculations } from "@/planets";

// Webhook check functions
const checkExtractorExpiry = async (character: any, planet: any, extractors: any[], config: WebhookConfig) => {
  if (!config.enabled || !config.zulipUrl) return;
  
  const now = new Date();
  const expiryThreshold = new Date(now.getTime() + 12 * 60 * 60 * 1000); // 12 hours from now
  
  for (const extractor of extractors) {
    if (extractor.expiry_time) {
      const expiryTime = new Date(extractor.expiry_time);
      if (expiryTime <= expiryThreshold) {
        const hoursRemaining = Math.round((expiryTime.getTime() - now.getTime()) / (1000 * 60 * 60));
        const message = `⚠️ Extractor ${extractor.type_name} expires in ${hoursRemaining} hours`;
        
        await fetch('/api/zulip-webhook', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            type: 'extractor_expiring',
            message,
            characterName: character.character.name,
            planetName: planet.infoUniverse.name,
            timestamp: now.toISOString(),
            zulipUrl: config.zulipUrl,
            zulipEmail: config.zulipEmail,
            zulipApiKey: config.zulipApiKey,
            zulipStream: config.zulipStream
          })
        });
      }
    }
  }
};

const checkStorageCapacity = async (character: any, planet: any, pins: any[], config: WebhookConfig) => {
  if (!config.enabled || !config.zulipUrl) return;
  
  // Import the storage constants
  const { STORAGE_IDS, STORAGE_CAPACITIES, PI_PRODUCT_VOLUMES } = await import('@/const');
  
  // Find storage facilities using the same logic as AccountCard
  const storageFacilities = pins.filter((pin: any) => 
    STORAGE_IDS().some((storage: any) => storage.type_id === pin.type_id)
  );

  for (const storage of storageFacilities) {
    const storageType = STORAGE_IDS().find((s: any) => s.type_id === storage.type_id)?.name;
    const storageCapacity = STORAGE_CAPACITIES[storage.type_id];
    
    const totalVolume = storage.contents
      .reduce((sum: number, item: any) => {
        const volume = PI_PRODUCT_VOLUMES[item.type_id];
        return sum + (item.amount * volume);
      }, 0);

    const fillPercentage = (totalVolume / storageCapacity) * 100;
    
    if (fillPercentage >= config.storageCriticalThreshold) {
      const message = `🚨 Storage ${storageType} is ${fillPercentage.toFixed(1)}% full!`;
      
      await fetch('/api/zulip-webhook', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          type: 'storage_full',
          message,
          characterName: character.character.name,
          planetName: planet.infoUniverse.name,
          timestamp: new Date().toISOString(),
          zulipUrl: config.zulipUrl,
          zulipEmail: config.zulipEmail,
          zulipApiKey: config.zulipApiKey,
          zulipStream: config.zulipStream
        })
      });
    } else if (fillPercentage >= config.storageWarningThreshold) {
      const message = `⚠️ Storage ${storageType} is ${fillPercentage.toFixed(1)}% full`;
      
      await fetch('/api/zulip-webhook', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          type: 'storage_almost_full',
          message,
          characterName: character.character.name,
          planetName: planet.infoUniverse.name,
          timestamp: new Date().toISOString(),
          zulipUrl: config.zulipUrl,
          zulipEmail: config.zulipEmail,
          zulipApiKey: config.zulipApiKey,
          zulipStream: config.zulipStream
        })
      });
    }
  }
};

// Add batch processing utility
const processInBatches = async <T, R>(
  items: T[],
  batchSize: number,
  processFn: (item: T) => Promise<R>
): Promise<R[]> => {
  const results: R[] = [];
  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    const batchResults = await Promise.all(batch.map(processFn));
    results.push(...batchResults);
  }
  return results;
};

const Home = () => {
  const searchParams = useSearchParams();
  const [characters, setCharacters] = useState<AccessToken[]>([]);
  const [sessionReady, setSessionReady] = useState(false);
  const [environment, setEnvironment] = useState<Env | undefined>(undefined);
  const [compactMode, setCompactMode] = useState(false);
  const [planMode, setPlanMode] = useState(false);
  const [piPrices, setPiPrices] = useState<EvePraisalResult | undefined>(
    undefined,
  );
  const [balanceThreshold, setBalanceThreshold] = useState(1000);
  const [showProductIcons, setShowProductIcons] = useState(false);
  const [extractionTimeMode, setExtractionTimeMode] = useState(false);
  const [webhookConfig, setWebhookConfig] = useState<WebhookConfig>(() => {
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem("webhookConfig");
      if (stored) {
        return JSON.parse(stored);
      }
    }
    return {
      enabled: false,
      expiryThreshold: 'P12H',
      storageWarningThreshold: 85,
      storageCriticalThreshold: 100
    };
  });
  const [webhookServerEnabled, setWebhookServerEnabled] = useState(false);

  const [colors, setColors] = useState<ColorSelectionType>(defaultColors);
  const [alertMode, setAlertMode] = useState(false);

  const deleteCharacter = (character: AccessToken) => {
    const charactersToSave = characters.filter(
      (c) => character.character.characterId !== c.character.characterId,
    );
    setCharacters(charactersToSave);
    saveCharacters(charactersToSave);
  };

  const updateCharacter = (
    character: AccessToken,
    updates: CharacterUpdate,
  ) => {
    const charactersToSave = characters.map((c) => {
      if (c.character.characterId === character.character.characterId)
        return {
          ...c,
          ...(updates.account ? { account: updates.account } : {}),
          ...(updates.comment ? { comment: updates.comment } : {}),
          ...(updates.system ? { system: updates.system } : {}),
        };
      return c;
    });
    setCharacters(charactersToSave);
    saveCharacters(charactersToSave);
  };

  const refreshSession = async (characters: AccessToken[]) => {
    return processInBatches(characters, 50, async (c) => {
      try {
        return await refreshToken(c);
      } catch {
        return { ...c, needsLogin: true };
      }
    });
  };

  const handleCallback = async (
    characters: AccessToken[],
  ): Promise<AccessToken[]> => {
    const code = searchParams?.get("code");
    if (code) {
      window.history.replaceState(null, "", "/");
      const res = await fetch(`api/token?code=${code}`);
      const newCharacter: AccessToken = await res.json();
      const oldCharacter = characters.find(
        (c) => c.character.characterId === newCharacter.character.characterId,
      );
      return [
        ...characters.filter(
          (c) => c.character.characterId !== newCharacter.character.characterId,
        ),
        { ...newCharacter, account: oldCharacter?.account ?? "-" },
      ];
    }
    return Promise.resolve(characters);
  };

  const initializeCharacters = useCallback((): AccessToken[] => {
    if (typeof window === 'undefined') return [];
    const localStorageCharacters = localStorage.getItem("characters");
    if (localStorageCharacters) {
      const characterArray: AccessToken[] = JSON.parse(localStorageCharacters);
      return characterArray.filter((c) => c.access_token && c.character);
    }
    return [];
  }, []);

  const initializeCharacterPlanets = (
    characters: AccessToken[],
  ): Promise<AccessToken[]> =>
    processInBatches(characters, 50, async (c) => {
      if (c.needsLogin || c.character === undefined)
        return { ...c, planets: [] };
      const planets = await getPlanets(c);
      const planetsWithInfo: PlanetWithInfo[] = await processInBatches(
        planets,
        3,
        async (p) => ({
          ...p,
          info: await getPlanet(c, p),
          infoUniverse: await getPlanetUniverse(p),
        })
        );
        
        // Run webhook checks for each planet if webhooks are enabled
        if (webhookConfig.enabled) {
          console.log(`🔍 Running webhook checks for ${c.character.name} (${planetsWithInfo.length} planets)`);
          for (const planet of planetsWithInfo) {
            try {
              const calculations = planetCalculations(planet);
              await checkExtractorExpiry(c, planet, calculations.extractors, webhookConfig);
              await checkStorageCapacity(c, planet, planet.info.pins, webhookConfig);
            } catch (error) {
              console.warn('Webhook check failed for planet:', planet.infoUniverse.name, error);
            }
          }
        }
        
        return {
        ...c,
        planets: planetsWithInfo,
      };
    });

  const saveCharacters = (characters: AccessToken[]): AccessToken[] => {
    if (typeof window !== 'undefined') {
      localStorage.setItem("characters", JSON.stringify(characters));
    }
    return characters;
  };

  const restoreCharacters = (characters: AccessToken[]) => {
    refreshSession(characters)
      .then(saveCharacters)
      .then(initializeCharacterPlanets)
      .then(setCharacters);
  };

  const toggleCompactMode = () => {
    setCompactMode(!compactMode);
  };

  const togglePlanMode = () => {
    setPlanMode(!planMode);
  };

  const toggleAlertMode = () => {
    setAlertMode(!alertMode);
  };

  const toggleExtractionTimeMode = () => {
    setExtractionTimeMode(!extractionTimeMode);
  };

  const updatePlanetConfig = (config: PlanetConfig) => {
    const charactersToSave = characters.map((c) => {
      if (c.character.characterId === config.characterId) {
        return {
          ...c,
          planetConfig: [
            ...c.planetConfig.filter((p) => p.planetId !== config.planetId),
            config,
          ],
        };
      }

      return c;
    });
    setCharacters(charactersToSave);
    saveCharacters(charactersToSave);
  };

  const readPlanetConfig = ({
    planetId,
    characterId,
  }: {
    planetId: number;
    characterId: number;
  }): PlanetConfig => {
    const defaultConfig = { planetId, characterId, excludeFromTotals: false };

    return (
      characters
        .find((c) => c.character.characterId === characterId)
        ?.planetConfig.find((p) => p.planetId === planetId) ?? defaultConfig
    );
  };

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const storedCompactMode = localStorage.getItem("compactMode");
      if (storedCompactMode) {
        setCompactMode(storedCompactMode === "true");
      }
    }
  }, []);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const storedColors = localStorage.getItem("colors");
      if (storedColors) {
        setColors(JSON.parse(storedColors));
      }
    }
  }, []);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const storedAlertMode = localStorage.getItem("alertMode");
      if (storedAlertMode) {
        setAlertMode(JSON.parse(storedAlertMode));
      }
    }
  }, []);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const storedBalanceThreshold = localStorage.getItem("balanceThreshold");
      if (storedBalanceThreshold) {
        setBalanceThreshold(parseInt(storedBalanceThreshold));
      }
    }
  }, []);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem("balanceThreshold", balanceThreshold.toString());
    }
  }, [balanceThreshold]);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem("compactMode", compactMode ? "true" : "false");
    }
  }, [compactMode]);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem("alertMode", alertMode ? "true" : "false");
    }
  }, [alertMode]);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem("colors", JSON.stringify(colors));
    }
  }, [colors]);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      const savedMode = localStorage.getItem('extractionTimeMode');
      if (savedMode) {
        setExtractionTimeMode(savedMode === 'true');
      }
    }
  }, []);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem('extractionTimeMode', extractionTimeMode.toString());
    }
  }, [extractionTimeMode]);

  // Load webhook config from localStorage after hydration
  useEffect(() => {
    if (typeof window !== 'undefined') {
      const savedWebhookConfig = localStorage.getItem("webhookConfig");
      if (savedWebhookConfig) {
        try {
          const config = JSON.parse(savedWebhookConfig);
          setWebhookConfig(prev => ({ ...prev, ...config }));
        } catch (error) {
          console.warn('Failed to parse webhook config from localStorage:', error);
        }
      }
    }
  }, []);

  // Save webhook config to localStorage
  useEffect(() => {
    if (typeof window !== 'undefined') {
      localStorage.setItem("webhookConfig", JSON.stringify(webhookConfig));
    }
  }, [webhookConfig]);


  useEffect(() => {
    console.log('🔧 Initializing app...');
    fetch("api/env")
      .then((r) => r.json())
      .then((env) => {
        console.log('🌐 Environment loaded:', env);
        setEnvironment({
          EVE_SSO_CLIENT_ID: env.EVE_SSO_CLIENT_ID,
          EVE_SSO_CALLBACK_URL: env.EVE_SSO_CALLBACK_URL,
        });
        setWebhookServerEnabled(env.WEBHOOK_ENABLED || false);
        console.log('🔔 Webhook server enabled:', env.WEBHOOK_ENABLED);
        // Only allow enabling webhooks if server supports it
        if (!env.WEBHOOK_ENABLED && webhookConfig.enabled) {
          console.log('⚠️ Disabling webhooks - server not configured');
          setWebhookConfig(prev => ({
            ...prev,
            enabled: false
          }));
        }
      })
      .then(initializeCharacters)
      .then(refreshSession)
      .then(handleCallback)
      .then(saveCharacters)
      .then(initializeCharacterPlanets)
      .then(setCharacters)
      .then(() => setSessionReady(true));
  }, []);

  useEffect(() => {
    fetchAllPrices()
      .then(setPiPrices)
      .catch(() => console.log("failed getting pi prices"));
  }, []);

  useEffect(() => {
    const ESI_CACHE_TIME_MS = 3000000;
    const interval = setInterval(() => {
      const characters = initializeCharacters();
      refreshSession(characters)
        .then(saveCharacters)
        .then(initializeCharacterPlanets)
        .then(setCharacters);
    }, ESI_CACHE_TIME_MS);
    return () => clearInterval(interval);
  });

  // Regular webhook checks (every minute)
  useEffect(() => {
    if (!webhookConfig.enabled) {
      console.log('🔕 Webhooks disabled, skipping regular checks');
      return;
    }

    console.log('⏰ Setting up regular webhook checks (every minute)');

    const runRegularWebhookChecks = async () => {
      console.log('🔄 Running regular webhook checks...');
      const currentCharacters = initializeCharacters();
      for (const character of currentCharacters) {
        if (character.needsLogin || !character.planets) continue;
        
        // Webhook checks removed
      }
      
      // Cleanup old webhook states
      cleanupOldWebhookStates();
    };

    // Run immediately
    runRegularWebhookChecks();

    // Set up interval for every minute
    const webhookInterval = setInterval(runRegularWebhookChecks, 60000);
    
    return () => clearInterval(webhookInterval);
  }, [webhookConfig.enabled]);

  return (
    <SessionContext.Provider
      value={{
        sessionReady,
        setSessionReady,
        refreshSession,
        EVE_SSO_CALLBACK_URL: environment?.EVE_SSO_CALLBACK_URL ?? "",
        EVE_SSO_CLIENT_ID: environment?.EVE_SSO_CLIENT_ID ?? "",
        compactMode,
        toggleCompactMode,
        planMode,
        togglePlanMode,
        piPrices,
        alertMode,
        toggleAlertMode,
        extractionTimeMode,
        toggleExtractionTimeMode,
        updatePlanetConfig,
        readPlanetConfig,
        balanceThreshold,
        setBalanceThreshold,
        showProductIcons,
        setShowProductIcons,
        webhookConfig,
        setWebhookConfig,
        webhookServerEnabled,
      }}
    >
      <CharacterContext.Provider
        value={{
          characters,
          deleteCharacter,
          updateCharacter,
          restoreCharacters,
        }}
      >
        <ColorContext.Provider value={{ colors: colors, setColors: setColors }}>
          <MainGrid />
        </ColorContext.Provider>
      </CharacterContext.Provider>
    </SessionContext.Provider>
  );
};

const HomeWrapper = () => (
  <Suspense>
    <Home />
  </Suspense>
);
HomeWrapper.displayName = 'HomeWrapper';

export default memo(HomeWrapper);
