import './forceServerApi';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import ReactDOM from 'react-dom/client';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { LogicalSize } from '@tauri-apps/api/dpi';
import { initStorage, refreshApiBaseFromStorage } from '@goldenchart/shared';
import { ensureDesktopApiBase } from './ensureDesktopApiBase';
import FloatingWidgetWindow from '@frontend/components/floatingWidgets/FloatingWidgetWindow';
import {
  defaultGridFr,
  type FloatingWidgetInstance,
} from '@frontend/types/floatingWidget';
import type { Theme } from '@frontend/types';
import type { WidgetSlot } from '@frontend/types/widgetDashboard';
import { useMarketTicker } from '@frontend/hooks/useMarketTicker';
import {
  loadPaperSummary,
  loadPaperTrades,
  loadStrategies,
  type PaperSummaryDto,
  type PaperTradeDto,
  type StrategyDto,
} from '@frontend/utils/backendApi';
import { PAPER_TRADES_CHANGED_EVENT } from '@frontend/utils/paperTradeEvents';
import { WidgetDashboardProvider } from '@frontend/widgets/WidgetDashboardContext';
import { readDesktopSync, subscribeDesktopSync } from '@frontend/utils/desktopSync';
import { syncDocumentTheme } from '@frontend/utils/documentTheme';
import '@frontend/App.css';
import '@frontend/styles/appPopup.css';
import '@frontend/styles/paperDashboard.css';
import '@frontend/styles/widgetDashboard.css';
import '@frontend/styles/floatingWidget.css';

document.documentElement.classList.add('fw-native-widget');

function parseInstanceFromUrl(): FloatingWidgetInstance | null {
  const params = new URLSearchParams(window.location.search);
  const id = params.get('id');
  if (!id) return null;
  const rows = Number(params.get('rows') ?? 1);
  const cols = Number(params.get('cols') ?? 1);
  const width = Number(params.get('width') ?? 640);
  const height = Number(params.get('height') ?? 480);
  let slots: WidgetSlot[] = [];
  try {
    slots = JSON.parse(params.get('slots') ?? '[]') as WidgetSlot[];
  } catch {
    slots = [];
  }
  const rowFrRaw = params.get('rowFr');
  const colFrRaw = params.get('colFr');
  const rowFr = rowFrRaw ? rowFrRaw.split(',').map(Number) : defaultGridFr(rows);
  const colFr = colFrRaw ? colFrRaw.split(',').map(Number) : defaultGridFr(cols);

  return {
    id,
    rows,
    cols,
    slots,
    rowFr,
    colFr,
    position: { x: 0, y: 0 },
    width,
    height,
    zIndex: 1,
  };
}

const WidgetApp: React.FC = () => {
  const initial = useMemo(() => parseInstanceFromUrl(), []);
  const [instance, setInstance] = useState<FloatingWidgetInstance | null>(initial);
  const sync = readDesktopSync();
  const [theme, setTheme] = useState<Theme>((sync?.theme as Theme | undefined) ?? 'dark');
  const [defaultMarket, setDefaultMarket] = useState(sync?.selectedMarket ?? 'KRW-BTC');

  const { tickers, marketInfos, loading: marketLoading, usdRate } = useMarketTicker(
    useMemo(() => ({ enabled: true, loadFull: true }), []),
  );
  const [strategies, setStrategies] = useState<StrategyDto[]>([]);
  const [summary, setSummary] = useState<PaperSummaryDto | null>(null);
  const [trades, setTrades] = useState<PaperTradeDto[]>([]);

  const refreshPaperData = useCallback(async () => {
    try {
      const [sum, tr] = await Promise.all([loadPaperSummary(), loadPaperTrades()]);
      setSummary(sum);
      setTrades(tr ?? []);
    } catch { /* ignore */ }
  }, []);

  useEffect(() => {
    void loadStrategies().then(list => setStrategies(list ?? []));
    void refreshPaperData();
  }, [refreshPaperData]);

  useEffect(() => {
    const onChanged = () => { void refreshPaperData(); };
    window.addEventListener(PAPER_TRADES_CHANGED_EVENT, onChanged);
    return () => window.removeEventListener(PAPER_TRADES_CHANGED_EVENT, onChanged);
  }, [refreshPaperData]);

  useEffect(() => {
    return subscribeDesktopSync(state => {
      if (state.theme) setTheme(state.theme as Theme);
      if (state.selectedMarket) setDefaultMarket(state.selectedMarket);
    });
  }, []);

  useEffect(() => {
    syncDocumentTheme(theme);
  }, [theme]);

  useEffect(() => {
    if (!instance) return;
    const title = `GoldenChart — 위젯 ${instance.rows}×${instance.cols}`;
    void getCurrentWindow().setTitle(title);
  }, [instance?.rows, instance?.cols, instance]);

  useEffect(() => {
    if (!instance) return;
    let unlisten: (() => void) | undefined;
    void (async () => {
      unlisten = await getCurrentWindow().onResized(async () => {
        const size = await getCurrentWindow().innerSize();
        setInstance(prev => (
          prev ? { ...prev, width: size.width, height: size.height } : prev
        ));
      });
    })();
    return () => { unlisten?.(); };
  }, [instance?.id]);

  const handleClose = useCallback(() => {
    void getCurrentWindow().close();
  }, []);

  if (!instance) {
    return <p className="wd-widget-empty">위젯 정보를 불러올 수 없습니다.</p>;
  }

  return (
    <WidgetDashboardProvider
      theme={theme}
      tickers={tickers}
      marketInfos={marketInfos}
      marketLoading={marketLoading}
      usdRate={usdRate}
      defaultMarket={defaultMarket}
      strategies={strategies}
      summary={summary}
      trades={trades}
      refreshPaperData={() => { void refreshPaperData(); }}
      paperTradingEnabled
      paperAutoTradeEnabled={false}
      chartRealtimeSource="BACKEND_STOMP"
    >
      <div className="fw-widget-native-root">
        <FloatingWidgetWindow
          instance={instance}
          focused
          nativeShell
          onClose={handleClose}
          onFocus={() => {}}
          onUpdateSlots={slots => setInstance(prev => (prev ? { ...prev, slots } : prev))}
          onUpdateSize={(width, height) => {
            setInstance(prev => (prev ? { ...prev, width, height } : prev));
            void getCurrentWindow().setSize(new LogicalSize(width, height));
          }}
          onUpdateGridFr={(rowFr, colFr) => setInstance(prev => (prev ? { ...prev, rowFr, colFr } : prev))}
        />
      </div>
    </WidgetDashboardProvider>
  );
};

async function bootstrap() {
  await initStorage();
  ensureDesktopApiBase();
  refreshApiBaseFromStorage();

  ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
      <WidgetApp />
    </React.StrictMode>,
  );
}

void bootstrap();
