import {
  CrawlingResponse,
  LyricGenerateRequest,
  LyricGenerateResponse,
  LyricStatusResponse,
  LyricDetailResponse,
  SongGenerateRequest,
  SongGenerateResponse,
  SongStatusResponse,
  SongDownloadResponse,
  SubtitleStatusResponse,
  VideoGenerateResponse,
  VideoStatusResponse,
  VideoDownloadResponse,
  VideosListResponse,
  ImageUrlItem,
  ImageUploadResponse,
  KakaoLoginUrlResponse,
  KakaoCallbackResponse,
  TokenRefreshResponse,
  UserMeResponse,
  YouTubeConnectResponse,
  SocialAccountsResponse,
  SocialAccountResponse,
  SocialDisconnectResponse,
  SocialUploadRequest,
  SocialUploadResponse,
  SocialUploadStatusResponse,
  TokenExpiredErrorResponse,
  YTAutoSeoRequest,
  YTAutoSeoResponse,
  UserCreditsResponse,
  VideoDetailItem,
  CommentsResponse,
  CommentItem,
  LikeToggleResponse,
} from '../types/api';

export const API_URL = import.meta.env.VITE_API_URL || 'http://40.82.133.44';
console.log('[API] API_URL:', API_URL);
console.log('[API] VITE_API_URL env:', import.meta.env.VITE_API_URL);

// 크롤링 타임아웃: 5분
const CRAWL_TIMEOUT = 5 * 60 * 1000;

export async function crawlUrl(url: string): Promise<CrawlingResponse> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), CRAWL_TIMEOUT);

  try {
    const response = await fetch(`${API_URL}/crawling`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ url }),
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return response.json();
  } catch (error) {
    clearTimeout(timeoutId);
    if (error instanceof Error && error.name === 'AbortError') {
      throw new Error('크롤링 요청 시간이 초과되었습니다. 다시 시도해주세요.');
    }
    throw error;
  }
}

// 가사 생성 API
export async function generateLyric(request: LyricGenerateRequest): Promise<LyricGenerateResponse> {
  const response = await authenticatedFetch(`${API_URL}/lyric/generate`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(request),
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 가사 상태 조회 API
export async function getLyricStatus(taskId: string): Promise<LyricStatusResponse> {
  const response = await authenticatedFetch(`${API_URL}/lyric/status/${taskId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 가사 상세 조회 API
export async function getLyricDetail(taskId: string): Promise<LyricDetailResponse> {
  const response = await authenticatedFetch(`${API_URL}/lyric/${taskId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 가사 생성 완료까지 폴링 (2분 타임아웃, 1초 간격)
const LYRIC_POLL_TIMEOUT = 2 * 60 * 1000; // 2분
const LYRIC_POLL_INTERVAL = 1000; // 1초

export async function waitForLyricComplete(
  taskId: string,
  onStatusChange?: (status: string) => void
): Promise<LyricDetailResponse> {
  const startTime = Date.now();

  // 재귀적으로 폴링하는 방식으로 변경 (async/await 제대로 동작)
  const poll = async (): Promise<LyricDetailResponse> => {
    // 2분 타임아웃 체크
    if (Date.now() - startTime > LYRIC_POLL_TIMEOUT) {
      throw new Error('TIMEOUT');
    }

    try {
      const statusResponse = await getLyricStatus(taskId);
      onStatusChange?.(statusResponse.status);

      if (statusResponse.status === 'completed') {
        // 완료되면 상세 조회로 가사 가져오기
        const detailResponse = await getLyricDetail(taskId);
        return detailResponse;
      } else if (statusResponse.status === 'failed') {
        throw new Error(statusResponse.error_message || '가사 생성에 실패했습니다.');
      }

      // processing은 대기 후 재시도
      await new Promise(resolve => setTimeout(resolve, LYRIC_POLL_INTERVAL));
      return poll();
    } catch (error) {
      throw error;
    }
  };

  return poll();
}

// 노래 생성 API (task_id는 URL 경로에 포함)
export async function generateSong(taskId: string, request: SongGenerateRequest): Promise<SongGenerateResponse> {
  const response = await authenticatedFetch(`${API_URL}/song/generate/${taskId}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(request),
  });

  if (!response.ok) {
    const errorBody = await response.json().catch(() => null);
    console.error('[generateSong] 422 detail:', JSON.stringify(errorBody));
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 노래 상태 조회 API (Suno Polling)
export async function getSongStatus(songId: string): Promise<SongStatusResponse> {
  const response = await authenticatedFetch(`${API_URL}/song/status/${songId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 노래 다운로드 API
export async function downloadSong(taskId: string): Promise<SongDownloadResponse> {
  const response = await authenticatedFetch(`${API_URL}/song/download/${taskId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 노래 생성 완료까지 폴링 (5분 타임아웃, 3초 간격)
// Suno API 상태: PENDING, processing, SUCCESS, failed, error
const SONG_POLL_TIMEOUT = 5 * 60 * 1000; // 5분
const SONG_POLL_INTERVAL = 3000; // 3초
const SONG_URL_RETRY_DELAY = 4000; // SUCCESS인데 song_result_url 없을 때 재요청 대기 시간 (4초)

export async function waitForSongComplete(
  songId: string,
  onStatusChange?: (status: string) => void
): Promise<SongStatusResponse> {
  const startTime = Date.now();

  const poll = async (): Promise<SongStatusResponse> => {
    // 5분 타임아웃 체크
    if (Date.now() - startTime > SONG_POLL_TIMEOUT) {
      throw new Error('TIMEOUT');
    }

    try {
      const response = await getSongStatus(songId);
      onStatusChange?.(response.status);

      // SUCCESS: Suno API 노래 생성 완료
      if (response.status === 'SUCCESS' && response.success) {
        // song_result_url이 있으면 완료
        if (response.song_result_url) {
          return response;
        }
        // song_result_url이 없으면 4초 후 재요청
        await new Promise(resolve => setTimeout(resolve, SONG_URL_RETRY_DELAY));
        return poll();
      }

      // failed 또는 error: Suno API 노래 생성 실패
      if (response.status === 'failed' || response.status === 'error') {
        throw new Error(response.error_message || '노래 생성에 실패했습니다.');
      }

      // PENDING, processing 등은 대기 후 재시도
      await new Promise(resolve => setTimeout(resolve, SONG_POLL_INTERVAL));
      return poll();
    } catch (error) {
      throw error;
    }
  };

  return poll();
}

// 자막 상태 확인 API
export async function getSubtitleStatus(taskId: string): Promise<SubtitleStatusResponse> {
  const response = await authenticatedFetch(`${API_URL}/lyric/subtitle/status/${taskId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 자막 완료까지 폴링 (5초 간격, 10분 타임아웃)
const SUBTITLE_POLL_INTERVAL = 5000;
const SUBTITLE_POLL_TIMEOUT = 5 * 60 * 1000;

export async function waitForSubtitleComplete(
  taskId: string,
  onStatusChange?: (status: string) => void
): Promise<SubtitleStatusResponse> {
  const startTime = Date.now();

  const poll = async (): Promise<SubtitleStatusResponse> => {
    if (Date.now() - startTime > SUBTITLE_POLL_TIMEOUT) {
      throw new Error('TIMEOUT');
    }

    const response = await getSubtitleStatus(taskId);
    onStatusChange?.(response.status);

    if (response.status === 'completed') {
      return response;
    }

    if (response.status === 'failed' || response.status === 'error') {
      throw new Error(response.message || '자막 생성에 실패했습니다.');
    }

    await new Promise(resolve => setTimeout(resolve, SUBTITLE_POLL_INTERVAL));
    return poll();
  };

  return poll();
}

// 영상 생성 API
export async function generateVideo(taskId: string, orientation: 'vertical' | 'horizontal' = 'vertical'): Promise<VideoGenerateResponse> {
  const response = await authenticatedFetch(`${API_URL}/video/generate/${taskId}?orientation=${orientation}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 영상 상태 확인 API
export async function getVideoStatus(taskId: string): Promise<VideoStatusResponse> {
  const response = await authenticatedFetch(`${API_URL}/video/status/${taskId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 영상 다운로드(결과 조회) API
// export async function downloadVideo(taskId: string): Promise<VideoDownloadResponse> {
//   const response = await fetch(`${API_URL}/video/download/${taskId}`, {
//     method: 'GET',
//     headers: {
//       ...getAuthHeader(),
//     },
//   });

//   if (!response.ok) {
//     throw new Error(`HTTP error! status: ${response.status}`);
//   }

//   return response.json();
// }

// 비디오 목록 조회 API
export async function getVideosList(page: number = 1, pageSize: number = 10): Promise<VideosListResponse> {
  const response = await authenticatedFetch(`${API_URL}/archive/videos/?page=${page}&page_size=${pageSize}&_t=${Date.now()}`, {
    method: 'GET',
    headers: {
      'Cache-Control': 'no-cache, no-store, must-revalidate',
      'Pragma': 'no-cache',
    },
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// task_id로 video_id 조회 (소셜 업로드용)
export async function getVideoIdByTaskId(taskId: string): Promise<number | null> {
  try {
    const response = await getVideosList(1, 50);
    const found = response.items.find(v => v.task_id === taskId);
    return found?.video_id ?? null;
  } catch {
    return null;
  }
}

// 비디오 삭제 API (개별 비디오 삭제)
export async function deleteVideo(videoId: number): Promise<void> {
  const response = await authenticatedFetch(`${API_URL}/archive/videos/${videoId}`, {
    method: 'DELETE',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
}

// 전체 사용자 영상 목록 조회 API (ADO2 콘텐츠 갤러리용)
export async function getAllVideos(
  page: number = 1,
  pageSize: number = 20,
  sortBy: 'created_at' | 'like_count' | 'comment_count' = 'created_at',
  storeName: string = '',
  order: 'desc' | 'asc' = 'desc',
  region: string = '',
): Promise<VideosListResponse> {
  const params = new URLSearchParams({
    page: String(page),
    page_size: String(pageSize),
    sort_by: sortBy,
    order,
  });
  if (storeName.trim()) params.set('store_name', storeName.trim());
  if (region.trim()) params.set('region', region.trim());
  const response = await authenticatedFetch(`${API_URL}/video/all?${params.toString()}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 단일 영상 상세 조회 API
export async function getVideoById(videoId: string): Promise<VideoDetailItem> {
  const response = await authenticatedFetch(`${API_URL}/video/${videoId}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 댓글 목록 조회
export async function getVideoComments(videoId: string, page: number = 1, pageSize: number = 20): Promise<CommentsResponse> {
  const response = await authenticatedFetch(`${API_URL}/comment/video/${videoId}?page=${page}&page_size=${pageSize}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 댓글 작성
export async function postVideoComment(videoId: string, content: string, nickname?: string, parentId?: number): Promise<CommentItem> {
  const response = await authenticatedFetch(`${API_URL}/comment/video/${videoId}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ content, nickname: nickname || '익명', parent_id: parentId ?? null }),
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 댓글 삭제
export async function deleteComment(commentId: number): Promise<void> {
  const response = await authenticatedFetch(`${API_URL}/comment/${commentId}`, {
    method: 'DELETE',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
}

// 좋아요 토글
export async function toggleVideoLike(videoId: string): Promise<LikeToggleResponse> {
  const response = await authenticatedFetch(`${API_URL}/video/${videoId}/like`, {
    method: 'POST',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 이미지 업로드 API (multipart/form-data)
// 타임아웃: 5분 (많은 이미지 업로드 시 시간이 오래 걸릴 수 있음)
const IMAGE_UPLOAD_TIMEOUT = 5 * 60 * 1000;

export async function uploadImages(
  imageUrls: ImageUrlItem[],
  files: File[]
): Promise<ImageUploadResponse> {
  const formData = new FormData();

  // URL 이미지들을 images_json으로 전달
  if (imageUrls.length > 0) {
    formData.append('images_json', JSON.stringify(imageUrls));
  }

  // 파일들을 files로 전달
  files.forEach((file) => {
    formData.append('files', file);
  });

  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), IMAGE_UPLOAD_TIMEOUT);

  try {
    const response = await authenticatedFetch(`${API_URL}/image/upload/blob`, {
      method: 'POST',
      body: formData,
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return response.json();
  } catch (error) {
    clearTimeout(timeoutId);
    if (error instanceof Error && error.name === 'AbortError') {
      throw new Error('이미지 업로드 시간이 초과되었습니다. 다시 시도해주세요.');
    }
    throw error;
  }
}

// 영상 생성 완료까지 폴링 (10분 타임아웃, 3초 간격)
const VIDEO_POLL_TIMEOUT = 10 * 60 * 1000; // 10분
const VIDEO_POLL_INTERVAL = 3000; // 3초

export async function waitForVideoComplete(
  taskId: string,
  onStatusChange?: (status: string) => void
): Promise<VideoStatusResponse> {
  const startTime = Date.now();

  // 재귀적으로 폴링하는 방식으로 변경 (async/await 제대로 동작)
  const poll = async (): Promise<VideoStatusResponse> => {
    // 10분 타임아웃 체크
    if (Date.now() - startTime > VIDEO_POLL_TIMEOUT) {
      throw new Error('TIMEOUT');
    }

    try {
      const statusResponse = await getVideoStatus(taskId);
      // render_data.status를 전달 (planned, waiting, transcribing, rendering, succeeded, failed)
      const renderStatus = statusResponse.render_data?.status;
      onStatusChange?.(renderStatus || statusResponse.status);

      // render_data.status가 "succeeded"일 때만 완료
      if (renderStatus === 'succeeded') {
        return statusResponse;
      } else if (renderStatus === 'failed' || statusResponse.status === 'FAILED' || statusResponse.status === 'failed') {
        throw new Error(statusResponse.error_message || 'Video generation failed');
      }

      // pending, rendering 등은 대기 후 재시도
      await new Promise(resolve => setTimeout(resolve, VIDEO_POLL_INTERVAL));
      return poll();
    } catch (error) {
      throw error;
    }
  };

  return poll();
}

// ============================================
// 카카오 인증 API
// ============================================

// 토큰 저장 키
const ACCESS_TOKEN_KEY = 'castad_access_token';
const REFRESH_TOKEN_KEY = 'castad_refresh_token';

// 토큰 저장
export function saveTokens(accessToken: string, refreshToken: string) {
  localStorage.setItem(ACCESS_TOKEN_KEY, accessToken);
  localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken);
}

// 토큰 가져오기
export function getAccessToken(): string | null {
  return localStorage.getItem(ACCESS_TOKEN_KEY);
}

export function getRefreshToken(): string | null {
  return localStorage.getItem(REFRESH_TOKEN_KEY);
}

// 토큰 삭제
export function clearTokens() {
  localStorage.removeItem(ACCESS_TOKEN_KEY);
  localStorage.removeItem(REFRESH_TOKEN_KEY);
}

// 인증 헤더 생성
function getAuthHeader(): HeadersInit {
  const token = getAccessToken();
  return token ? { 'Authorization': `Bearer ${token}` } : {};
}

// 토큰 갱신 중복 방지를 위한 Promise (싱글톤 패턴)
let refreshPromise: Promise<TokenRefreshResponse> | null = null;

// 로그인 페이지로 리다이렉트 (토큰 만료 시)
function redirectToLogin() {
  // 토큰 삭제
  clearTokens();
  // localStorage 정리
  localStorage.removeItem('castad_view_mode');
  localStorage.removeItem('castad_analysis_data');
  localStorage.removeItem('castad_wizard_step');
  localStorage.removeItem('castad_active_item');
  // 홈으로 리다이렉트
  window.location.href = '/';
}

// 401 에러 시 자동으로 토큰 갱신 후 재요청하는 래퍼 함수
export async function authenticatedFetch(
  url: string,
  options: RequestInit = {}
): Promise<Response> {
  // 인증 헤더 + 캐시 방지 헤더 추가
  const headers: HeadersInit = {
    ...options.headers,
    ...getAuthHeader(),
    'Cache-Control': 'no-cache, no-store, must-revalidate',
    'Pragma': 'no-cache',
  };

  let response = await fetch(url, { ...options, headers });

  // 401 에러 시 에러 코드에 따라 처리
  if (response.status === 401) {
    const errorBody = await response.json().catch(() => null);
    const errorCode = errorBody?.detail?.code;

    if (errorCode !== 'TOKEN_EXPIRED') {
      // INVALID_TOKEN 등 갱신으로 해결 불가한 경우 즉시 로그인 이동
      redirectToLogin();
      throw new Error(errorCode ?? 'Unauthorized');
    }

    try {
      if (!refreshPromise) {
        refreshPromise = refreshAccessToken().finally(() => {
          refreshPromise = null;
        });
      }

      await refreshPromise;

      // 새 토큰으로 재요청
      const newHeaders: HeadersInit = {
        ...options.headers,
        ...getAuthHeader(),
        'Cache-Control': 'no-cache, no-store, must-revalidate',
        'Pragma': 'no-cache',
      };
      response = await fetch(url, { ...options, headers: newHeaders });
    } catch (refreshError) {
      console.error('Token refresh failed:', refreshError);
      redirectToLogin();
      throw refreshError;
    }
  }

  return response;
}

// 카카오 로그인 URL 획득
export async function getKakaoLoginUrl(): Promise<KakaoLoginUrlResponse> {
  const response = await fetch(`${API_URL}/user/auth/kakao/login`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 카카오 콜백 처리 (인가 코드로 JWT 토큰 발급)
// 1. callback 호출 후 2. verify로 토큰 발급
export async function kakaoCallback(code: string): Promise<KakaoCallbackResponse> {
  // 1단계: 콜백 처리
  const callbackResponse = await fetch(`${API_URL}/user/auth/kakao/callback?code=${encodeURIComponent(code)}`, {
    method: 'GET',
  });

  if (!callbackResponse.ok) {
    throw new Error(`Callback HTTP error! status: ${callbackResponse.status}`);
  }

  // 2단계: 코드 검증 및 토큰 발급
  const verifyResponse = await fetch(`${API_URL}/user/auth/kakao/verify`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ code }),
  });

  if (!verifyResponse.ok) {
    throw new Error(`Verify HTTP error! status: ${verifyResponse.status}`);
  }

  const data: KakaoCallbackResponse = await verifyResponse.json();
  

  // 토큰 저장
  saveTokens(data.access_token, data.refresh_token);

  return data;
}

// Access Token 갱신
export async function refreshAccessToken(): Promise<TokenRefreshResponse> {
  const refreshToken = getRefreshToken();

  if (!refreshToken) {
    console.error('[Auth] No refresh token available');
    throw new Error('No refresh token available');
  }

  console.log('[Auth] Attempting to refresh access token...');

  const response = await fetch(`${API_URL}/user/auth/refresh`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': 'no-cache, no-store, must-revalidate',
      'Pragma': 'no-cache',
    },
    body: JSON.stringify({ refresh_token: refreshToken }),
  });

  if (!response.ok) {
    console.error(`[Auth] Token refresh failed with status: ${response.status}`);
    // 리프레시 토큰도 만료된 경우 토큰 삭제
    if (response.status === 401 || response.status === 403) {
      console.log('[Auth] Refresh token expired, clearing tokens...');
      clearTokens();
    }
    throw new Error(`Token refresh failed: ${response.status}`);
  }

  const data: TokenRefreshResponse = await response.json();
  console.log('[Auth] Token refresh successful');

  // 새 액세스 토큰과 리프레시 토큰을 localStorage에 갱신
  saveTokens(data.access_token, data.refresh_token);

  return data;
}

// 로컬 스토리지 전체 정리
function clearAllLocalData() {
  clearTokens();
  localStorage.removeItem('castad_view_mode');
  localStorage.removeItem('castad_analysis_data');
  localStorage.removeItem('castad_wizard_step');
  localStorage.removeItem('castad_active_item');
  localStorage.removeItem('castad_song_task_id');
  localStorage.removeItem('castad_image_task_id');
  localStorage.removeItem('castad_song_generation');
  localStorage.removeItem('castad_video_generation');
  localStorage.removeItem('castad_video_ratio');
}

// 로그아웃
export async function logout(): Promise<void> {
  const response = await authenticatedFetch(`${API_URL}/user/auth/logout`, {
    method: 'POST',
  });

  // 응답과 관계없이 로컬 데이터 전체 삭제
  clearAllLocalData();

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
}

// 모든 기기에서 로그아웃
export async function logoutAll(): Promise<void> {
  const response = await authenticatedFetch(`${API_URL}/user/auth/logout/all`, {
    method: 'POST',
  });

  // 응답과 관계없이 로컬 데이터 전체 삭제
  clearAllLocalData();

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
}

// 현재 사용자 정보 조회
export async function getUserMe(): Promise<UserMeResponse> {
  const response = await authenticatedFetch(`${API_URL}/user/auth/me`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 사용자 크레딧 조회
export async function getUserCredits(): Promise<UserCreditsResponse> {
  const response = await authenticatedFetch(`${API_URL}/user/auth/me/credits`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 크레딧 충전 요청
export async function requestCreditCharge(amount: number, note: string): Promise<void> {
  const response = await authenticatedFetch(`${API_URL}/user/credits/charge-requests`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ requested_amount: amount, message: note }),
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
}

// 로그인 여부 확인
export function isLoggedIn(): boolean {
  return !!getAccessToken();
}

// ============================================
// 숙소 검색 & 자동완성 API
// ============================================

export interface AccommodationSearchItem {
  address: string;
  roadAddress: string;
  title: string;
}

export interface AccommodationSearchResponse {
  count: number;
  items: AccommodationSearchItem[];
  query: string;
}

export interface AutocompleteRequest {
  address: string;
  roadAddress: string;
  title: string;
}

// 숙소 검색 API (업체명 자동완성용)
export async function searchAccommodation(query: string): Promise<AccommodationSearchResponse> {
  const response = await authenticatedFetch(`${API_URL}/search/accommodation?query=${encodeURIComponent(query)}`, {
    method: 'GET',
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json();
}

// 자동완성 API (업체 정보로 크롤링)
export async function autocomplete(request: AutocompleteRequest): Promise<CrawlingResponse> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), CRAWL_TIMEOUT);

  try {
    const response = await authenticatedFetch(`${API_URL}/autocomplete`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(request),
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return response.json();
  } catch (error) {
    clearTimeout(timeoutId);
    if (error instanceof Error && error.name === 'AbortError') {
      throw new Error('자동완성 요청 시간이 초과되었습니다. 다시 시도해주세요.');
    }
    throw error;
  }
}

// 업체명·주소 직접 입력으로 마케팅 분석
export async function marketingAnalysis(storeName: string, address: string): Promise<CrawlingResponse> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), CRAWL_TIMEOUT);

  try {
    const response = await authenticatedFetch(`${API_URL}/marketing`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ store_name: storeName, address }),
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return response.json();
  } catch (error) {
    clearTimeout(timeoutId);
    if (error instanceof Error && error.name === 'AbortError') {
      throw new Error('요청 시간이 초과되었습니다. 다시 시도해주세요.');
    }
    throw error;
  }
}

// ============================================
// Social OAuth TOKEN_EXPIRED 처리
// ============================================

// YouTube 등 소셜 플랫폼 토큰 만료 에러 클래스
export class TokenExpiredError extends Error {
  platform: string;
  reconnectUrl: string;

  constructor(response: TokenExpiredErrorResponse) {
    super(response.detail);
    this.name = 'TokenExpiredError';
    this.platform = response.platform;
    this.reconnectUrl = response.reconnect_url;
  }
}

// Social API 응답에서 TOKEN_EXPIRED 에러를 감지하고 처리
async function handleSocialResponse(response: Response): Promise<void> {
  if (!response.ok) {
    const body = await response.json().catch(() => null);
    if (body && body.code === 'TOKEN_EXPIRED') {
      throw new TokenExpiredError(body as TokenExpiredErrorResponse);
    }
    throw new Error(body?.detail || `HTTP error! status: ${response.status}`);
  }
}

// TOKEN_EXPIRED 발생 시 재연동 플로우 실행
export async function handleSocialReconnect(reconnectUrl: string): Promise<void> {
  try {
    const response = await authenticatedFetch(`${API_URL}${reconnectUrl}`, {
      method: 'GET',
    });

    if (!response.ok) {
      throw new Error(`재연동 요청 실패: ${response.status}`);
    }

    const data: { auth_url: string } = await response.json();
    window.location.href = data.auth_url;
  } catch (error) {
    console.error('[Social] 재연동 처리 실패:', error);
    throw error;
  }
}

// ============================================
// Social OAuth API (YouTube, Instagram, Facebook)
// ============================================

// YouTube 연결 URL 획득
export async function getYouTubeConnectUrl(): Promise<YouTubeConnectResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/oauth/youtube/connect`, {
    method: 'GET',
  });

  await handleSocialResponse(response);
  return response.json();
}

// 연결된 소셜 계정 목록 조회
export async function getSocialAccounts(): Promise<SocialAccountsResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/oauth/accounts`, {
    method: 'GET',
  });

  await handleSocialResponse(response);
  return response.json();
}

// 특정 플랫폼 계정 조회
export async function getSocialAccountByPlatform(platform: 'youtube' | 'instagram' | 'facebook'): Promise<SocialAccountResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/oauth/accounts/${platform}`, {
    method: 'GET',
  });

  await handleSocialResponse(response);
  return response.json();
}

// 소셜 계정 연결 해제 (계정 ID로)
export async function disconnectSocialAccount(accountId: number): Promise<SocialDisconnectResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/oauth/accounts/${accountId}`, {
    method: 'DELETE',
  });

  await handleSocialResponse(response);
  return response.json();
}

// ============================================
// Social Upload API (YouTube Video Upload)
// ============================================

// YouTube Description API
export async function getAutoSeoYoutube(request: YTAutoSeoRequest): Promise<YTAutoSeoResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/seo/youtube`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(request),
  });

  await handleSocialResponse(response);
  return response.json();
}

// YouTube 영상 업로드 시작
export async function uploadToSocial(request: SocialUploadRequest): Promise<SocialUploadResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/upload`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(request),
  });

  await handleSocialResponse(response);
  return response.json();
}

// 업로드 상태 조회
export async function getUploadStatus(uploadId: string): Promise<SocialUploadStatusResponse> {
  const response = await authenticatedFetch(`${API_URL}/social/upload/${uploadId}/status`, {
    method: 'GET',
  });

  await handleSocialResponse(response);
  return response.json();
}

// 업로드 완료까지 폴링 (5분 타임아웃, 2초 간격)
const UPLOAD_POLL_TIMEOUT = 5 * 60 * 1000; // 5분
const UPLOAD_POLL_INTERVAL = 2000; // 2초

export async function waitForUploadComplete(
  uploadId: string,
  onStatusChange?: (status: string, progress?: number) => void
): Promise<SocialUploadStatusResponse> {
  const startTime = Date.now();

  const poll = async (): Promise<SocialUploadStatusResponse> => {
    // 5분 타임아웃 체크
    if (Date.now() - startTime > UPLOAD_POLL_TIMEOUT) {
      throw new Error('TIMEOUT');
    }

    try {
      const response = await getUploadStatus(uploadId);
      onStatusChange?.(response.status, response.upload_progress);

      if (response.status === 'completed') {
        return response;
      } else if (response.status === 'failed') {
        throw new Error(response.error_message || '업로드에 실패했습니다.');
      }

      // pending, uploading은 대기 후 재시도
      await new Promise(resolve => setTimeout(resolve, UPLOAD_POLL_INTERVAL));
      return poll();
    } catch (error) {
      throw error;
    }
  };

  return poll();
}

// 업로드 히스토리 조회
export async function getUploadHistory(
  tab: 'all' | 'completed' | 'scheduled' | 'failed' = 'all',
  options?: { year?: number; month?: number; platform?: string; page?: number; size?: number }
): Promise<import('../types/api').UploadHistoryResponse> {
  const params = new URLSearchParams({ tab });
  if (options?.year) params.set('year', String(options.year));
  if (options?.month) params.set('month', String(options.month));
  if (options?.platform) params.set('platform', options.platform);
  if (options?.page) params.set('page', String(options.page));
  if (options?.size) params.set('size', String(options.size));
  const response = await authenticatedFetch(
    `${API_URL}/social/upload/history?${params.toString()}`,
    { method: 'GET' }
  );
  if (!response.ok) throw new Error('히스토리 조회 실패');
  return response.json();
}

// 예약 업로드 취소
export async function cancelUpload(uploadId: number): Promise<{ success: boolean; message: string }> {
  const response = await authenticatedFetch(
    `${API_URL}/social/upload/${uploadId}`,
    { method: 'DELETE' }
  );
  if (!response.ok) throw new Error('취소 실패');
  return response.json();
}

// 업로드 재시도
export async function retryUpload(uploadId: number): Promise<{ success: boolean; message: string }> {
  const response = await authenticatedFetch(
    `${API_URL}/social/upload/${uploadId}/retry`,
    { method: 'POST' }
  );
  if (!response.ok) throw new Error('재시도 실패');
  return response.json();
}
