import type { FeedItem, Scen } from './data'

const TOKEN_KEY = 'ssulbox_token'
export const getToken = () => localStorage.getItem(TOKEN_KEY)
const authH = (): Record<string, string> => {
  const t = getToken()
  return t ? { Authorization: 'Bearer ' + t } : {}
}

const REFRESH_KEY = 'ssulbox_refresh'
export interface Me {
  user_uuid: string; nickname: string; email: string | null
  profile_image_url: string | null; bio: string | null
  credits: number; is_admin: boolean
}

export interface ProfileBody { nickname?: string; profile_image_url?: string; bio?: string }
export async function updateProfile(body: ProfileBody): Promise<{ ok: boolean; me?: Me; message: string }> {
  try {
    const r = await fetch('/api/auth/me', {
      method: 'PATCH', headers: { 'Content-Type': 'application/json', ...authH() },
      body: JSON.stringify(body),
    })
    if (r.ok) return { ok: true, me: await r.json(), message: '저장했어요.' }
    const detail = await r.json().then((j) => j.detail).catch(() => '')
    return { ok: false, message: detail || '저장에 실패했어요.' }
  } catch { return { ok: false, message: '네트워크 오류로 저장에 실패했어요.' } }
}

/** 카카오 콜백이 ?access_token=&refresh_token= 로 되돌려준 토큰을 저장하고 URL을 정리. */
export function captureTokensFromUrl(): boolean {
  const q = new URLSearchParams(window.location.search)
  const at = q.get('access_token')
  if (!at) return false
  localStorage.setItem(TOKEN_KEY, at)
  const rt = q.get('refresh_token')
  if (rt) localStorage.setItem(REFRESH_KEY, rt)
  window.history.replaceState({}, '', window.location.pathname)
  return true
}

/** 카카오 로그인 시작: auth_url 있으면 이동. 미설정(501)이면 null. */
export async function getKakaoAuthUrl(): Promise<string | null> {
  try {
    const r = await fetch('/api/auth/kakao/login')
    if (!r.ok) return null
    return (await r.json()).auth_url ?? null
  } catch { return null }
}
export function startKakaoLogin(url: string) { window.location.href = url }

export function logout() {
  localStorage.removeItem(TOKEN_KEY)
  localStorage.removeItem(REFRESH_KEY)
}

export async function devLogin(nickname = '진우'): Promise<boolean> {
  try {
    const r = await fetch('/api/auth/dev-login', {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ nickname }),
    })
    if (!r.ok) return false
    localStorage.setItem(TOKEN_KEY, (await r.json()).access_token)
    return true
  } catch { return false }
}

export async function getMe(): Promise<Me | null> {
  try {
    const r = await fetch('/api/auth/me', { headers: authH() })
    return r.ok ? r.json() : null
  } catch { return null }
}

/** 토큰이 없거나 만료면 개발용 로그인. 백엔드 없으면 null. */
export async function ensureLogin(): Promise<Me | null> {
  let me = await getMe()
  if (!me) { await devLogin(); me = await getMe() }
  return me
}

export async function getFeed(opts?: { sort?: string; owner?: string }): Promise<FeedItem[] | null> {
  try {
    const q = new URLSearchParams({ page_size: '60' })
    if (opts?.sort) q.set('sort', opts.sort)
    if (opts?.owner) q.set('owner', opts.owner)
    const r = await fetch('/api/feed?' + q, { headers: authH() })
    if (!r.ok) return null
    const j = await r.json()
    return Array.isArray(j) ? j : (j.items ?? null)   // 페이지네이션 {items} 언랩
  } catch { return null }
}

export async function toggleLike(id: string): Promise<{ liked: boolean; likes: number }> {
  const r = await fetch(`/api/content/${encodeURIComponent(id)}/like`, { method: 'POST', headers: authH() })
  if (!r.ok) throw new Error('좋아요 실패')
  return r.json()
}

export interface CommentNode {
  id: number; body: string | null; nickname: string; is_mine: boolean
  created_at: string; replies?: CommentNode[]
}
export async function listComments(id: string): Promise<CommentNode[]> {
  try {
    const r = await fetch(`/api/comment/content/${encodeURIComponent(id)}`, { headers: authH() })
    if (!r.ok) return []
    return (await r.json()).items ?? []
  } catch { return [] }
}
export async function addComment(id: string, body: string, parent_id?: number): Promise<void> {
  const r = await fetch(`/api/comment/content/${encodeURIComponent(id)}`, {
    method: 'POST', headers: { 'Content-Type': 'application/json', ...authH() },
    body: JSON.stringify({ body, parent_id }),
  })
  if (!r.ok) throw new Error('댓글 실패')
}

/* ============================ 업장 검색 (동명 업장 구분 → place_url) ============================ */
export interface PlaceItem {
  title: string; category: string; address: string; roadAddress: string; place_url: string
}
export async function searchPlace(query: string): Promise<PlaceItem[]> {
  try {
    const r = await fetch('/api/search/place?query=' + encodeURIComponent(query), { headers: authH() })
    if (!r.ok) return []
    return (await r.json()).items ?? []
  } catch { return [] }
}

/* ============================ SNS 연동 ============================ */
export type Platform = 'youtube'
export interface SocialAccount { id: number; platform: Platform; account_name: string }

/** 플랫폼별 키 설정 여부(연동 가능 여부). 미설정이면 '곧 지원' 안내. */
export async function socialConfig(): Promise<Partial<Record<Platform, boolean>>> {
  try {
    const r = await fetch('/api/social/config')
    return r.ok ? r.json() : {}
  } catch { return {} }
}

export async function listSocial(): Promise<SocialAccount[]> {
  try {
    const r = await fetch('/api/social/accounts', { headers: authH() })
    return r.ok ? r.json() : []
  } catch { return [] }
}
/** 연동 시작: Google OAuth 동의 URL 반환(있으면 프론트가 그리로 이동). 미설정이면 message. */
export async function connectSocial(platform: Platform): Promise<{ authUrl?: string; message: string }> {
  try {
    const r = await fetch(`/api/social/${platform}/connect`, { headers: authH() })
    if (r.ok) { const j = await r.json(); return { authUrl: j.auth_url, message: '' } }
    const detail = await r.json().then((j) => j.detail).catch(() => '')
    return { message: detail || '연동에 실패했어요.' }
  } catch { return { message: '네트워크 오류로 연동에 실패했어요.' } }
}
export async function disconnectSocial(platform: Platform): Promise<boolean> {
  try {
    const r = await fetch(`/api/social/${platform}/disconnect`, { method: 'DELETE', headers: authH() })
    return r.ok
  } catch { return false }
}
export async function uploadToSocial(platform: Platform, contentId: string): Promise<{ ok: boolean; pending?: boolean; message: string }> {
  try {
    const r = await fetch(`/api/social/upload/${platform}/${encodeURIComponent(contentId)}`, { method: 'POST', headers: authH() })
    if (r.ok) return { ok: true, message: '업로드했어요.' }
    const detail = await r.json().then((j) => j.detail).catch(() => '')
    return { ok: false, pending: r.status === 501, message: detail || '업로드에 실패했어요.' }
  } catch { return { ok: false, message: '네트워크 오류로 업로드에 실패했어요.' } }
}

/* ============================ 크레딧 충전 상품 ============================ */
export interface Product { id: string; label: string; credits: number; bonus: number; price: number; best: boolean }
export async function getProducts(): Promise<Product[]> {
  try {
    const r = await fetch('/api/credits/products', { headers: authH() })
    return r.ok ? (await r.json()).items ?? [] : []
  } catch { return [] }
}
export async function purchaseProduct(productId: string): Promise<{ ok: boolean; credits?: number; message: string }> {
  try {
    const r = await fetch('/api/credits/purchase', {
      method: 'POST', headers: { 'Content-Type': 'application/json', ...authH() },
      body: JSON.stringify({ product_id: productId }),
    })
    if (r.ok) { const j = await r.json(); return { ok: true, credits: j.credits, message: `${j.product} · ${j.added}크레딧 충전 완료!` } }
    const detail = await r.json().then((j) => j.detail).catch(() => '')
    return { ok: false, message: detail || '충전에 실패했어요.' }
  } catch { return { ok: false, message: '네트워크 오류로 충전에 실패했어요.' } }
}

export interface CreateBody { scenario: Scen; input: string }
export async function createJob(body: CreateBody): Promise<{ id: string }> {
  const r = await fetch('/api/create', {
    method: 'POST', headers: { 'Content-Type': 'application/json', ...authH() },
    body: JSON.stringify(body),
  })
  if (!r.ok) {
    let detail = '생성 요청 실패'
    try { detail = (await r.json()).detail || detail } catch { /* noop */ }
    throw new Error(detail)
  }
  return r.json()
}

export interface JobStatus {
  id: string; status: 'queued' | 'running' | 'done' | 'error'
  step: number; stepName: string; output: string | null; error: string | null; log: string[]
}
export async function getJob(id: string): Promise<JobStatus> {
  const r = await fetch('/api/jobs/' + id, { cache: 'no-store', headers: authH() })
  if (!r.ok) throw new Error('잡 조회 실패')
  return r.json()
}
