import React, { useState, useMemo, useEffect } from 'react';
import * as XLSX from 'xlsx';
import { SalesRecord, AdsRecord } from '../../types';
import { Product } from './types';
import { KPICards } from './KPICards';
import { MasterTable } from './MasterTable';
import { WaterfallModal } from './WaterfallModal';
import { Settings2 } from 'lucide-react';

// ---------------------------------------------------------------------------
// Excel parsing helpers (all files use raw: true so numbers come back as JS numbers)
// ---------------------------------------------------------------------------

function parseNumericCell(val: unknown): number {
  if (typeof val === 'number') return isNaN(val) ? 0 : val;
  if (typeof val === 'string') {
    const clean = val.replace(/[€$£\s]/g, '').trim();
    if (!clean) return 0;
    // EU format: "1.234,56" — comma is decimal, dot is thousands
    if (clean.includes(',') && clean.includes('.') && clean.indexOf(',') > clean.indexOf('.')) {
      return parseFloat(clean.replace(/\./g, '').replace(',', '.')) || 0;
    }
    // EU format: "263,83" — only comma, treat as decimal
    if (clean.includes(',') && !clean.includes('.')) {
      return parseFloat(clean.replace(',', '.')) || 0;
    }
    return parseFloat(clean.replace(/,/g, '')) || 0;
  }
  return 0;
}

// Deals file: ASIN = col A (idx 0), total deal cost = col C (idx 2)
function parseDealsExcel(buffer: ArrayBuffer): Map<string, number> {
  const wb = XLSX.read(buffer, { type: 'array' });
  const ws = wb.Sheets[wb.SheetNames[0]];
  const rows = XLSX.utils.sheet_to_json<unknown[]>(ws, { header: 1, raw: true });
  const map = new Map<string, number>();
  for (let i = 1; i < rows.length; i++) {
    const row = rows[i] as unknown[];
    const asin = row[0];
    const cost = row[2];
    if (asin && typeof asin === 'string' && asin.trim()) {
      const key = asin.trim().toUpperCase();
      map.set(key, (map.get(key) || 0) + parseNumericCell(cost));
    }
  }
  return map;
}

// Promos file: ASIN = col E (idx 4), promo cost = col K (idx 10)
function parsePromosExcel(buffer: ArrayBuffer): Map<string, number> {
  const wb = XLSX.read(buffer, { type: 'array' });
  const ws = wb.Sheets[wb.SheetNames[0]];
  const rows = XLSX.utils.sheet_to_json<unknown[]>(ws, { header: 1, raw: true });
  const map = new Map<string, number>();
  for (let i = 1; i < rows.length; i++) {
    const row = rows[i] as unknown[];
    const asin = row[4];
    const cost = row[10];
    if (asin && typeof asin === 'string' && asin.trim()) {
      const key = asin.trim().toUpperCase();
      map.set(key, (map.get(key) || 0) + parseNumericCell(cost));
    }
  }
  return map;
}

// Chargebacks file: ASIN = col AN (idx 39), chargeback cost = col B (idx 1)
function parseChargebacksExcel(buffer: ArrayBuffer): Map<string, number> {
  const wb = XLSX.read(buffer, { type: 'array' });
  const ws = wb.Sheets[wb.SheetNames[0]];
  const rows = XLSX.utils.sheet_to_json<unknown[]>(ws, { header: 1, raw: true });
  const map = new Map<string, number>();
  for (let i = 1; i < rows.length; i++) {
    const row = rows[i] as unknown[];
    const asin = row[39];
    const cost = row[1];
    if (asin && typeof asin === 'string' && asin.trim()) {
      const key = asin.trim().toUpperCase();
      map.set(key, (map.get(key) || 0) + parseNumericCell(cost));
    }
  }
  return map;
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

interface MktDataViewProps {
  rawData: SalesRecord[];
  adsData: AdsRecord[];
  stockMap?: Map<string, number>;
  vendorStockMap?: Map<string, { eu: number; uk: number }>;
  top50Mode?: 'eu' | 'uk';
  velocityMap?: Map<string, number>;
  buyBoxLostMap?: Map<string, { countries: string[]; reasons: Record<string, string> }>;
  top50Ranking?: { eu: Map<string, number>; uk: Map<string, number> };
}

export default function MktDataView({ 
  rawData, 
  adsData,
  stockMap,
  vendorStockMap,
  top50Mode = 'eu',
  velocityMap,
  buyBoxLostMap,
  top50Ranking
}: MktDataViewProps) {
  const [includeCOGS, setIncludeCOGS] = useState(true);
  const [selectedProduct, setSelectedProduct] = useState<Product | null>(null);

  const [mktLoading, setMktLoading] = useState(true);
  const [dealsMap, setDealsMap] = useState<Map<string, number>>(new Map());
  const [promosMap, setPromosMap] = useState<Map<string, number>>(new Map());
  const [chargebacksMap, setChargebacksMap] = useState<Map<string, number>>(new Map());

  // Fetch the 3 new marketing data files once on mount
  useEffect(() => {
    let cancelled = false;
    const fetchAll = async () => {
      setMktLoading(true);
      try {
        const [dealsRes, promosRes, chargesRes] = await Promise.all([
          fetch('/api/fetch-mkt-data?file=deals'),
          fetch('/api/fetch-mkt-data?file=promos'),
          fetch('/api/fetch-mkt-data?file=chargebacks'),
        ]);

        if (cancelled) return;

        if (dealsRes.ok) {
          const buf = await dealsRes.arrayBuffer();
          if (!cancelled) setDealsMap(parseDealsExcel(buf));
        } else {
          console.warn('[MktDataView] fetch-mkt-data?file=deals failed:', dealsRes.status);
        }

        if (promosRes.ok) {
          const buf = await promosRes.arrayBuffer();
          if (!cancelled) setPromosMap(parsePromosExcel(buf));
        } else {
          console.warn('[MktDataView] fetch-mkt-data?file=promos failed:', promosRes.status);
        }

        if (chargesRes.ok) {
          const buf = await chargesRes.arrayBuffer();
          if (!cancelled) setChargebacksMap(parseChargebacksExcel(buf));
        } else {
          console.warn('[MktDataView] fetch-mkt-data?file=chargebacks failed:', chargesRes.status);
        }
      } catch (e) {
        console.error('[MktDataView] Error fetching marketing data:', e);
      } finally {
        if (!cancelled) setMktLoading(false);
      }
    };
    fetchAll();
    return () => { cancelled = true; };
  }, []);

  // Build Product[] from real data sources
  const allProducts = useMemo((): Product[] => {
    if (rawData.length === 0) return [];

    // ASIN → best metadata (longest title wins)
    const metaMap = new Map<string, { sku: string; title: string; line: string }>();
    rawData.forEach(r => {
      const asin = r.asin.trim().toUpperCase();
      const existing = metaMap.get(asin);
      if (!existing || (r.title && r.title.length > (existing.title?.length || 0))) {
        metaMap.set(asin, { sku: r.sku || '', title: r.title || '', line: r.line || 'Other' });
      }
    });

    // ASIN → global sell-out and units
    const sellOutMap = new Map<string, number>();
    const unitsMap = new Map<string, number>();
    rawData.forEach(r => {
      const asin = r.asin.trim().toUpperCase();
      sellOutMap.set(asin, (sellOutMap.get(asin) || 0) + r.sellOut);
      unitsMap.set(asin, (unitsMap.get(asin) || 0) + r.units);
    });

    // ASIN → global ad spend
    const adsSpendMap = new Map<string, number>();
    let totalAdsPassed = 0;
    adsData.forEach(r => {
      const asin = r.asin.trim().toUpperCase();
      adsSpendMap.set(asin, (adsSpendMap.get(asin) || 0) + r.cost);
      totalAdsPassed += r.cost;
    });

    // Deals/Promos/Chargebacks
    const has2025 = rawData.some(r => r.year === 2025) || adsData.some(r => r.year === 2025);
    const getDeals = (asin: string) => has2025 ? (dealsMap.get(asin) || 0) : 0;
    const getPromos = (asin: string) => has2025 ? (promosMap.get(asin) || 0) : 0;
    const getChargebacks = (asin: string) => has2025 ? (chargebacksMap.get(asin) || 0) : 0;

    // 1. Start with all sales-based ASINs
    const products: Product[] = Array.from(metaMap.entries())
      .map(([asin, meta]): Product => {
        const spend = adsSpendMap.get(asin) || 0;
        adsSpendMap.delete(asin); // Mark as processed
        return {
          id: asin,
          asin,
          sku: meta.sku,
          name: meta.title || asin,
          image: '',
          category: meta.line,
          brand: '',
          grossSales: sellOutMap.get(asin) || 0,
          unitsSold: unitsMap.get(asin) || 0,
          ppcSpend: spend,
          deals: getDeals(asin),
          promos: getPromos(asin),
          chargebacks: getChargebacks(asin),
          chargebacksPrevMonth: 0,
          cogs: 0,
        };
      });

    // 2. Add remaining ad spend (including "" ASIN and ASINs without sales)
    adsSpendMap.forEach((spend, asin) => {
      if (spend === 0) return;
      products.push({
        id: asin || '__unassigned__',
        asin: asin || '—',
        sku: '',
        name: asin ? asin : 'Unassigned Ad Spend (incl. Sponsored Brands)',
        image: '',
        category: 'Other',
        brand: '',
        grossSales: 0,
        unitsSold: 0,
        ppcSpend: spend,
        deals: asin ? getDeals(asin) : 0,
        promos: asin ? getPromos(asin) : 0,
        chargebacks: asin ? getChargebacks(asin) : 0,
        chargebacksPrevMonth: 0,
        cogs: 0,
      });
    });

    // Debug check
    const finalTotal = products.reduce((sum, p) => sum + p.ppcSpend, 0);
    if (Math.abs(finalTotal - totalAdsPassed) > 0.01) {
      console.warn(`[MktDataView] PPC Spend Mismatch: Total Ads=${totalAdsPassed.toFixed(2)}, Table Sum=${finalTotal.toFixed(2)}`);
    }

    return products;
  }, [rawData, adsData, dealsMap, promosMap, chargebacksMap]);

  const filteredProducts = allProducts;

  // ---------------------------------------------------------------------------
  // Loading skeleton — shown while MKT files are being fetched or rawData is empty
  // ---------------------------------------------------------------------------
  if (rawData.length === 0 || mktLoading) {
    return (
      <div className="font-sans text-slate-200 px-4 md:px-6 pb-24">
        <div className="flex items-center justify-between mb-8">
          <div>
            <h2 className="text-2xl font-bold text-white">Profitability Dashboard</h2>
            <p className="text-slate-400">Overview of product performance and margins.</p>
          </div>
        </div>
        {/* Skeleton KPI cards */}
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
          {[...Array(4)].map((_, i) => (
            <div key={i} className="bg-[#13161F] rounded-xl border border-[#1F2433] p-6 h-32 animate-pulse" />
          ))}
        </div>
        {/* Skeleton table */}
        <div className="bg-[#13161F] rounded-xl border border-[#1F2433] overflow-hidden">
          {[...Array(8)].map((_, i) => (
            <div key={i} className="px-6 py-4 border-b border-[#1F2433] animate-pulse flex gap-4">
              <div className="h-4 bg-[#1F2433] rounded w-1/3" />
              <div className="h-4 bg-[#1F2433] rounded w-1/6 ml-auto" />
              <div className="h-4 bg-[#1F2433] rounded w-1/6" />
              <div className="h-4 bg-[#1F2433] rounded w-1/6" />
            </div>
          ))}
        </div>
      </div>
    );
  }

  return (
    <div className="font-sans text-slate-200 px-4 md:px-6 pb-24">
      {/* Header Controls */}
      <div className="flex items-center justify-between mb-8">
        <div>
          <h2 className="text-2xl font-bold text-white">Profitability Dashboard</h2>
          <p className="text-slate-400">Overview of product performance and margins.</p>
        </div>

        <div className="flex items-center gap-4">
          {/* COGS Toggle */}
          <div className="flex items-center gap-2 bg-[#0A0C10] px-3 py-1.5 rounded-lg border border-[#1F2433]">
            <Settings2 className="w-4 h-4 text-slate-400" />
            <label className="flex items-center gap-2 cursor-pointer">
              <div className="relative">
                <input
                  type="checkbox"
                  className="sr-only"
                  checked={includeCOGS}
                  onChange={() => setIncludeCOGS(!includeCOGS)}
                />
                <div className={`block w-10 h-6 rounded-full transition-colors ${includeCOGS ? 'bg-indigo-600' : 'bg-[#1F2433]'}`}></div>
                <div className={`absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform ${includeCOGS ? 'transform translate-x-4' : ''}`}></div>
              </div>
              <span className="text-sm font-medium text-slate-300">Include COGS</span>
            </label>
          </div>
        </div>
      </div>

      <KPICards products={filteredProducts} includeCOGS={includeCOGS} />

      <div className="mb-8">
        <div className="mb-4 flex items-center justify-between">
          <h3 className="text-lg font-semibold text-white">Product Performance</h3>
          <p className="text-sm text-slate-400">Click on a product to view the waterfall breakdown.</p>
        </div>
        <MasterTable
          products={filteredProducts}
          includeCOGS={includeCOGS}
          onProductClick={setSelectedProduct}
          stockMap={stockMap}
          vendorStockMap={vendorStockMap}
          top50Mode={top50Mode}
          velocityMap={velocityMap}
          buyBoxLostMap={buyBoxLostMap}
          top50Ranking={top50Ranking}
        />
      </div>

      {/* Modal */}
      <WaterfallModal
        product={selectedProduct}
        includeCOGS={includeCOGS}
        onClose={() => setSelectedProduct(null)}
      />
    </div>
  );
}
