import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { EChart } from "../charts/EChart.jsx";
import { createGeoOption } from "../charts/options/createGeoOption.js";
import { formatMoney, moneyMajor } from "../utils/format.js";
import { GlobeMap } from "./GlobeMap.jsx";
import { Panel } from "./Panel.jsx";
import { RankList } from "./RankList.jsx";

const MODAL_TRANSITION_MS = 180;

export function GlobalOverviewPanel({ countryBreakdown, loading = false }) {
  const [globeOpen, setGlobeOpen] = useState(false);
  const rechargeCountries = useMemo(() => countryBreakdown.filter(hasRecharge), [countryBreakdown]);
  const rankedCountries = useMemo(() => rechargeCountries.slice(0, 4), [rechargeCountries]);

  return (
    <>
      <Panel className="panel--map" title="全球概览">
        {loading ? <GlobalOverviewSkeleton /> : (
          <div className="geo-layout">
            <div className="geo-map">
              {rankedCountries.length ? <EChart className="geo-chart" option={createGeoOption(rankedCountries)} /> : <div className="panel-empty">暂无国家数据</div>}
              <div className="geo-scale">
                <span>高</span>
                <i />
                <span>低</span>
              </div>
            </div>
            <div className="rank-block">
              <RankList items={rankedCountries} title="充值国家排行" valueFormatter={formatRankMoney} />
              <button className="all-countries-button" disabled={!rechargeCountries.length} type="button" onClick={() => setGlobeOpen(true)}>
                查看全部国家
              </button>
            </div>
          </div>
        )}
      </Panel>
      {globeOpen ? <CountryGlobeDialog items={rechargeCountries} onClose={() => setGlobeOpen(false)} /> : null}
    </>
  );
}

function GlobalOverviewSkeleton() {
  return (
    <div className="geo-layout skeleton-panel" aria-busy="true">
      <div className="geo-map skeleton-map">
        <span className="skeleton-block skeleton-map-glow" />
      </div>
      <div className="rank-block">
        <span className="skeleton-block skeleton-rank-title" />
        {Array.from({ length: 4 }).map((_, index) => (
          <span className="skeleton-block skeleton-rank-row" key={index} />
        ))}
        <span className="skeleton-block skeleton-button" />
      </div>
    </div>
  );
}

function CountryGlobeDialog({ items, onClose }) {
  const [closing, setClosing] = useState(false);
  const closeTimerRef = useRef(null);
  const requestClose = useCallback(() => {
    if (closing) {
      return;
    }
    setClosing(true);
    closeTimerRef.current = window.setTimeout(onClose, MODAL_TRANSITION_MS);
  }, [closing, onClose]);

  useEffect(() => () => {
    if (closeTimerRef.current) {
      window.clearTimeout(closeTimerRef.current);
    }
  }, []);

  useEffect(() => {
    const closeOnEscape = (event) => {
      if (event.key === "Escape") {
        requestClose();
      }
    };
    window.addEventListener("keydown", closeOnEscape);
    return () => window.removeEventListener("keydown", closeOnEscape);
  }, [requestClose]);

  return (
    <div
      className={["country-globe-modal", closing ? "is-closing" : ""].filter(Boolean).join(" ")}
      role="presentation"
      onMouseDown={(event) => {
        if (event.target === event.currentTarget) {
          requestClose();
        }
      }}
    >
      <section aria-label="全部国家地球仪" aria-modal="true" className="country-globe-dialog" role="dialog">
        <div className="country-globe-head">
          <div>
            <h2>全部国家</h2>
            <span>{items.length} 个国家 / 按充值规模展示</span>
          </div>
          <button aria-label="关闭" type="button" onClick={requestClose}>
            <span aria-hidden="true" className="modal-close-mark" />
          </button>
        </div>
        <div className="country-globe-body">
          <GlobeMap items={items} />
        </div>
      </section>
    </div>
  );
}

function formatRankMoney(value) {
  const amount = moneyMajor(value);
  if (Math.abs(amount) >= 100_000) {
    return `$${(amount / 1_000_000).toFixed(2)}M`;
  }
  return formatMoney(value);
}

function hasRecharge(item) {
  return Number(item?.recharge_usd_minor) > 0;
}
