import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { authenticatedFetch, API_URL } from '../../utils/api';
import {
  ResponsiveContainer, ComposedChart, Area, Line,
  XAxis, CartesianGrid, Tooltip,
} from 'recharts';

// 환경변수에서 테스트 모드 확인
const isTestPage = import.meta.env.VITE_IS_TESTPAGE === 'true';

// =====================================================
// Types
// =====================================================

interface ContentMetric {
  id: string;
  label: string;
  value: number;  // 원시 숫자값 (단위: unit 참조)
  unit: string;   // "count" | "hours" | "minutes"
  trend: number;
  trendDirection: 'up' | 'down' | '-';
}

interface MonthlyData {
  month: string;
  thisYear: number;
  lastYear: number;
}

interface DailyData {
  date: string;
  thisPeriod: number;
  lastPeriod: number;
}

interface TopContent {
  id: string;
  title: string;
  thumbnail: string;
  platform: 'youtube' | 'instagram';
  views: number;  // 원시 정수 (포맷팅은 formatNumber로 처리)
  engagement: string;
  date: string;
}

interface AudienceData {
  ageGroups: { label: string; percentage: number }[];
  gender: { male: number; female: number };
  topRegions: { region: string; percentage: number }[];
}

interface DashboardError {
  code: string;
  message: string;
  reconnect_url?: string;
}

interface DashboardResponse {
  contentMetrics: ContentMetric[];
  monthlyData: MonthlyData[];
  dailyData: DailyData[];
  topContent: TopContent[];
  audienceData: AudienceData;
  hasUploads: boolean;  // 업로드 영상 존재 여부 (false 시 mock 데이터 + 안내 메시지 표시)
  error: DashboardError | null;
}

interface ConnectedAccount {
  id: number;
  platform: string;
  platformUserId: string;
  platformUsername?: string | null;
  channelTitle?: string | null;
  connectedAt: string;
  isActive: boolean;
}

// =====================================================
// Mock Data (연동 전 샘플 데이터)
// =====================================================

const MOCK_CONTENT_METRICS: ContentMetric[] = [
  { id: 'total-views',      label: 'dashboard.metricTotalViews',      value: 240000, unit: 'count',   trend: 3800, trendDirection: 'up' },
  { id: 'total-watch-time', label: 'dashboard.metricWatchTime',       value: 85.3,   unit: 'hours',   trend: 21.5, trendDirection: 'up' },
  { id: 'avg-view-duration',label: 'dashboard.metricAvgViewDuration', value: 41,     unit: 'minutes', trend: 2.4,  trendDirection: 'up' },
  { id: 'new-subscribers',  label: 'dashboard.metricNewSubscribers',  value: 483,    unit: 'count',   trend: 50,   trendDirection: 'up' },
  { id: 'likes',            label: 'dashboard.metricLikes',           value: 15800,  unit: 'count',   trend: 180,  trendDirection: 'up' },
  { id: 'comments',         label: 'dashboard.metricComments',        value: 2500,   unit: 'count',   trend: 50,   trendDirection: 'down' },
  { id: 'shares',           label: 'dashboard.metricShares',          value: 840,    unit: 'count',   trend: 15,   trendDirection: 'up' },
  { id: 'uploaded-videos',  label: 'dashboard.metricUploadedVideos',  value: 17,     unit: 'count',   trend: 4,    trendDirection: 'up' },
];

const MOCK_MONTHLY_DATA: MonthlyData[] = [
  { month: 'dashboard.months.jan', thisYear: 18000, lastYear: 14500 },
  { month: 'dashboard.months.feb', thisYear: 19500, lastYear: 15800 },
  { month: 'dashboard.months.mar', thisYear: 21000, lastYear: 17200 },
  { month: 'dashboard.months.apr', thisYear: 18500, lastYear: 16800 },
  { month: 'dashboard.months.may', thisYear: 24000, lastYear: 19500 },
  { month: 'dashboard.months.jun', thisYear: 27500, lastYear: 21000 },
  { month: 'dashboard.months.jul', thisYear: 32000, lastYear: 23500 },
  { month: 'dashboard.months.aug', thisYear: 29500, lastYear: 24800 },
  { month: 'dashboard.months.sep', thisYear: 31000, lastYear: 26200 },
  { month: 'dashboard.months.oct', thisYear: 28500, lastYear: 25500 },
  { month: 'dashboard.months.nov', thisYear: 34000, lastYear: 27800 },
  { month: 'dashboard.months.dec', thisYear: 38000, lastYear: 29500 },
];

const MOCK_DAILY_DATA: DailyData[] = Array.from({ length: 30 }, (_, i) => {
  const month = i <= 11 ? 1 : 2;
  const day = i <= 11 ? i + 20 : i - 11;
  const thisPeriod = [820, 910, 780, 1020, 890, 1100, 950, 870, 1010, 980, 1120, 1050, 930, 860, 1080, 1150, 970, 1030, 800, 990, 1180, 1070, 920, 880, 1040, 1110, 960, 1000, 850, 940][i];
  const lastPeriod = [680, 720, 650, 800, 700, 800, 770, 710, 800, 790, 900, 860, 760, 700, 870, 920, 790, 840, 690, 800, 940, 870, 700, 720, 850, 890, 780, 810, 690, 760][i];
  return { date: `${month}/${day}`, thisPeriod, lastPeriod };
});

const MOCK_TOP_CONTENT: TopContent[] = [
  { id: '1', title: '겨울 펜션 프로모션 영상', thumbnail: 'https://picsum.photos/seed/content1/120/68', platform: 'youtube', views: 125400, engagement: '8.2%', date: '2025.01.15' },
  { id: '2', title: '스테이 머뭄 소개 릴스', thumbnail: 'https://picsum.photos/seed/content2/120/68', platform: 'instagram', views: 89200, engagement: '12.5%', date: '2025.01.22' },
  { id: '3', title: '신년 특가 이벤트 안내', thumbnail: 'https://picsum.photos/seed/content3/120/68', platform: 'youtube', views: 67800, engagement: '6.4%', date: '2025.01.08' },
  { id: '4', title: '펜션 야경 타임랩스', thumbnail: 'https://picsum.photos/seed/content4/120/68', platform: 'instagram', views: 54300, engagement: '15.8%', date: '2025.01.28' },
];

const MOCK_AUDIENCE_DATA: AudienceData = {
  ageGroups: [
    { label: '13-24', percentage: 12 },
    { label: '25-34', percentage: 35 },
    { label: '35-44', percentage: 28 },
    { label: '45-54', percentage: 18 },
    { label: '55+', percentage: 7 },
  ],
  gender: { male: 42, female: 58 },
  topRegions: [
    { region: '한국', percentage: 77 },
    { region: '일본', percentage: 5 },
    { region: '중국', percentage: 4 },
    { region: '미국', percentage: 2 },
    { region: '인도', percentage: 1 },
  ],
};

// =====================================================
// Animation Components
// =====================================================

interface AnimatedItemProps {
  children: React.ReactNode;
  index: number;
  baseDelay?: number;
  className?: string;
}

const AnimatedItem: React.FC<AnimatedItemProps> = ({ children, index, baseDelay = 0, className = '' }) => {
  const [isVisible, setIsVisible] = useState(false);
  const delay = baseDelay + index * 80;

  useEffect(() => {
    const timer = setTimeout(() => setIsVisible(true), delay);
    return () => clearTimeout(timer);
  }, [delay]);

  return (
    <div
      className={`transition-all duration-500 ${
        isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-4 pointer-events-none'
      } ${className}`}
    >
      {children}
    </div>
  );
};

interface AnimatedSectionProps {
  children: React.ReactNode;
  delay?: number;
  className?: string;
}

const AnimatedSection: React.FC<AnimatedSectionProps> = ({ children, delay = 0, className = '' }) => {
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    const timer = setTimeout(() => setIsVisible(true), delay);
    return () => clearTimeout(timer);
  }, [delay]);

  return (
    <div
      className={`transition-all duration-600 ${
        isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-6 pointer-events-none'
      } ${className}`}
    >
      {children}
    </div>
  );
};

const formatNumber = (num: number): string => {
  if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
  if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
  return num.toString();
};

const formatValue = (value: number, unit: string, unitHours: string, unitMinutes: string): string => {
  if (unit === 'hours') return value.toFixed(1) + unitHours;
  if (unit === 'minutes') return Math.round(value) + unitMinutes;
  return formatNumber(Math.round(value));
};

const formatTrend = (trend: number, unit: string, unitHours: string, unitMinutes: string): string => {
  const abs = Math.abs(trend);
  if (unit === 'hours') return abs.toFixed(1) + unitHours;
  if (unit === 'minutes') return Math.round(abs) + unitMinutes;
  return formatNumber(Math.round(abs));
};

// =====================================================
// UI Components
// =====================================================

const TrendIcon: React.FC<{ direction: 'up' | 'down' }> = ({ direction }) => (
  <svg
    className="stat-trend-icon"
    viewBox="0 0 12 12"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    {direction === 'up' ? (
      <path d="M6 9V3M3 5l3-3 3 3" />
    ) : (
      <path d="M6 3v6M3 7l3 3 3-3" />
    )}
  </svg>
);

const StatCard: React.FC<ContentMetric> = ({ label, value, unit, trend, trendDirection }) => {
  const { t } = useTranslation();
  const unitHours = t('dashboard.unitHours');
  const unitMinutes = t('dashboard.unitMinutes');
  const isNeutral = trend === 0 || trendDirection === '-';
  const isUp = trendDirection === 'up';
  return (
    <div className="stat-card">
      <span className="stat-label">{t(label)}</span>
      <h3 className="stat-value">{formatValue(value, unit, unitHours, unitMinutes)}</h3>
      <div className="stat-trend-wrapper">
        {isNeutral ? (
          <span className="stat-trend neutral">─</span>
        ) : (
          <span className={`stat-trend ${isUp ? 'up' : 'down'}`}>
            <TrendIcon direction={isUp ? 'up' : 'down'} />
            {isUp ? '+' : '-'}{formatTrend(trend, unit, unitHours, unitMinutes)}
          </span>
        )}
      </div>
    </div>
  );
};

// =====================================================
// Chart Component with Tooltip
// =====================================================

// 차트에 전달하는 통합 데이터 포인트 타입
// MonthlyData / DailyData 모두 이 형식으로 변환하여 사용
interface ChartDataPoint {
  label: string;    // X축 레이블 (월별: "1월", 일별: "1/20")
  current: number;  // 현재 기간 (thisYear 또는 thisPeriod)
  previous: number; // 이전 기간 (lastYear 또는 lastPeriod)
}

const YearOverYearChart: React.FC<{
  data: ChartDataPoint[];
  currentLabel: string;
  previousLabel: string;
  mode: 'day' | 'month';
  noDataLabel: string;
}> = ({ data, currentLabel, previousLabel, mode, noDataLabel }) => {
  if (data.length === 0) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '200px', opacity: 0.4 }}>
        <span>{noDataLabel}</span>
      </div>
    );
  }

  const CustomTooltip = ({ active, payload, label }: { active?: boolean; payload?: { dataKey: string; value: number }[]; label?: string }) => {
    if (!active || !payload?.length) return null;
    const current = payload.find((p: { dataKey: string; value: number }) => p.dataKey === 'current')?.value ?? 0;
    const previous = payload.find((p: { dataKey: string; value: number }) => p.dataKey === 'previous')?.value ?? 0;
    const isEqual = current === previous;
    const isUp = current > previous;
    const diff = Math.abs(current - previous);
    const changeClass = isEqual ? ' neutral' : isUp ? '' : ' down';
    return (
      <div className="chart-tooltip">
        <div className="chart-tooltip-title">{label}</div>
        <div className="chart-tooltip-row">
          <span className="chart-tooltip-dot mint"></span>
          <span className="chart-tooltip-label">{currentLabel}</span>
          <span className="chart-tooltip-value">{formatNumber(current)}</span>
        </div>
        <div className="chart-tooltip-row">
          <span className="chart-tooltip-dot purple"></span>
          <span className="chart-tooltip-label">{previousLabel}</span>
          <span className="chart-tooltip-value">{formatNumber(previous)}</span>
        </div>
        <div className={`chart-tooltip-change${changeClass}`}>
          {isEqual ? '─' : `${isUp ? '↑' : '↓'} ${formatNumber(diff)}`}
        </div>
      </div>
    );
  };

  return (
    <div className="yoy-chart-wrapper">
      <ResponsiveContainer width="100%" height="100%">
        <ComposedChart data={data} margin={{ top: 20, right: 20, bottom: 0, left: 20 }}>
          <defs>
            <linearGradient id="thisYearGradient" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor="#a6ffea" stopOpacity="0.25" />
              <stop offset="100%" stopColor="#a6ffea" stopOpacity="0" />
            </linearGradient>
          </defs>
          <CartesianGrid stroke="white" strokeOpacity={0.05} vertical={false} />
          <XAxis
            dataKey="label"
            tick={{ fill: 'rgba(255,255,255,0.4)', fontSize: 12 }}
            axisLine={false}
            tickLine={false}
            interval={mode === 'day' ? 2 : 0}
          />
          <Tooltip content={<CustomTooltip />} />
          <Area
            type="monotone"
            dataKey="current"
            stroke="#a6ffea"
            strokeWidth={3}
            fill="url(#thisYearGradient)"
            dot={{ fill: '#a6ffea', r: 2, filter: 'drop-shadow(0 0 6px rgba(166,255,234,0.6))' }}
            activeDot={{ r: 4, fill: '#a6ffea' }}
            isAnimationActive={true}
          />
          <Line
            type="monotone"
            dataKey="previous"
            stroke="#a682ff"
            strokeWidth={2}
            strokeDasharray="6 4"
            dot={false}
            opacity={0.7}
            isAnimationActive={true}
          />
        </ComposedChart>
      </ResponsiveContainer>
    </div>
  );
};

// =====================================================
// Icon Components
// =====================================================

const YouTubeIcon: React.FC<{ className?: string; style?: React.CSSProperties }> = ({ className, style }) => (
  <svg className={className || "platform-tab-icon"} style={style} viewBox="0 0 24 24" fill="currentColor">
    <path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
  </svg>
);

const InstagramIcon: React.FC<{ className?: string; style?: React.CSSProperties }> = ({ className, style }) => (
  <svg className={className || "platform-tab-icon"} style={style} viewBox="0 0 24 24" fill="currentColor">
    <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z" />
  </svg>
);

// =====================================================
// Content Components
// =====================================================

const TopContentItem: React.FC<TopContent> = ({ title, thumbnail, platform, views, engagement, date }) => (
  <div className="top-content-item">
    <div className="top-content-thumbnail">
      <img src={thumbnail} alt={title} />
      <div className="top-content-platform-badge">
        {platform === 'youtube' ? <YouTubeIcon className="top-content-platform-icon" /> : <InstagramIcon className="top-content-platform-icon" />}
      </div>
    </div>
    <div className="top-content-info">
      <h4 className="top-content-title">{title}</h4>
      <div className="top-content-stats">
        <span className="top-content-stat">
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
            <circle cx="12" cy="12" r="3" />
          </svg>
          {formatNumber(views)}
        </span>
        <span className="top-content-stat">
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
          </svg>
          {engagement}
        </span>
      </div>
      <span className="top-content-date">{date}</span>
    </div>
  </div>
);

const AudienceBarChart: React.FC<{ data: { label: string; percentage: number }[]; delay?: number }> = ({ data, delay = 0 }) => {
  const [isAnimated, setIsAnimated] = useState(false);

  useEffect(() => {
    const timer = setTimeout(() => setIsAnimated(true), delay);
    return () => clearTimeout(timer);
  }, [delay]);

  return (
    <div className="audience-bar-chart">
      {data.map((item, index) => (
        <div key={item.label} className="audience-bar-item">
          <span className="audience-bar-label">{item.label}</span>
          <div className="audience-bar-track">
            <div
              className="audience-bar-fill"
              style={{
                width: isAnimated ? `${item.percentage}%` : '0%',
                transitionDelay: `${index * 100}ms`,
              }}
            />
          </div>
          <span className="audience-bar-value">{item.percentage}%</span>
        </div>
      ))}
    </div>
  );
};

const GenderChart: React.FC<{ male: number; female: number; delay?: number }> = ({ male, female, delay = 0 }) => {
  const { t } = useTranslation();
  const [isAnimated, setIsAnimated] = useState(false);

  useEffect(() => {
    const timer = setTimeout(() => setIsAnimated(true), delay);
    return () => clearTimeout(timer);
  }, [delay]);

  return (
    <div className="gender-chart">
      <div className="gender-chart-bars">
        <div className="gender-bar male" style={{ width: isAnimated ? `${male}%` : '0%' }}>
          <span>{male}%</span>
        </div>
        <div className="gender-bar female" style={{ width: isAnimated ? `${female}%` : '0%' }}>
          <span>{female}%</span>
        </div>
      </div>
      <div className="gender-chart-labels">
        <span className="gender-label male">{t('dashboard.male')}</span>
        <span className="gender-label female">{t('dashboard.female')}</span>
      </div>
    </div>
  );
};

// =====================================================
// Main Component
// =====================================================

interface DashboardContentProps {
  onNavigate?: (id: string) => void;
}

const DashboardContent: React.FC<DashboardContentProps> = ({ onNavigate }) => {
  const { t } = useTranslation();
  const [mode, setMode] = useState<'day' | 'month'>('month');

  const [dashboardData, setDashboardData] = useState<DashboardResponse | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<DashboardError | null>(null);
  const [showMockData, setShowMockData] = useState(false);
  const [retryTrigger, setRetryTrigger] = useState(0);

  // 계정 관련 state
  const [accounts, setAccounts] = useState<ConnectedAccount[]>([]);
  const [selectedAccountId, setSelectedAccountId] = useState<number | null>(() => {
    const stored = localStorage.getItem('castad_selected_account_id');
    return stored ? Number(stored) : null;
  });
  const [accountsLoaded, setAccountsLoaded] = useState(false);
  const [accountDropdownOpen, setAccountDropdownOpen] = useState(false);
  const accountDropdownRef = React.useRef<HTMLDivElement>(null);

  // 드롭다운 외부 클릭 시 닫기
  useEffect(() => {
    if (!accountDropdownOpen) return;
    const handleClickOutside = (e: MouseEvent) => {
      if (accountDropdownRef.current && !accountDropdownRef.current.contains(e.target as Node)) {
        setAccountDropdownOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [accountDropdownOpen]);

  // 연결된 YouTube 계정 목록 fetch (마운트 시 1회)
  useEffect(() => {
    const fetchAccounts = async () => {
      try {
        const response = await authenticatedFetch(`${API_URL}/dashboard/accounts`, { method: 'GET' });
        if (!response.ok) return;
        const data = await response.json();
        // snake_case(Python 백엔드) / camelCase 모두 처리
        const list: ConnectedAccount[] = (data.accounts ?? []).map((acc: Record<string, unknown>) => ({
          id: acc.id as number,
          platform: acc.platform as string,
          platformUserId: (acc.platformUserId ?? acc.platform_user_id ?? null) as string | null,
          platformUsername: (acc.platformUsername ?? acc.platform_username ?? null) as string | null,
          channelTitle: (acc.channelTitle ?? acc.channel_title ?? null) as string | null,
          connectedAt: (acc.connectedAt ?? acc.connected_at ?? '') as string,
          isActive: (acc.isActive ?? acc.is_active ?? true) as boolean,
        }));
        setAccounts(list);

        // localStorage 값이 현재 계정 목록에 없으면 초기화
        const storedId = localStorage.getItem('castad_selected_account_id');
        if (storedId && !list.some((a: ConnectedAccount) => a.id === Number(storedId))) {
          localStorage.removeItem('castad_selected_account_id');
          setSelectedAccountId(null);
        }

        if (list.length === 1) {
          setSelectedAccountId(list[0].id);
          localStorage.setItem('castad_selected_account_id', String(list[0].id));
        }
      } catch (err) {
        console.error('Failed to fetch accounts:', err);
      } finally {
        setAccountsLoaded(true);
      }
    };
    fetchAccounts();
  }, []);

  useEffect(() => {
    if (!accountsLoaded) return;
    if (accounts.length > 1 && selectedAccountId === null) {
      setIsLoading(false); // 계정 선택 전 로딩 종료 → 드롭다운 표시
      return;
    }

    const fetchDashboardData = async () => {
      try {
        setIsLoading(true);
        setError(null);

        const params = new URLSearchParams({ mode });
        // selectedAccountId로 계정을 찾아 platformUserId를 API 파라미터로 전달
        if (selectedAccountId !== null) {
          const selectedAccount = accounts.find((a: ConnectedAccount) => a.id === selectedAccountId);
          if (selectedAccount?.platformUserId) {
            params.set('platform_user_id', selectedAccount.platformUserId);
          }
        }

        const response = await authenticatedFetch(`${API_URL}/dashboard/stats?${params}`, { method: 'GET' });

        if (!response.ok) {
          const errorData = await response.json();
          if (errorData.code === 'YOUTUBE_ACCOUNT_SELECTION_REQUIRED') {
            setDashboardData(null);
            return;
          }
          if (errorData.code === 'YOUTUBE_API_FAILED') {
            setError({ code: 'YOUTUBE_API_FAILED', message: t('dashboard.youtubeApiFailed') });
            setDashboardData(null);
            return;
          }
          setError({ code: errorData.code || 'API_ERROR', message: errorData.detail || `API Error: ${response.status}`, reconnect_url: errorData.reconnect_url });
          return;
        }

        const data: DashboardResponse = await response.json();

        if (data.error) {
          setError(data.error);
          setDashboardData(data);
          return;
        }

        setDashboardData(data);
        setError(null);
      } catch (err) {
        console.error('Dashboard API Error:', err);
        setError({ code: 'UNKNOWN', message: err instanceof Error ? err.message : 'Unknown error' });
        setDashboardData(null);
      } finally {
        setIsLoading(false);
      }
    };

    fetchDashboardData();
  }, [mode, selectedAccountId, accountsLoaded, retryTrigger]);

  if (isLoading) {
    return (
      <div className="flex justify-center items-center h-screen">
        <div className="text-lg">{t('dashboard.dataLoading')}</div>
      </div>
    );
  }

  // hasUploads === false이고 error 없음: 업로드 영상 없음 → 전체 mock 데이터 표시 + 안내 배너
  const isEmptyState = dashboardData?.hasUploads === false && !dashboardData?.error;

  // showMockData=true면 전체 mock 강제, 아니면 API 우선 / isEmptyState 시 mock 폴백
  const useReal = !showMockData && !isEmptyState;
  const hasRealContentMetrics = useReal && !!dashboardData?.contentMetrics?.some((m: ContentMetric) => m.value > 0);
  const contentMetrics = hasRealContentMetrics ? dashboardData!.contentMetrics : MOCK_CONTENT_METRICS;

  // 블러 조건: 1)계정 미연결  2)업로드 영상 없음  3)데이터 없음  4)에러 있음  5)실제 지표 없음
  const isBlurred = accounts.length === 0 || isEmptyState || !dashboardData || !!error || !hasRealContentMetrics;
  const topContent = (useReal && dashboardData?.topContent?.length) ? dashboardData.topContent : MOCK_TOP_CONTENT;
  const hasRealAgeGroups = useReal && !!dashboardData?.audienceData?.ageGroups?.some(g => g.percentage > 0);
  const hasRealGender = useReal && ((dashboardData?.audienceData?.gender?.male ?? 0) + (dashboardData?.audienceData?.gender?.female ?? 0)) > 0;
  const hasRealTopRegions = useReal && !!dashboardData?.audienceData?.topRegions?.some(r => r.percentage > 0);
  const hasRealAudienceData = hasRealAgeGroups && hasRealGender && hasRealTopRegions;
  const audienceData = hasRealAudienceData ? dashboardData!.audienceData : MOCK_AUDIENCE_DATA;

  // mode별 차트 데이터를 ChartDataPoint 통합 형식으로 변환
  const chartData: ChartDataPoint[] = mode === 'month'
    ? ((useReal && dashboardData?.monthlyData?.length)
        ? dashboardData.monthlyData.map((d: MonthlyData) => ({ label: d.month, current: d.thisYear, previous: d.lastYear }))
        : MOCK_MONTHLY_DATA.map((d: MonthlyData) => ({ label: t(d.month), current: d.thisYear, previous: d.lastYear })))
    : ((useReal && dashboardData?.dailyData?.length)
        ? dashboardData.dailyData.map((d: DailyData) => ({ label: d.date, current: d.thisPeriod, previous: d.lastPeriod }))
        : MOCK_DAILY_DATA.map((d: DailyData) => ({ label: d.date, current: d.thisPeriod, previous: d.lastPeriod })));

  // mode별 차트 레이블
  const chartCurrentLabel = mode === 'month' ? t('dashboard.chartThisYear') : t('dashboard.chartThisMonth');
  const chartPreviousLabel = mode === 'month' ? t('dashboard.chartLastYear') : t('dashboard.chartLastMonth');
  const chartSectionTitle = mode === 'month' ? t('dashboard.yearOverYear') : t('dashboard.monthOverMonth');

  const lastUpdated = new Date().toLocaleDateString('ko-KR', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  });

  return (
    <div className="dashboard-container">
      {/* 업로드 영상 없음 배너 */}
      {isEmptyState && (
        <div className="mb-4 p-4 border-l-4 rounded" style={{ background: 'rgba(166,255,234,0.06)', borderColor: '#a6ffea' }}>
          <div className="flex items-center gap-3">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#a6ffea" strokeWidth="2" style={{ flexShrink: 0 }}>
              <path d="M15 10l4.553-2.069A1 1 0 0121 8.87v6.26a1 1 0 01-1.447.899L15 14M3 8a2 2 0 012-2h10a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2V8z" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
            <div>
              <p style={{ color: '#a6ffea', fontSize: '20px', fontWeight: 600, marginBottom: '2px' }}>{t('dashboard.noUploadsTitle')}</p>
              <p style={{ color: 'rgba(255,255,255,0.5)', fontSize: '16px' }}>{t('dashboard.noUploadsDesc')}</p>
            </div>
          </div>
        </div>
      )}

      {/* 48시간 지연 안내 배너 */}
      {dashboardData && !isEmptyState && !hasRealContentMetrics && !showMockData && (
        <div className="mb-4 p-4 border-l-4 rounded" style={{ background: 'rgba(255,210,100,0.06)', borderColor: '#ffd264' }}>
          <div className="flex items-center gap-3">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#ffd264" strokeWidth="2" style={{ flexShrink: 0 }}>
              <circle cx="12" cy="12" r="10" />
              <path d="M12 6v6l4 2" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
            <div>
              <p style={{ color: '#ffd264', fontSize: '16px', fontWeight: 600, marginBottom: '2px' }}>{t('dashboard.dataDelayTitle')}</p>
              <p style={{ color: 'rgba(255,255,255,0.5)', fontSize: '14px' }}>{t('dashboard.dataDelayDesc')}</p>
            </div>
          </div>
        </div>
      )}

      {/* 에러 배너 */}
      {error && (
        <div className="mb-4 p-4 bg-yellow-50 border-l-4 border-yellow-400 text-yellow-800 rounded">
          <div className="flex items-center justify-between">
            <div className="flex items-center">
              <svg className="w-5 h-5 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
                <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
              </svg>
              <p className="font-semibold">{error.message}</p>
            </div>
            {error.code === 'YOUTUBE_TOKEN_EXPIRED' && (
              <button
                onClick={() => onNavigate?.('내 정보')}
                className="ml-4 px-4 py-2 bg-yellow-600 text-white rounded hover:bg-yellow-700 whitespace-nowrap"
              >
                {t('dashboard.reconnectButton')}
              </button>
            )}
            {error.code === 'YOUTUBE_NOT_CONNECTED' && (
              <button
                onClick={() => onNavigate?.('내 정보')}
                className="ml-4 px-4 py-2 bg-yellow-600 text-white rounded hover:bg-yellow-700 whitespace-nowrap"
              >
                {t('dashboard.connectButton')}
              </button>
            )}
            {(error.code === 'YOUTUBE_API_FAILED' || error.code === 'DASHBOARD_DATA_ERROR') && (
              <button
                onClick={() => { setError(null); setRetryTrigger((n: number) => n + 1); }}
                className="ml-4 px-4 py-2 bg-yellow-600 text-white rounded hover:bg-yellow-700 whitespace-nowrap"
              >
                {t('dashboard.retryButton')}
              </button>
            )}
          </div>
        </div>
      )}

      {/* Header */}
      <AnimatedSection delay={0} className="relative z-10">
        <div className="dashboard-header-row">
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
              <h1 className="dashboard-title">{t('dashboard.title')}</h1>
              {/* 계정 드롭다운: 연결된 계정이 2개 이상일 때만 표시 */}
              {accounts.length > 1 && (
                <div ref={accountDropdownRef} style={{ position: 'relative', zIndex: 11 }}>
                  {/* 트리거 버튼 */}
                  <button
                    onClick={() => setAccountDropdownOpen(!accountDropdownOpen)}
                    style={{
                      display: 'flex', alignItems: 'center', gap: '6px',
                      background: '#001a1c',
                      border: '1px solid rgba(255,255,255,0.15)',
                      borderRadius: '8px',
                      color: 'rgba(255,255,255,0.85)',
                      padding: '5px 10px',
                      fontSize: '13px',
                      cursor: 'pointer',
                      minWidth: '160px',
                    }}
                  >
                    {(() => {
                      const acc = accounts.find((a: ConnectedAccount) => a.id === selectedAccountId);
                      return acc ? (
                        <>
                          {acc.platform === 'youtube'
                            ? <YouTubeIcon style={{ width: 14, height: 14, color: '#ff4444', flexShrink: 0 }} />
                            : <InstagramIcon style={{ width: 14, height: 14, color: '#e1306c', flexShrink: 0 }} />}
                          <span style={{ flex: 1, textAlign: 'left', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {acc.channelTitle ?? acc.platformUsername ?? String(acc.id)}
                          </span>
                        </>
                      ) : (
                        <span style={{ flex: 1, color: 'rgba(255,255,255,0.4)' }}>{t('dashboard.selectAccount')}</span>
                      );
                    })()}
                    <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.5)" strokeWidth="2" style={{ flexShrink: 0, marginLeft: 'auto' }}>
                      <path d="M6 9l6 6 6-6" />
                    </svg>
                  </button>
                  {/* 드롭다운 목록 */}
                  {accountDropdownOpen && (
                    <div style={{
                      position: 'absolute', top: 'calc(100% + 4px)', left: 0,
                      zIndex: 9999,
                      background: '#001a1c',
                      border: '1px solid rgba(255,255,255,0.15)',
                      borderRadius: '8px',
                      overflow: 'hidden',
                      minWidth: '100%',
                      boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
                    }}>
                      {accounts.map((acc: ConnectedAccount) => (
                        <div
                          key={acc.id}
                          onClick={() => {
                            setSelectedAccountId(acc.id);
                            localStorage.setItem('castad_selected_account_id', String(acc.id));
                            setAccountDropdownOpen(false);
                          }}
                          style={{
                            display: 'flex', alignItems: 'center', gap: '8px',
                            padding: '8px 12px',
                            cursor: 'pointer',
                            fontSize: '13px',
                            background: acc.id === selectedAccountId ? 'rgba(255,255,255,0.08)' : 'transparent',
                            color: 'rgba(255,255,255,0.85)',
                          }}
                          onMouseEnter={(e: React.MouseEvent<HTMLDivElement>) => { e.currentTarget.style.background = 'rgba(255,255,255,0.1)'; }}
                          onMouseLeave={(e: React.MouseEvent<HTMLDivElement>) => { e.currentTarget.style.background = acc.id === selectedAccountId ? 'rgba(255,255,255,0.08)' : 'transparent'; }}
                        >
                          {acc.platform === 'youtube'
                            ? <YouTubeIcon style={{ width: 14, height: 14, color: '#ff4444', flexShrink: 0 }} />
                            : <InstagramIcon style={{ width: 14, height: 14, color: '#e1306c', flexShrink: 0 }} />}
                          <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {acc.channelTitle ?? acc.platformUsername ?? acc.platformUserId}
                          </span>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              )}
            </div>
            <p className="dashboard-description">{t('dashboard.description')}</p>
          </div>
          <span className="dashboard-last-updated">{t('dashboard.lastUpdated')} {lastUpdated}</span>
        </div>
      </AnimatedSection>

      {/* Content Performance Section */}
      <AnimatedSection delay={100} className="dashboard-section">
        <div className="flex items-center justify-between mb-4">
          <div>
            <h2 className="dashboard-section-title" style={{ marginBottom: '2px' }}>{t('dashboard.contentPerformance')}</h2>
            <p style={{ fontSize: '14px', color: 'rgba(255,255,255,0.4)', margin: 0 }}>{t('dashboard.recentVideosDesc')}</p>
          </div>
          <div className="mode-toggle">
            <button
              className={`mode-btn ${mode === 'month' ? 'active' : ''}`}
              onClick={() => setMode('month')}
            >
              {t('dashboard.modeAnnual')}
            </button>
            <button
              className={`mode-btn ${mode === 'day' ? 'active' : ''}`}
              onClick={() => setMode('day')}
            >
              {t('dashboard.modeMonthly')}
            </button>
          </div>
        </div>
        <div className="stats-grid-8" style={isBlurred && !showMockData ? { filter: 'blur(4px)', pointerEvents: 'none', userSelect: 'none' } : {}}>
          {contentMetrics.map((metric: ContentMetric, index: number) => (
            <AnimatedItem key={metric.id} index={index} baseDelay={200}>
              <StatCard {...metric} />
            </AnimatedItem>
          ))}
        </div>
      </AnimatedSection>

      {/* Two Column Layout */}
      <div className="dashboard-two-column" style={isBlurred && !showMockData ? { filter: 'blur(4px)', pointerEvents: 'none', userSelect: 'none' } : {}}>
          {/* 추이 차트 섹션 (mode=month: 연간, mode=day: 일별) */}
          <AnimatedSection delay={600}>
            <div className="yoy-chart-card">
              <div className="yoy-chart-header">
                <h2 className="dashboard-section-title">{chartSectionTitle}</h2>
                <div className="chart-legend-dual">
                  <div className="chart-legend-item">
                    <span className="chart-legend-line solid"></span>
                    <span className="chart-legend-text">{chartCurrentLabel}</span>
                  </div>
                  <div className="chart-legend-item">
                    <span className="chart-legend-line dashed"></span>
                    <span className="chart-legend-text">{chartPreviousLabel}</span>
                  </div>
                </div>
              </div>
              <div className="yoy-chart-container">
                <YearOverYearChart
                  data={chartData}
                  currentLabel={chartCurrentLabel}
                  previousLabel={chartPreviousLabel}
                  mode={mode}
                  noDataLabel={t('dashboard.noDataInPeriod')}
                />
              </div>
            </div>
          </AnimatedSection>

          {/* Top Content Section */}
          <AnimatedSection delay={700}>
            <div className="top-content-card">
              <h2 className="dashboard-section-title">{t('dashboard.popularContent')}</h2>
              <div className="top-content-list">
                {topContent.map((content, index) => (
                  <AnimatedItem key={content.id} index={index} baseDelay={800}>
                    <TopContentItem {...content} />
                  </AnimatedItem>
                ))}
              </div>
            </div>
          </AnimatedSection>
        </div>

      {/* Audience Insights Section */}
      <AnimatedSection delay={1000} className="audience-section">
        <div style={{ marginBottom: '16px' }}>
          <h2 className="dashboard-section-title" style={{ marginBottom: '2px' }}>{t('dashboard.audienceInsights')}</h2>
          <p style={{ fontSize: '14px', color: 'rgba(255,255,255,0.4)', margin: 0 }}>{t('dashboard.channelStatsDesc')}</p>
        </div>
        <div style={{ position: 'relative' }}>
          <div className="audience-cards" style={!hasRealAudienceData && !showMockData ? { filter: 'blur(4px)', pointerEvents: 'none', userSelect: 'none' } : {}}>
            <AnimatedItem index={0} baseDelay={1100}>
              <div className="audience-card">
                <h3 className="audience-card-title">{t('dashboard.ageDistribution')}</h3>
                <AudienceBarChart data={audienceData.ageGroups} delay={1200} />
              </div>
            </AnimatedItem>
            <AnimatedItem index={1} baseDelay={1100}>
              <div className="audience-card">
                <h3 className="audience-card-title">{t('dashboard.genderDistribution')}</h3>
                <GenderChart male={audienceData.gender.male} female={audienceData.gender.female} delay={1300} />
              </div>
            </AnimatedItem>
            <AnimatedItem index={2} baseDelay={1100}>
              <div className="audience-card">
                <h3 className="audience-card-title">{t('dashboard.topRegions')}</h3>
                <AudienceBarChart data={audienceData.topRegions.map(r => ({ label: r.region, percentage: r.percentage }))} delay={1400} />
              </div>
            </AnimatedItem>
          </div>
          {dashboardData && !isEmptyState && !hasRealAudienceData && !showMockData && (
            <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', pointerEvents: 'none' }}>
              <div style={{
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px',
                background: 'rgba(0,0,0,0.45)',
                backdropFilter: 'blur(2px)',
                borderRadius: '12px',
                padding: '20px 28px',
              }}>
                <p style={{ color: 'rgba(255,255,255,0.85)', fontSize: '16px', fontWeight: 500, margin: 0, textAlign: 'center' }}>
                  {t('dashboard.noAudienceData')}
                </p>
              </div>
            </div>
          )}
        </div>
      </AnimatedSection>

      {/* mock 데이터 보기 버튼 */}
      <button
        onClick={() => setShowMockData(prev => !prev)}
        style={{
          position: 'fixed',
          bottom: '24px',
          right: '24px',
          zIndex: 9999,
          display: 'flex',
          alignItems: 'center',
          gap: '6px',
          background: showMockData ? 'rgba(255,100,100,0.15)' : 'rgba(166,255,234,0.12)',
          border: `1px solid ${showMockData ? 'rgba(255,100,100,0.4)' : 'rgba(166,255,234,0.4)'}`,
          borderRadius: '10px',
          color: showMockData ? 'rgba(255,150,150,0.9)' : '#a6ffea',
          padding: '8px 14px',
          fontSize: '12px',
          fontWeight: 600,
          cursor: 'pointer',
          backdropFilter: 'blur(8px)',
        }}
      >
        <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          {showMockData
            ? <><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94"/><path d="M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19"/><line x1="1" y1="1" x2="23" y2="23"/></>
            : <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>
          }
        </svg>
        {showMockData ? t('dashboard.sampleHide') : t('dashboard.sampleShow')}
      </button>
    </div>
  );
};

export default DashboardContent;
