import {
  AlertCircle,
  BarChart3,
  Flame,
  Newspaper,
  RefreshCcw,
  TrendingDown,
  TrendingUp,
} from "lucide-react";
import type { ComponentType } from "react";
import { useRouter } from "next/navigation";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { ScrollArea } from "@/components/ui/scroll-area";
import type {
  DashboardMarketHubResponse,
  DashboardMarketRankItem,
} from "@/features/dashboard/types/dashboard.types";
import {
  formatCurrency,
  formatSignedCurrency,
  formatSignedPercent,
  getChangeToneClass,
} from "@/features/dashboard/utils/dashboard-format";
import { useTradeNavigationStore } from "@/features/trade/store/use-trade-navigation-store";
import { cn } from "@/lib/utils";

interface MarketHubSectionProps {
  marketHub: DashboardMarketHubResponse | null;
  isLoading: boolean;
  error: string | null;
  onRetry?: () => void;
}

/**
 * @description 시장 탭의 급등/인기/뉴스 요약 섹션입니다.
 * @remarks UI 흐름: DashboardContainer -> MarketHubSection -> 급등/인기/뉴스 카드 렌더링
 */
export function MarketHubSection({
  marketHub,
  isLoading,
  error,
  onRetry,
}: MarketHubSectionProps) {
  const router = useRouter();
  const setPendingTarget = useTradeNavigationStore(
    (state) => state.setPendingTarget,
  );
  const gainers = marketHub?.gainers ?? [];
  const losers = marketHub?.losers ?? [];
  const popularByVolume = marketHub?.popularByVolume ?? [];
  const popularByValue = marketHub?.popularByValue ?? [];
  const news = marketHub?.news ?? [];
  const warnings = marketHub?.warnings ?? [];
  const pulse = marketHub?.pulse;

  const navigateToTrade = (item: DashboardMarketRankItem) => {
    setPendingTarget({
      symbol: item.symbol,
      name: item.name,
      market: item.market,
    });
    router.push("/trade");
  };

  return (
    <div className="grid gap-3">
      <Card className="border-brand-200/80 bg-linear-to-br from-brand-100/60 via-brand-50/20 to-background shadow-sm dark:border-brand-800/45 dark:from-brand-900/30 dark:via-brand-950/20">
        <CardHeader className="pb-3">
          <CardTitle className="flex items-center gap-2 text-base text-brand-700 dark:text-brand-300">
            <TrendingUp className="h-4 w-4" />
            시장 허브
          </CardTitle>
          <CardDescription>
            급등/급락, 인기 종목, 주요 뉴스를 한 화면에서 확인합니다.
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-3">
          <div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
            <PulseMetric label="급등주" value={`${pulse?.gainersCount ?? 0}개`} tone="up" />
            <PulseMetric label="급락주" value={`${pulse?.losersCount ?? 0}개`} tone="down" />
            <PulseMetric
              label="인기종목(거래량)"
              value={`${pulse?.popularByVolumeCount ?? 0}개`}
              tone="neutral"
            />
            <PulseMetric
              label="거래대금 상위"
              value={`${pulse?.popularByValueCount ?? 0}개`}
              tone="neutral"
            />
            <PulseMetric label="주요 뉴스" value={`${pulse?.newsCount ?? 0}건`} tone="brand" />
          </div>

          {warnings.length > 0 && (
            <div className="flex flex-wrap gap-2">
              {warnings.map((warning) => (
                <Badge
                  key={warning}
                  variant="outline"
                  className="border-amber-300 bg-amber-50 text-amber-700 dark:border-amber-700 dark:bg-amber-950/30 dark:text-amber-300"
                >
                  <AlertCircle className="h-3 w-3" />
                  {warning}
                </Badge>
              ))}
            </div>
          )}

          {isLoading && !marketHub && (
            <p className="text-sm text-muted-foreground">시장 허브를 불러오는 중입니다.</p>
          )}

          {error && (
            <div className="rounded-md border border-red-200 bg-red-50/60 p-2.5 dark:border-red-900/40 dark:bg-red-950/20">
              <p className="flex items-start gap-1.5 text-sm text-red-600 dark:text-red-400">
                <AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
                <span>{error}</span>
              </p>
              {onRetry ? (
                <Button
                  type="button"
                  size="sm"
                  variant="outline"
                  onClick={onRetry}
                  className="mt-2 border-red-300 text-red-700 hover:bg-red-100 dark:border-red-700 dark:text-red-300 dark:hover:bg-red-900/40"
                >
                  <RefreshCcw className="mr-1.5 h-3.5 w-3.5" />
                  시장 허브 다시 불러오기
                </Button>
              ) : null}
            </div>
          )}
        </CardContent>
      </Card>

      <div className="grid gap-3 md:grid-cols-2">
        <RankListCard
          title="급등주식"
          description="전일 대비 상승률 상위 종목"
          icon={Flame}
          items={gainers}
          tone="up"
          onSelectItem={navigateToTrade}
          secondaryLabel="거래량"
          secondaryValue={(item) => `${formatCurrency(item.volume)}주`}
        />
        <RankListCard
          title="급락주식"
          description="전일 대비 하락률 상위 종목"
          icon={TrendingDown}
          items={losers}
          tone="down"
          onSelectItem={navigateToTrade}
          secondaryLabel="거래량"
          secondaryValue={(item) => `${formatCurrency(item.volume)}주`}
        />
        <RankListCard
          title="인기종목"
          description="거래량 상위 종목"
          icon={BarChart3}
          items={popularByVolume}
          tone="neutral"
          onSelectItem={navigateToTrade}
          secondaryLabel="거래량"
          secondaryValue={(item) => `${formatCurrency(item.volume)}주`}
        />
        <RankListCard
          title="거래대금 상위"
          description="거래대금 상위 종목"
          icon={TrendingUp}
          items={popularByValue}
          tone="brand"
          onSelectItem={navigateToTrade}
          secondaryLabel="거래대금"
          secondaryValue={(item) => `${formatCurrency(item.tradingValue)}원`}
        />
      </div>

      <Card className="border-brand-200/70 bg-background/90 dark:border-brand-800/45">
        <CardHeader className="pb-3">
          <CardTitle className="flex items-center gap-2 text-base">
            <Newspaper className="h-4 w-4 text-brand-600 dark:text-brand-400" />
            주요 뉴스
          </CardTitle>
          <CardDescription>
            국내 시장 시황/공시 제목을 최신순으로 보여줍니다.
          </CardDescription>
        </CardHeader>
        <CardContent>
          <ScrollArea className="h-[220px] pr-3">
            {news.length === 0 ? (
              <p className="text-sm text-muted-foreground">표시할 뉴스가 없습니다.</p>
            ) : (
              <div className="space-y-2">
                {news.map((item) => (
                  <article
                    key={item.id}
                    className="rounded-xl border border-border/70 bg-linear-to-br from-background to-brand-50/30 px-3 py-2 dark:from-background dark:to-brand-950/20"
                  >
                    <p className="text-sm font-medium text-foreground">{item.title}</p>
                    <p className="mt-1 text-xs text-muted-foreground">
                      {item.source} · {item.publishedAt}
                    </p>
                    {item.symbols.length > 0 && (
                      <div className="mt-1 flex flex-wrap gap-1">
                        {item.symbols.slice(0, 3).map((symbol) => (
                          <Badge
                            key={`${item.id}-${symbol}`}
                            variant="outline"
                            className="text-[10px]"
                          >
                            {symbol}
                          </Badge>
                        ))}
                      </div>
                    )}
                  </article>
                ))}
              </div>
            )}
          </ScrollArea>
        </CardContent>
      </Card>
    </div>
  );
}

function PulseMetric({
  label,
  value,
  tone,
}: {
  label: string;
  value: string;
  tone: "up" | "down" | "neutral" | "brand";
}) {
  const toneClass =
    tone === "up"
      ? "border-red-200/70 bg-red-50/70 dark:border-red-900/40 dark:bg-red-950/20"
      : tone === "down"
        ? "border-blue-200/70 bg-blue-50/70 dark:border-blue-900/40 dark:bg-blue-950/20"
        : tone === "brand"
          ? "border-brand-200/70 bg-brand-50/70 dark:border-brand-700/60 dark:bg-brand-900/30"
          : "border-border/70 bg-background/80";

  return (
    <div className={cn("rounded-xl border p-3", toneClass)}>
      <p className="text-xs text-muted-foreground">{label}</p>
      <p className="mt-1 text-sm font-semibold text-foreground">{value}</p>
    </div>
  );
}

function RankListCard({
  title,
  description,
  icon: Icon,
  items,
  tone,
  onSelectItem,
  secondaryLabel,
  secondaryValue,
}: {
  title: string;
  description: string;
  icon: ComponentType<{ className?: string }>;
  items: DashboardMarketRankItem[];
  tone: "up" | "down" | "neutral" | "brand";
  onSelectItem: (item: DashboardMarketRankItem) => void;
  secondaryLabel: string;
  secondaryValue: (item: DashboardMarketRankItem) => string;
}) {
  const toneClass =
    tone === "up"
      ? "border-red-200/70 bg-red-50/35 dark:border-red-900/35 dark:bg-red-950/15"
      : tone === "down"
        ? "border-blue-200/70 bg-blue-50/35 dark:border-blue-900/35 dark:bg-blue-950/15"
        : tone === "brand"
          ? "border-brand-200/70 bg-brand-50/35 dark:border-brand-800/50 dark:bg-brand-900/20"
          : "border-border/70 bg-background/90";

  return (
    <Card className={cn("overflow-hidden shadow-sm", toneClass)}>
      <CardHeader className="pb-2">
        <CardTitle className="flex items-center gap-2 text-base">
          <Icon className="h-4 w-4 text-brand-600 dark:text-brand-400" />
          {title}
        </CardTitle>
        <CardDescription>{description}</CardDescription>
      </CardHeader>
      <CardContent>
        <ScrollArea className="h-[220px] pr-3">
          {items.length === 0 ? (
            <p className="text-sm text-muted-foreground">표시할 데이터가 없습니다.</p>
          ) : (
            <div className="space-y-2">
              {items.map((item) => {
                const toneClass = getChangeToneClass(item.change);
                return (
                  <div
                    key={`${title}-${item.symbol}-${item.rank}`}
                    className="rounded-xl border border-border/70 bg-background/80 px-3 py-2 shadow-sm"
                  >
                    <button
                      type="button"
                      onClick={() => onSelectItem(item)}
                      className="w-full text-left hover:opacity-90"
                      title={`${item.name} 거래 화면으로 이동`}
                    >
                      <div className="flex items-center justify-between gap-2">
                        <p className="text-sm font-semibold text-foreground">{item.name}</p>
                        <p className={cn("text-xs font-medium", toneClass)}>
                          {formatSignedPercent(item.changeRate)}
                        </p>
                      </div>
                      <p className="mt-0.5 text-xs text-muted-foreground">
                        #{item.rank} · {item.symbol} · {item.market}
                      </p>
                      <div className="mt-1 flex items-center justify-between gap-2 text-xs">
                        <span className="text-muted-foreground">
                          현재가 {formatCurrency(item.price)}원
                        </span>
                        <span className={cn("font-medium", toneClass)}>
                          {formatSignedCurrency(item.change)}원
                        </span>
                      </div>
                      <p className="mt-1 text-xs text-muted-foreground">
                        {secondaryLabel} {secondaryValue(item)}
                      </p>
                    </button>
                  </div>
                );
              })}
            </div>
          )}
        </ScrollArea>
      </CardContent>
    </Card>
  );
}
