import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { DateRange } from "react-day-picker";
import { subMonths } from "date-fns";
import { useMutation, useQuery } from "@tanstack/react-query";
import { motion } from "motion/react";

import { acotService } from "@/services/dashboard/acotService";
import { ConfigPanel } from "@/components/discount-simulator/ConfigPanel";
import { SummaryCard } from "@/components/discount-simulator/SummaryCard";
import { ResultsChart } from "@/components/discount-simulator/ResultsChart";
import { ResultsTable } from "@/components/discount-simulator/ResultsTable";
import {
  DiscountPromoOption,
  DiscountSimulationRequest,
  DiscountSimulationResponse,
  DiscountPromoType,
  ShippingPromoType,
  ShippingTierConfig,
  SurchargeConfig,
  CogsCalculationMode,
} from "@/types/discount-simulator";
import { toast } from "sonner";
import { toDateOnly } from "@/utils/businessTime";

const DEFAULT_POINT_VALUE = 0.005;
const DEFAULT_REDEMPTION_RATE = 0.9;
const DEFAULT_MERCHANT_FEE = 2.9;
const DEFAULT_FIXED_COST = 1.25;
const STORAGE_KEY = 'discount-simulator-config-v1';

const getDefaultDateRange = (): DateRange => ({
  from: subMonths(new Date(), 6),
  to: new Date(),
});

function ensureDateRange(range: DateRange): { from: Date; to: Date } {
  const from = range.from ?? subMonths(new Date(), 6);
  const to = range.to ?? new Date();
  return { from, to };
}

const defaultProductPromo = {
  type: 'none' as DiscountPromoType,
  value: 0,
  minSubtotal: 0,
};

const defaultShippingPromo = {
  type: 'none' as ShippingPromoType,
  value: 0,
  minSubtotal: 0,
  maxDiscount: 0,
};

export function DiscountSimulator() {
  const [dateRange, setDateRange] = useState<DateRange>(() => getDefaultDateRange());
  const [selectedPromoId, setSelectedPromoId] = useState<number | undefined>(undefined);
  const [productPromo, setProductPromo] = useState(defaultProductPromo);
  const [shippingPromo, setShippingPromo] = useState(defaultShippingPromo);
  const [shippingTiers, setShippingTiers] = useState<ShippingTierConfig[]>([]);
  const [surcharges, setSurcharges] = useState<SurchargeConfig[]>([]);
  const [merchantFeePercent, setMerchantFeePercent] = useState(DEFAULT_MERCHANT_FEE);
  const [fixedCostPerOrder, setFixedCostPerOrder] = useState(DEFAULT_FIXED_COST);
  const [cogsCalculationMode, setCogsCalculationMode] = useState<CogsCalculationMode>('actual');
  const [applyHistoricalProductPromo, setApplyHistoricalProductPromo] = useState(false);
  const [pointDollarValue, setPointDollarValue] = useState(DEFAULT_POINT_VALUE);
  const [pointDollarTouched, setPointDollarTouched] = useState(false);
  const [redemptionRate, setRedemptionRate] = useState(DEFAULT_REDEMPTION_RATE);
  const [simulationResult, setSimulationResult] = useState<DiscountSimulationResponse | undefined>(undefined);
  const [baselineResult, setBaselineResult] = useState<DiscountSimulationResponse | undefined>(undefined);
  const [isSimulating, setIsSimulating] = useState(false);
  const [hasLoadedConfig, setHasLoadedConfig] = useState(false);
  const [loadedFromStorage, setLoadedFromStorage] = useState(false);
  const skipAutoRunRef = useRef(false);
  const latestPayloadKeyRef = useRef('');
  const pendingCountRef = useRef(0);

  const promoDateBounds = useMemo(() => {
    const { from, to } = ensureDateRange(dateRange);
    return {
      // Date-only strings = business dates; the server resolves bounds.
      startDate: toDateOnly(from),
      endDate: toDateOnly(to),
    };
  }, [dateRange]);

  const promosQuery = useQuery<DiscountPromoOption[]>({
    queryKey: ['discount-promos', promoDateBounds.startDate, promoDateBounds.endDate],
    queryFn: async () => {
      const response = await acotService.getDiscountPromos(promoDateBounds) as { promos?: Array<Record<string, unknown>> };
      const rawList = Array.isArray(response?.promos)
        ? response.promos
        : [];
      const list: DiscountPromoOption[] = rawList.map((promo) => {

        const idValue = promo.id ?? promo.promo_id ?? 0;
        const codeValue = promo.code ?? promo.promo_code ?? '';
        const descriptionValue =
          (promo.description as string | undefined) ||
          (promo.promo_description_online as string | undefined) ||
          (promo.promo_description_private as string | undefined) ||
          (promo.description_online as string | undefined) ||
          (promo.description_private as string | undefined) ||
          (typeof codeValue === 'string' ? codeValue : '');
        const privateDescriptionValue =
          (promo.privateDescription as string | undefined) ||
          (promo.promo_description_private as string | undefined) ||
          (promo.description_private as string | undefined) ||
          '';

        const dateStartValue = (promo.dateStart as string | undefined) || (promo.date_start as string | undefined) || null;
        const dateEndValue = (promo.dateEnd as string | undefined) || (promo.date_end as string | undefined) || null;
        const usageValue = promo.usageCount ?? promo.usage_count ?? 0;

        return {
          id: Number(idValue) || 0,
          code: typeof codeValue === 'string' ? codeValue : '',
          description: descriptionValue ?? '',
          privateDescription: privateDescriptionValue,
          dateStart: dateStartValue,
          dateEnd: dateEndValue,
          usageCount: Number(usageValue) || 0,
        };
      });
      return list;
    },
  });

  const promosLoading = !promosQuery.data && promosQuery.isLoading;

  const createPayload = useCallback((): DiscountSimulationRequest => {
    const { from, to } = ensureDateRange(dateRange);

    const payloadPointsConfig = {
      pointsPerDollar: null,
      redemptionRate,
      pointDollarValue,
    };

    return {
      dateRange: {
        start: toDateOnly(from),
        end: toDateOnly(to),
      },
      filters: {
        shipCountry: 'US',
        promoIds: selectedPromoId ? [selectedPromoId] : undefined,
      },
      productPromo,
      shippingPromo,
      shippingTiers: shippingTiers.map((tier) => {
        const { id, ...rest } = tier;
        void id;
        return rest;
      }),
      surcharges: surcharges.map((surcharge) => {
        const { id, ...rest } = surcharge;
        void id;
        return rest;
      }),
      merchantFeePercent,
      fixedCostPerOrder,
      cogsCalculationMode,
      applyHistoricalProductPromo,
      pointsConfig: payloadPointsConfig,
    };
  }, [
    dateRange,
    selectedPromoId,
    productPromo,
    shippingPromo,
    shippingTiers,
    surcharges,
    merchantFeePercent,
    fixedCostPerOrder,
    cogsCalculationMode,
    applyHistoricalProductPromo,
    pointDollarValue,
    redemptionRate,
  ]);

  const simulationMutation = useMutation<
    DiscountSimulationResponse,
    unknown,
    DiscountSimulationRequest
  >({
    mutationKey: ['discount-simulation'],
    mutationFn: async (payload: DiscountSimulationRequest) => {
      const response = await acotService.simulateDiscounts(payload);
      return response as DiscountSimulationResponse;
    },
    onMutate: () => {
      pendingCountRef.current += 1;
      setIsSimulating(true);
    },
    onSuccess: (data, variables) => {
      const payloadKey = JSON.stringify(variables);
      if (payloadKey !== latestPayloadKeyRef.current) {
        return;
      }

      setSimulationResult(data);

      if (!pointDollarTouched && typeof data.totals.pointDollarValue === 'number') {
        const incomingValue = data.totals.pointDollarValue;
        if (pointDollarValue !== incomingValue) {
          skipAutoRunRef.current = true;
          setPointDollarValue(incomingValue);
        } else {
          skipAutoRunRef.current = false;
        }
      }
    },
    onError: (error) => {
      console.error('Simulation error', error);
      toast.error('Simulation failed', {
        description: error instanceof Error ? error.message : 'Unable to run discount simulation right now.',
      });
    },
    onSettled: () => {
      pendingCountRef.current = Math.max(0, pendingCountRef.current - 1);
      if (pendingCountRef.current === 0) {
        setIsSimulating(false);
      }
    },
  });

  const { mutate } = simulationMutation;

  const runSimulation = useCallback((overridePayload?: DiscountSimulationRequest) => {
    const payload = overridePayload ?? createPayload();
    latestPayloadKeyRef.current = JSON.stringify(payload);
    mutate(payload);
  }, [createPayload, mutate]);

  useEffect(() => {
    if (typeof window === 'undefined') {
      setHasLoadedConfig(true);
      return;
    }

    const raw = window.localStorage.getItem(STORAGE_KEY);
    if (!raw) {
      setHasLoadedConfig(true);
      return;
    }

    try {
      const parsed = JSON.parse(raw) as {
        dateRange?: { start?: string | null; end?: string | null };
        selectedPromoId?: number | null;
        productPromo?: typeof defaultProductPromo;
        shippingPromo?: typeof defaultShippingPromo;
        shippingTiers?: ShippingTierConfig[];
        surcharges?: SurchargeConfig[];
        merchantFeePercent?: number;
        fixedCostPerOrder?: number;
        cogsCalculationMode?: CogsCalculationMode;
        applyHistoricalProductPromo?: boolean;
        pointsConfig?: {
          pointsPerDollar?: number | null;
          redemptionRate?: number | null;
          pointDollarValue?: number | null;
        };
        pointDollarValue?: number;
        redemptionRate?: number;
      };

      skipAutoRunRef.current = true;

      if (parsed.dateRange) {
        const defaultRange = getDefaultDateRange();
        // Saved values may be date-only ('YYYY-MM-DD') or legacy ISO instants.
        // Parse date-only as LOCAL (bare new Date() would treat it as UTC and
        // show the previous day in US zones).
        const parseSaved = (value: string) =>
          /^\d{4}-\d{2}-\d{2}$/.test(value) ? new Date(`${value}T00:00:00`) : new Date(value);
        const fromValue = parsed.dateRange.start ? parseSaved(parsed.dateRange.start) : undefined;
        const toValue = parsed.dateRange.end ? parseSaved(parsed.dateRange.end) : undefined;
        setDateRange({
          from: fromValue ?? defaultRange.from,
          to: toValue ?? defaultRange.to,
        });
      }

      if (typeof parsed.selectedPromoId === 'number') {
        setSelectedPromoId(parsed.selectedPromoId);
      } else if (parsed.selectedPromoId === null) {
        setSelectedPromoId(undefined);
      }

      if (parsed.productPromo) {
        setProductPromo(parsed.productPromo);
      }

      if (parsed.shippingPromo) {
        setShippingPromo(parsed.shippingPromo);
      }

      if (Array.isArray(parsed.shippingTiers)) {
        setShippingTiers(parsed.shippingTiers);
      }

      if (Array.isArray(parsed.surcharges)) {
        setSurcharges(parsed.surcharges);
      }

      if (typeof parsed.merchantFeePercent === 'number') {
        setMerchantFeePercent(parsed.merchantFeePercent);
      }

      if (typeof parsed.fixedCostPerOrder === 'number') {
        setFixedCostPerOrder(parsed.fixedCostPerOrder);
      }

      if (parsed.cogsCalculationMode === 'actual' || parsed.cogsCalculationMode === 'average') {
        setCogsCalculationMode(parsed.cogsCalculationMode);
      }

      if (typeof parsed.applyHistoricalProductPromo === 'boolean') {
        setApplyHistoricalProductPromo(parsed.applyHistoricalProductPromo);
      }

      if (parsed.pointsConfig && typeof parsed.pointsConfig.pointDollarValue === 'number') {
        setPointDollarValue(parsed.pointsConfig.pointDollarValue);
        setPointDollarTouched(true);
      }

      if (typeof parsed.pointDollarValue === 'number') {
        setPointDollarValue(parsed.pointDollarValue);
        setPointDollarTouched(true);
      }

      if (typeof parsed.redemptionRate === 'number') {
        setRedemptionRate(parsed.redemptionRate);
      }

      setLoadedFromStorage(true);
    } catch (error) {
      console.error('Failed to load discount simulator config', error);
      skipAutoRunRef.current = false;
    } finally {
      setHasLoadedConfig(true);
    }
  }, []);

  const handleConfigInputChange = useCallback(() => {
    skipAutoRunRef.current = true;
  }, []);

  const serializedConfig = useMemo(() => {
    const { from, to } = ensureDateRange(dateRange);
    return JSON.stringify({
      dateRange: {
        start: toDateOnly(from),
        end: toDateOnly(to),
      },
      selectedPromoId: selectedPromoId ?? null,
      productPromo,
      shippingPromo,
      shippingTiers,
      surcharges,
      merchantFeePercent,
      fixedCostPerOrder,
      cogsCalculationMode,
      applyHistoricalProductPromo,
      pointDollarValue,
      redemptionRate,
    });
  }, [dateRange, selectedPromoId, productPromo, shippingPromo, shippingTiers, surcharges, merchantFeePercent, fixedCostPerOrder, cogsCalculationMode, applyHistoricalProductPromo, pointDollarValue, redemptionRate]);

  useEffect(() => {
    if (!hasLoadedConfig) {
      return;
    }

    if (typeof window === 'undefined') {
      return;
    }

    window.localStorage.setItem(STORAGE_KEY, serializedConfig);
  }, [serializedConfig, hasLoadedConfig]);

  useEffect(() => {
    if (skipAutoRunRef.current) {
      skipAutoRunRef.current = false;
      return;
    }

    runSimulation();
  }, [serializedConfig, runSimulation]);

  useEffect(() => {
    if (!loadedFromStorage) {
      return;
    }

    if (typeof window === 'undefined') {
      skipAutoRunRef.current = false;
      runSimulation();
      return;
    }

    const timeoutId = window.setTimeout(() => {
      skipAutoRunRef.current = false;
      runSimulation();
    }, 0);

    return () => window.clearTimeout(timeoutId);
  }, [loadedFromStorage, runSimulation]);

  const currentPointsPerDollar = simulationResult?.totals?.pointsPerDollar ?? 0;
  const recommendedPointDollarValue = simulationResult?.totals?.pointDollarValue;

  const handlePointDollarValueChange = (value: number) => {
    setPointDollarTouched(true);
    setPointDollarValue(value);
  };

  const handleApplyRecommendedPointValue = () => {
    if (typeof recommendedPointDollarValue === 'number') {
      setPointDollarValue(recommendedPointDollarValue);
      setPointDollarTouched(true);
    }
  };

  const handleSaveAsBaseline = useCallback(() => {
    if (simulationResult) {
      setBaselineResult(simulationResult);
    }
  }, [simulationResult]);

  const handleClearBaseline = useCallback(() => {
    setBaselineResult(undefined);
  }, []);

  const resetConfig = useCallback(() => {
    skipAutoRunRef.current = true;
    const defaultRange = getDefaultDateRange();

    setDateRange(defaultRange);
    setSelectedPromoId(undefined);
    setProductPromo(defaultProductPromo);
    setShippingPromo(defaultShippingPromo);
    setShippingTiers([]);
    setSurcharges([]);
    setMerchantFeePercent(DEFAULT_MERCHANT_FEE);
    setFixedCostPerOrder(DEFAULT_FIXED_COST);
    setCogsCalculationMode('actual');
    setApplyHistoricalProductPromo(false);
    setPointDollarValue(DEFAULT_POINT_VALUE);
    setPointDollarTouched(false);
    setRedemptionRate(DEFAULT_REDEMPTION_RATE);
    setSimulationResult(undefined);

    if (typeof window !== 'undefined') {
      window.localStorage.removeItem(STORAGE_KEY);
      window.setTimeout(() => {
        skipAutoRunRef.current = false;
        runSimulation();
      }, 0);
    } else {
      skipAutoRunRef.current = false;
      runSimulation();
    }
  }, [runSimulation]);

  const promos = promosQuery.data ?? [];

  const isLoading = isSimulating && !simulationResult;

  return (
    <motion.div layout className="flex-1 p-8 pt-6">
      <div className="flex flex-col gap-4 mb-6">
        <h1 className="text-3xl font-bold">Discount Simulator</h1>
      </div>

      <div className="grid gap-4 md:grid-cols-[300px,1fr] lg:grid-cols-[340px,1fr]">
        {/* Left Sidebar - Configuration */}
        <div className="space-y-4">
          <ConfigPanel
            dateRange={dateRange}
            onDateRangeChange={(range) => range && setDateRange(range)}
            promos={promos}
            promoLoading={promosLoading}
            selectedPromoId={selectedPromoId}
            onPromoChange={setSelectedPromoId}
            productPromo={productPromo}
            onProductPromoChange={(update) => setProductPromo((prev) => ({ ...prev, ...update }))}
            shippingPromo={shippingPromo}
            onShippingPromoChange={(update) => setShippingPromo((prev) => ({ ...prev, ...update }))}
            shippingTiers={shippingTiers}
            onShippingTiersChange={setShippingTiers}
            surcharges={surcharges}
            onSurchargesChange={setSurcharges}
            merchantFeePercent={merchantFeePercent}
            onMerchantFeeChange={setMerchantFeePercent}
            fixedCostPerOrder={fixedCostPerOrder}
            onFixedCostChange={setFixedCostPerOrder}
            cogsCalculationMode={cogsCalculationMode}
            onCogsCalculationModeChange={setCogsCalculationMode}
            applyHistoricalProductPromo={applyHistoricalProductPromo}
            onApplyHistoricalProductPromoChange={setApplyHistoricalProductPromo}
            pointsPerDollar={currentPointsPerDollar}
            redemptionRate={redemptionRate}
            onRedemptionRateChange={setRedemptionRate}
            pointDollarValue={pointDollarValue}
            onPointDollarValueChange={handlePointDollarValueChange}
            onConfigInputChange={handleConfigInputChange}
            onResetConfig={resetConfig}
            onRunSimulation={() => runSimulation()}
            isRunning={isSimulating}
            recommendedPointDollarValue={recommendedPointDollarValue}
            onApplyRecommendedPointDollarValue={handleApplyRecommendedPointValue}
            result={simulationResult}
          />
        </div>

        {/* Right Side - Results */}
        <div className="space-y-4 min-w-0 flex-1 overflow-hidden">
          {/* Top - Summary (horizontal) */}
          <SummaryCard
            result={simulationResult}
            isLoading={isLoading}
            baselineResult={baselineResult}
            onSaveAsBaseline={handleSaveAsBaseline}
            onClearBaseline={handleClearBaseline}
          />

          {/* Chart */}
          <div className="w-full min-w-0 overflow-hidden">
            <ResultsChart buckets={simulationResult?.buckets ?? []} isLoading={isSimulating} />
          </div>

          {/* Table */}
          <div className="w-full min-w-0 overflow-hidden">
            <ResultsTable buckets={simulationResult?.buckets ?? []} isLoading={isSimulating} />
          </div>
        </div>
      </div>
    </motion.div>
  );
}

export default DiscountSimulator;
