import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { fetchFilterOptions, fetchSelfGameStatisticsOverview, fetchStatisticsOverview, getCurrentAppCode, getDefaultAppOptions, setCurrentAppCode } from "./api.js";
import { CountryPerformanceTable } from "./components/CountryPerformanceTable.jsx";
import { DatabiHeader } from "./components/DatabiHeader.jsx";
import { FunnelPanel } from "./components/FunnelPanel.jsx";
import { GlobalOverviewPanel } from "./components/GlobalOverviewPanel.jsx";
import { LuckyGiftPoolModal } from "./components/LuckyGiftPoolModal.jsx";
import { MetricCard } from "./components/MetricCard.jsx";
import { MetricTrendModal } from "./components/MetricTrendModal.jsx";
import { ReportOverview } from "./components/ReportOverview.jsx";
import { EmptyReportSection, ReportSidebar } from "./components/ReportSidebar.jsx";
import { RevenueTrendPanel } from "./components/RevenueTrendPanel.jsx";
import { SelfGameScreen } from "./components/SelfGameScreen.jsx";
import { SocialBiApp } from "./social/SocialBiApp.jsx";
import { createDashboardModel } from "./data/createDashboardModel.js";
import { lastDaysRange, rangeEndMs, rangeStartMs, readStoredTimeZone, sameRange, thisMonthRange, TIME_ZONE_OPTIONS, todayRange, writeStoredTimeZone } from "./utils/time.js";

const initialFilterOptions = {
  appOptions: getDefaultAppOptions(),
  countryOptions: [{ countryCode: "", id: 0, label: "全部国家", regionIds: [], searchText: "全部国家 all", value: 0 }],
  regionOptions: [{ countryCodes: [], id: "all", label: "全部区域", value: "all" }]
};

export function DatabiApp() {
  if (isSocialBiPath()) {
    return <SocialBiApp />;
  }
  return <DatabiOverviewApp />;
}

function DatabiOverviewApp() {
  const initialTimeZone = useMemo(() => readStoredTimeZone(), []);
  const initialRange = useMemo(() => todayRange(initialTimeZone), [initialTimeZone]);
  const [timeZone, setTimeZone] = useState(initialTimeZone);
  const [range, setRange] = useState(initialRange);
  const [countryId, setCountryId] = useState(0);
  const [regionId, setRegionId] = useState("all");
  const [appCode, setAppCode] = useState(() => getCurrentAppCode());
  const [viewMode, setViewMode] = useState("report");
  const [activeReportSection, setActiveReportSection] = useState("data");
  const [activeScreen, setActiveScreen] = useState("overview");
  const [gameId, setGameId] = useState("all");
  const [filterOptions, setFilterOptions] = useState(initialFilterOptions);
  const [filtersLoading, setFiltersLoading] = useState(false);
  const [overview, setOverview] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [selfGameOverview, setSelfGameOverview] = useState(null);
  const [selfGameLoading, setSelfGameLoading] = useState(false);
  const [selfGameError, setSelfGameError] = useState("");
  const [poolModalOpen, setPoolModalOpen] = useState(false);
  const [trendModalItem, setTrendModalItem] = useState(null);
  const overviewRequestIdRef = useRef(0);
  const selfGameRequestIdRef = useRef(0);
  const overviewRef = useRef(null);
  const selfGameOverviewRef = useRef(null);
  const scopedCountries = useMemo(() => {
    return filterOptions.countryOptions.filter((country) => Number(country.id) > 0 && countryBelongsToRegion(country, regionId));
  }, [filterOptions.countryOptions, regionId]);
  const isDataReportSection = activeReportSection === "data";

  const handleAppChange = useCallback((value) => {
    setAppCode(setCurrentAppCode(value));
  }, []);

  const handleRegionChange = useCallback((value) => {
    setRegionId(String(value || "all"));
    setCountryId(0);
  }, []);

  const handleTimeZoneChange = useCallback((value) => {
    const nextTimeZone = writeStoredTimeZone(value);
    setRange((currentRange) => {
      const currentPreset = resolveRangePresetValue(currentRange, timeZone);
      return currentPreset ? rangeForPreset(currentPreset, nextTimeZone) : currentRange;
    });
    setTimeZone(nextTimeZone);
  }, [timeZone]);

  const loadFilterOptions = useCallback(async () => {
    setFiltersLoading(true);
    try {
      const options = await fetchFilterOptions({ appCode });
      setFilterOptions(options);
      const nextAppCode = resolveSelectedAppCode(options.appOptions, appCode);
      if (nextAppCode !== appCode) {
        setAppCode(setCurrentAppCode(nextAppCode));
      }
      setRegionId((current) => (options.regionOptions.some((item) => String(item.id) === String(current)) ? current : "all"));
      setCountryId((current) => (options.countryOptions.some((item) => Number(item.id) === Number(current)) ? current : 0));
    } catch (err) {
      setError(err.message || "筛选项加载失败");
    } finally {
      setFiltersLoading(false);
    }
  }, [appCode]);

  useEffect(() => {
    overviewRef.current = overview;
  }, [overview]);

  useEffect(() => {
    selfGameOverviewRef.current = selfGameOverview;
  }, [selfGameOverview]);

  const loadOverview = useCallback(async ({ preserveData = false } = {}) => {
    const requestId = overviewRequestIdRef.current + 1;
    overviewRequestIdRef.current = requestId;
    const keepCurrentOverview = preserveData && overviewRef.current;
    setLoading(true);
    setError("");
    if (!keepCurrentOverview) {
      setOverview(null);
    }
    try {
      const startMs = rangeStartMs(range, timeZone);
      const endMs = rangeEndMs(range, timeZone);
      const seriesRange = sameRange(range, todayRange(timeZone)) ? lastDaysRange(7, timeZone) : range;
      const data = await fetchStatisticsOverview({
        appCode,
        countryId,
        endMs,
        regionId,
        seriesEndMs: rangeEndMs(seriesRange, timeZone),
        seriesStartMs: rangeStartMs(seriesRange, timeZone),
        startMs,
        statTz: timeZone
      });
      const nextOverview = enrichCountryBreakdown(data || {}, scopedCountries);
      if (requestId === overviewRequestIdRef.current) {
        setOverview(nextOverview);
      }
    } catch (err) {
      if (requestId === overviewRequestIdRef.current) {
        if (!keepCurrentOverview) {
          setOverview(null);
        }
        setError(err.message || "请求失败");
      }
    } finally {
      if (requestId === overviewRequestIdRef.current) {
        setLoading(false);
      }
    }
  }, [appCode, countryId, range, regionId, scopedCountries, timeZone]);

  const loadSelfGameOverview = useCallback(async ({ preserveData = false } = {}) => {
    const requestId = selfGameRequestIdRef.current + 1;
    selfGameRequestIdRef.current = requestId;
    const keepCurrentOverview = preserveData && selfGameOverviewRef.current;
    setSelfGameLoading(true);
    setSelfGameError("");
    if (!keepCurrentOverview) {
      setSelfGameOverview(null);
    }
    try {
      const data = await fetchSelfGameStatisticsOverview({
        appCode,
        countryId,
        endMs: rangeEndMs(range, timeZone),
        gameId,
        regionId,
        startMs: rangeStartMs(range, timeZone),
        statTz: timeZone
      });
      if (requestId === selfGameRequestIdRef.current) {
        setSelfGameOverview(data || {});
      }
    } catch (err) {
      if (requestId === selfGameRequestIdRef.current) {
        if (!keepCurrentOverview) {
          setSelfGameOverview(null);
        }
        setSelfGameError(err.message || "请求失败");
      }
    } finally {
      if (requestId === selfGameRequestIdRef.current) {
        setSelfGameLoading(false);
      }
    }
  }, [appCode, countryId, gameId, range, regionId, timeZone]);

  useEffect(() => {
    if (!isDataReportSection) {
      return undefined;
    }
    void loadFilterOptions();
  }, [isDataReportSection, loadFilterOptions]);

  useEffect(() => {
    if (!isDataReportSection) {
      return undefined;
    }
    if (activeScreen === "selfGames") {
      void loadSelfGameOverview();
      const timer = window.setInterval(() => void loadSelfGameOverview({ preserveData: true }), 60_000);
      return () => window.clearInterval(timer);
    }
    void loadOverview();
    const timer = window.setInterval(() => void loadOverview({ preserveData: true }), 60_000);
    return () => window.clearInterval(timer);
  }, [activeScreen, isDataReportSection, loadOverview, loadSelfGameOverview]);

  const handleRefresh = useCallback(() => {
    if (!isDataReportSection) {
      return;
    }
    if (activeScreen === "selfGames") {
      void loadSelfGameOverview({ preserveData: true });
      return;
    }
    void loadOverview({ preserveData: true });
  }, [activeScreen, isDataReportSection, loadOverview, loadSelfGameOverview]);

  const model = useMemo(() => createDashboardModel(overview, { appCode, countryId, range, timeZone }), [appCode, countryId, overview, range, timeZone]);
  const showSkeleton = loading && !overview;
  const isReportView = viewMode === "report";
  const openLuckyGiftPools = useCallback(() => {
    setPoolModalOpen(true);
  }, []);

  return (
    <main className={`databi-shell databi-shell--${viewMode}`}>
      <ReportSidebar activeSection={activeReportSection} onSectionChange={setActiveReportSection} />
      <div className="databi-shell-content">
        {isDataReportSection ? (
          <section className={[
            "databi-screen",
            isReportView ? "databi-screen--report" : "databi-screen--bigscreen",
            activeScreen === "selfGames" ? "databi-screen--self-game" : ""
          ].filter(Boolean).join(" ")}>
            <DatabiHeader
              activeScreen={activeScreen}
              appCode={appCode}
              appOptions={filterOptions.appOptions}
              countryOptions={filterOptions.countryOptions}
              countryId={countryId}
              error={activeScreen === "selfGames" ? selfGameError : error}
              filtersLoading={filtersLoading}
              loading={activeScreen === "selfGames" ? selfGameLoading : loading}
              onAppChange={handleAppChange}
              onCountryChange={setCountryId}
              onRefresh={handleRefresh}
              onRangeChange={setRange}
              onRegionChange={handleRegionChange}
              onScreenChange={setActiveScreen}
              onTimeZoneChange={handleTimeZoneChange}
              range={range}
              regionId={regionId}
              regionOptions={filterOptions.regionOptions}
              timeZone={timeZone}
              timeZoneOptions={TIME_ZONE_OPTIONS}
              updatedAt={model.updatedAt}
              viewMode={viewMode}
              onViewModeChange={setViewMode}
            />

            {activeScreen === "selfGames" ? (
              <SelfGameScreen gameId={gameId} loading={selfGameLoading && !selfGameOverview} onGameChange={setGameId} overview={selfGameOverview} />
            ) : isReportView ? (
              <ReportOverview
                grantDrilldownQuery={{
                  appCode,
                  countryId,
                  endMs: rangeEndMs(range, timeZone),
                  regionId,
                  startMs: rangeStartMs(range, timeZone),
                  statTz: timeZone
                }}
                loading={showSkeleton}
                model={model}
                onMetricTrend={setTrendModalItem}
                onOpenLuckyGiftPools={openLuckyGiftPools}
              />
            ) : (
              <BigscreenOverview
                loading={showSkeleton}
                model={model}
                onMetricTrend={setTrendModalItem}
                onOpenLuckyGiftPools={openLuckyGiftPools}
              />
            )}
          </section>
        ) : (
          <EmptyReportSection section={activeReportSection} />
        )}

        {isDataReportSection && activeScreen === "overview" && !isReportView ? (
          <CountryPerformanceTable gameRanking={model.gameRanking} giftRanking={model.giftRanking} items={model.countryBreakdown} loading={showSkeleton} />
        ) : null}
        {isDataReportSection && activeScreen === "overview" && poolModalOpen ? (
          <LuckyGiftPoolModal items={model.luckyGiftPools} onClose={() => setPoolModalOpen(false)} />
        ) : null}
        {isDataReportSection && activeScreen === "overview" && trendModalItem ? (
          <MetricTrendModal item={trendModalItem} onClose={() => setTrendModalItem(null)} />
        ) : null}
      </div>
    </main>
  );
}

function BigscreenOverview({ loading, model, onMetricTrend, onOpenLuckyGiftPools }) {
  return (
    <>
      <section className="metric-grid" aria-label="核心指标">
        {model.kpis.map((item) => (
          <MetricCard key={item.label} item={item} loading={loading} onClick={() => onMetricTrend(item)} />
        ))}
      </section>

      <section className="business-metric-grid" aria-label="业务指标">
        {model.businessKpis.map((item) => (
          <MetricCard
            key={item.label}
            item={item}
            loading={loading}
            onClick={item.detailKey === "luckyGiftPools" ? onOpenLuckyGiftPools : undefined}
          />
        ))}
      </section>

      <section className="business-metric-grid robot-gift-metric-grid" aria-label="真人房机器人送礼指标">
        {model.robotGiftKpis.map((item) => (
          <MetricCard key={item.label} item={item} loading={loading} onClick={() => onMetricTrend(item)} />
        ))}
      </section>

      <section className="databi-grid databi-grid--top">
        <GlobalOverviewPanel countryBreakdown={model.countryBreakdown} loading={loading} topCountries={model.topCountries} />
        <RevenueTrendPanel loading={loading} revenueSeries={model.revenueSeries} />
        <FunnelPanel funnel={model.funnel} loading={loading} sideMetrics={model.sideMetrics} />
      </section>
    </>
  );
}

function resolveSelectedAppCode(options, current) {
  const normalized = String(current || "").trim().toLowerCase();
  if (options.some((item) => optionAppCode(item) === normalized)) {
    return normalized;
  }
  if (options.length) {
    return optionAppCode(options[0]);
  }
  return normalized || "lalu";
}

function optionAppCode(option) {
  return String(option?.code ?? option?.value ?? "").trim().toLowerCase();
}

function resolveRangePresetValue(range, timeZone) {
  const presets = [
    { range: todayRange(timeZone), value: "today" },
    { range: lastDaysRange(7, timeZone), value: "7d" },
    { range: lastDaysRange(14, timeZone), value: "14d" },
    { range: lastDaysRange(30, timeZone), value: "30d" },
    { range: thisMonthRange(timeZone), value: "month" }
  ];
  return presets.find((preset) => sameRange(preset.range, range))?.value || "";
}

function rangeForPreset(value, timeZone) {
  switch (value) {
    case "today":
      return todayRange(timeZone);
    case "7d":
      return lastDaysRange(7, timeZone);
    case "14d":
      return lastDaysRange(14, timeZone);
    case "30d":
      return lastDaysRange(30, timeZone);
    case "month":
      return thisMonthRange(timeZone);
    default:
      return null;
  }
}

function countryBelongsToRegion(country, regionId) {
  if (!regionId || regionId === "all") {
    return true;
  }
  if (Array.isArray(country.regionIds) && country.regionIds.length) {
    return country.regionIds.includes(String(regionId));
  }
  return String(country.regionId || "") === String(regionId);
}

function enrichCountryBreakdown(data, countries) {
  if ((!Array.isArray(data?.country_breakdown) || !data.country_breakdown.length) &&
    (!Array.isArray(data?.daily_country_breakdown) || !data.daily_country_breakdown.length)) {
    return data;
  }
  const countryById = new Map(countries.map((country) => [Number(country.id), country]));
  const enrichRows = (rows) => rows.map((row) => {
    const country = countryById.get(Number(row.country_id ?? row.countryId));
    if (!country) {
      return row;
    }
    return {
      ...row,
      country: row.country || country.name || country.label,
      country_code: row.country_code || country.countryCode,
      flag: row.flag || country.flag
    };
  });
  return {
    ...data,
    country_breakdown: Array.isArray(data.country_breakdown) ? enrichRows(data.country_breakdown) : data.country_breakdown,
    daily_country_breakdown: Array.isArray(data.daily_country_breakdown) ? enrichRows(data.daily_country_breakdown) : data.daily_country_breakdown
  };
}

function isSocialBiPath() {
  return window.location.pathname.replace(/\/+$/, "") === "/databi/social";
}
