type GenerationJobType = 'image' | 'video';

export type GenerationJobStatus = {
  id?: string;
  jobId?: string;
  type?: GenerationJobType;
  status: 'queued' | 'running' | 'succeeded' | 'failed';
  result?: Record<string, unknown>;
  error?: string | null;
  estimateSeconds?: number;
  elapsed_seconds?: number;
  progress?: Record<string, unknown>;
  eta?: {
    estimateSeconds?: number;
    source?: string;
    sampleCount?: number;
    windowDays?: number | null;
  };
  created_at?: string;
  started_at?: string | null;
  finished_at?: string | null;
  updated_at?: string;
};

type GenerationJobOptions = {
  timeoutMs?: number;
  intervalMs?: number;
  onStatus?: (status: GenerationJobStatus) => void;
};

export class GenerationJobStillRunningError extends Error {
  status: GenerationJobStatus | null;

  constructor(status: GenerationJobStatus | null) {
    super('生成任务仍在执行，请稍后在创作历史中查看');
    this.name = 'GenerationJobStillRunningError';
    this.status = status;
  }
}

function getAuthToken(): string | null {
  try {
    const raw = window.localStorage.getItem('miaojing_auth');
    if (!raw) return null;
    return (JSON.parse(raw) as { accessToken?: string }).accessToken || null;
  } catch {
    return null;
  }
}

function sleep(ms: number) {
  return new Promise(resolve => window.setTimeout(resolve, ms));
}

export async function runGenerationFinalCountdown(
  onTick: (seconds: number | null) => void,
  seconds = 3,
) {
  for (let remaining = seconds; remaining > 0; remaining -= 1) {
    onTick(remaining);
    await sleep(1000);
  }
  onTick(0);
}

export async function runGenerationJob<T extends Record<string, unknown>>(
  type: GenerationJobType,
  payload: Record<string, unknown>,
  options: GenerationJobOptions = {},
): Promise<T> {
  const createRes = await fetch('/api/generation-jobs', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      ...(getAuthToken() ? { Authorization: `Bearer ${getAuthToken()}` } : {}),
    },
    body: JSON.stringify({ type, payload }),
  });

  const createData = await createRes.json().catch(() => ({}));
  if (!createRes.ok || !createData.jobId) {
    throw new Error(createData.error || `任务创建失败 (${createRes.status})`);
  }
  options.onStatus?.({
    ...createData,
    status: 'queued',
  } as GenerationJobStatus);

  const timeoutMs = options.timeoutMs ?? (type === 'video' ? 600_000 : 900_000);
  const intervalMs = options.intervalMs ?? 2_000;
  const startedAt = Date.now();
  let lastStatus: GenerationJobStatus | null = null;

  while (Date.now() - startedAt < timeoutMs) {
    await sleep(intervalMs);

    const statusRes = await fetch(`/api/generation-jobs/${encodeURIComponent(createData.jobId)}`, {
      headers: {
        ...(getAuthToken() ? { Authorization: `Bearer ${getAuthToken()}` } : {}),
      },
    });
    const statusData = await statusRes.json().catch(() => ({}));
    if (!statusRes.ok) {
      throw new Error(statusData.error || `任务查询失败 (${statusRes.status})`);
    }
    options.onStatus?.(statusData as GenerationJobStatus);
    lastStatus = statusData as GenerationJobStatus;

    if (statusData.status === 'succeeded') {
      return (statusData.result || {}) as T;
    }
    if (statusData.status === 'failed') {
      throw new Error(statusData.error || '生成任务失败');
    }
  }

  throw new GenerationJobStillRunningError(lastStatus);
}
