import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { fetchFilterOptions, fetchSelfGameStatisticsOverview, fetchStatisticsOverview, getCurrentAppCode, 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 { RevenueTrendPanel } from "./components/RevenueTrendPanel.jsx";
import { SelfGameScreen } from "./components/SelfGameScreen.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: [],
  countryOptions: [{ countryCode: "", id: 0, label: "全部国家", regionIds: [], searchText: "全部国家 all", value: 0 }],
  regionOptions: [{ countryCodes: [], id: "all", label: "全部区域", value: "all" }]
};

export function DatabiApp() {
  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 [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 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
      });
      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)
      });
      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(() => {
    void loadFilterOptions();
  }, [loadFilterOptions]);

  useEffect(() => {
    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, loadOverview, loadSelfGameOverview]);

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

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

  return (
    <main className="databi-shell">
      <section className={activeScreen === "selfGames" ? "databi-screen databi-screen--self-game" : "databi-screen"}>
        <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}
        />

        {activeScreen === "selfGames" ? (
          <SelfGameScreen gameId={gameId} loading={selfGameLoading && !selfGameOverview} onGameChange={setGameId} overview={selfGameOverview} />
        ) : (
          <>
            <section className="metric-grid" aria-label="核心指标">
              {model.kpis.map((item) => (
                <MetricCard key={item.label} item={item} loading={showSkeleton} onClick={() => setTrendModalItem(item)} />
              ))}
            </section>

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

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

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

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

function resolveSelectedAppCode(options, current) {
  const normalized = String(current || "").trim().toLowerCase();
  if (options.some((item) => String(item.code || item.value || "").trim().toLowerCase() === normalized)) {
    return normalized;
  }
  return String(options[0]?.code || options[0]?.value || normalized || "lalu").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) {
    return data;
  }
  const countryById = new Map(countries.map((country) => [Number(country.id), country]));
  return {
    ...data,
    country_breakdown: data.country_breakdown.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
      };
    })
  };
}
