import { API_URL } from '@/lib/api';
import { buildVelocityHeaders } from '@/lib/velocitySession';

const rawDreamWeaverBase = import.meta.env.VITE_DREAM_WEAVER_URL?.trim();
const rawDreamWeaverApiKey = import.meta.env.VITE_DREAM_WEAVER_API_KEY?.trim();
const LOCAL_DREAM_WEAVER_GATEWAY = 'http://127.0.0.1:8082';

export const DREAM_WEAVER_URL = (rawDreamWeaverBase && rawDreamWeaverBase.length > 0
  ? rawDreamWeaverBase
  : import.meta.env.DEV
    ? LOCAL_DREAM_WEAVER_GATEWAY
  : API_URL
).replace(/\/$/, '');

export interface DreamWeaverHealth {
  online: boolean;
  routeMounted: boolean;
  status: string;
  comfyuiOnline?: boolean;
  comfyuiUrl?: string;
  checkpointReady?: boolean;
  checkpointCount?: number;
  availableCheckpoints?: string[];
  preferredCheckpoints?: string[];
  detail?: string;
}

export interface DreamWeaverJobResponse {
  job_id: string;
  status?: string;
  poll_url?: string;
  result_url?: string;
}

export interface DreamWeaverStatusResponse {
  status?: string;
  ready?: boolean;
  result_url?: string;
  error?: string;
}

export interface SubmitDreamWeaverJobInput {
  image: File;
  roomType: string;
  keywords: string;
}

function buildDreamWeaverHeaders(init?: HeadersInit): Headers {
  const headers = buildVelocityHeaders(init, false);
  if (rawDreamWeaverApiKey && !headers.has('X-Dream-Weaver-API-Key')) {
    headers.set('X-Dream-Weaver-API-Key', rawDreamWeaverApiKey);
  }
  return headers;
}

function resolveDreamWeaverUrl(candidate: string | undefined, fallbackPath: string): string {
  const path = candidate && candidate.trim().length > 0 ? candidate.trim() : fallbackPath;
  if (/^https?:\/\//i.test(path)) {
    return path;
  }
  return `${DREAM_WEAVER_URL}${path.startsWith('/') ? path : `/${path}`}`;
}

async function readErrorMessage(response: Response, fallback: string): Promise<string> {
  const body = await response.json().catch(() => null) as { detail?: unknown; message?: unknown; error?: unknown } | null;
  if (typeof body?.detail === 'string') return body.detail;
  if (typeof body?.message === 'string') return body.message;
  if (typeof body?.error === 'string') return body.error;
  const text = await response.text().catch(() => '');
  return text.trim() || fallback;
}

async function requestDreamWeaverJson<T>(url: string, init?: RequestInit): Promise<T> {
  const response = await fetch(url, {
    ...init,
    headers: buildDreamWeaverHeaders(init?.headers),
  });
  if (!response.ok) {
    throw new Error(await readErrorMessage(response, `Dream Weaver request failed: ${response.status}`));
  }
  return response.json() as Promise<T>;
}

export async function checkDreamWeaverHealth(): Promise<DreamWeaverHealth> {
  let status = 'offline';
  let detail: string | undefined;
  let comfyuiOnline: boolean | undefined;
  let comfyuiUrl: string | undefined;
  let checkpointReady: boolean | undefined;
  let checkpointCount: number | undefined;
  let availableCheckpoints: string[] | undefined;
  let preferredCheckpoints: string[] | undefined;
  let healthOk = false;

  try {
    const response = await fetch(resolveDreamWeaverUrl(undefined, '/dream-weaver/health'), {
      headers: buildDreamWeaverHeaders(),
    });
    const body = await response.json().catch(() => null) as {
      status?: unknown;
      detail?: unknown;
      comfyui?: unknown;
      comfyui_url?: unknown;
      comfyuiUrl?: unknown;
      checkpoint_ready?: unknown;
      checkpoint_count?: unknown;
      available_checkpoints?: unknown;
      preferred_checkpoints?: unknown;
    } | null;
    status = typeof body?.status === 'string' ? body.status : response.ok ? 'ok' : `HTTP ${response.status}`;
    detail = typeof body?.detail === 'string' ? body.detail : undefined;
    comfyuiOnline = typeof body?.comfyui === 'boolean' ? body.comfyui : undefined;
    comfyuiUrl = typeof body?.comfyui_url === 'string'
      ? body.comfyui_url
      : typeof body?.comfyuiUrl === 'string'
        ? body.comfyuiUrl
        : undefined;
    checkpointReady = typeof body?.checkpoint_ready === 'boolean' ? body.checkpoint_ready : undefined;
    checkpointCount = typeof body?.checkpoint_count === 'number' ? body.checkpoint_count : undefined;
    availableCheckpoints = Array.isArray(body?.available_checkpoints)
      ? body.available_checkpoints.filter((item): item is string => typeof item === 'string')
      : undefined;
    preferredCheckpoints = Array.isArray(body?.preferred_checkpoints)
      ? body.preferred_checkpoints.filter((item): item is string => typeof item === 'string')
      : undefined;
    healthOk = response.ok && ['ok', 'healthy', 'online'].includes(status.toLowerCase());
  } catch (error) {
    detail = error instanceof Error ? error.message : 'Unable to reach Dream Weaver gateway.';
  }

  try {
    const probe = await fetch(resolveDreamWeaverUrl(undefined, '/dream-weaver/status/velocity-route-probe'), {
      headers: buildDreamWeaverHeaders(),
    });
    if (probe.ok) {
      return { online: healthOk, routeMounted: true, status, comfyuiOnline, comfyuiUrl, checkpointReady, checkpointCount, availableCheckpoints, preferredCheckpoints, detail };
    }
    const probeMessage = await readErrorMessage(probe, '');
    const expectedMissingJob = probe.status === 404 && /job|not found|missing/i.test(probeMessage);
    return {
      online: healthOk && expectedMissingJob,
      routeMounted: expectedMissingJob,
      status,
      comfyuiOnline,
      comfyuiUrl,
      checkpointReady,
      checkpointCount,
      availableCheckpoints,
      preferredCheckpoints,
      detail: detail ?? probeMessage,
    };
  } catch (error) {
    return {
      online: false,
      routeMounted: false,
      status,
      comfyuiOnline,
      comfyuiUrl,
      checkpointReady,
      checkpointCount,
      availableCheckpoints,
      preferredCheckpoints,
      detail: error instanceof Error ? error.message : detail,
    };
  }
}

export async function submitDreamWeaverJob(input: SubmitDreamWeaverJobInput): Promise<DreamWeaverJobResponse> {
  const formData = new FormData();
  formData.append('image', input.image, input.image.name || 'room-source.jpg');
  formData.append('room_type', input.roomType);
  const trimmedKeywords = input.keywords.trim();
  if (trimmedKeywords.length > 0) {
    formData.append('keywords', trimmedKeywords);
  }

  return requestDreamWeaverJson<DreamWeaverJobResponse>(resolveDreamWeaverUrl(undefined, '/dream-weaver'), {
    method: 'POST',
    body: formData,
  });
}

export async function getDreamWeaverStatus(job: Pick<DreamWeaverJobResponse, 'job_id' | 'poll_url'>): Promise<DreamWeaverStatusResponse> {
  return requestDreamWeaverJson<DreamWeaverStatusResponse>(
    resolveDreamWeaverUrl(job.poll_url, `/dream-weaver/status/${encodeURIComponent(job.job_id)}`),
  );
}

export async function fetchDreamWeaverResult(jobId: string, resultUrl?: string): Promise<Blob> {
  const response = await fetch(resolveDreamWeaverUrl(resultUrl, `/dream-weaver/result/${encodeURIComponent(jobId)}`), {
    headers: buildDreamWeaverHeaders({ Accept: 'image/png,image/*,*/*' }),
  });
  if (!response.ok) {
    throw new Error(await readErrorMessage(response, `Dream Weaver result failed: ${response.status}`));
  }
  return response.blob();
}
