import type { ConnectedAccount, GeneratePostRequest, GeneratedPost } from "@/types/workflow";

export async function generatePost(
  payload: GeneratePostRequest & { mode?: "next" | "specific" },
): Promise<GeneratedPost> {
  const res = await fetch("/api/generation/generate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });

  const data = (await res.json()) as { post?: GeneratedPost; error?: string; code?: string };
  if (!res.ok) {
    const err = new Error(data.error ?? "Generation failed") as Error & { code?: string };
    err.code = data.code;
    throw err;
  }
  if (!data.post) throw new Error("No post returned");
  return data.post;
}

export async function regeneratePost(
  postId: string,
  payload: GeneratePostRequest,
): Promise<GeneratedPost> {
  const res = await fetch(`/api/generation/posts/${postId}/regenerate`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });

  const data = (await res.json()) as { post?: GeneratedPost; error?: string; code?: string };
  if (!res.ok) {
    const err = new Error(data.error ?? "Regeneration failed") as Error & { code?: string };
    err.code = data.code;
    throw err;
  }
  if (!data.post) throw new Error("No post returned");
  return data.post;
}

export async function fetchGeneratedPosts(
  projectId?: string,
  projectName?: string,
): Promise<GeneratedPost[]> {
  const params = new URLSearchParams();
  if (projectId) params.set("projectId", projectId);
  else if (projectName) params.set("project", projectName);
  const qs = params.toString();
  const url = qs ? `/api/generation/posts?${qs}` : "/api/generation/posts";
  const res = await fetch(url);
  if (res.status === 401) return [];
  const data = (await res.json()) as { posts: GeneratedPost[] };
  return data.posts ?? [];
}

export async function updatePostStatus(
  id: string,
  status: GeneratedPost["status"],
): Promise<GeneratedPost> {
  const res = await fetch(`/api/generation/posts/${id}`, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ status }),
  });
  const data = (await res.json()) as { post?: GeneratedPost; error?: string };
  if (!res.ok || !data.post) throw new Error(data.error ?? "Update failed");
  return data.post;
}

export async function updatePostCaption(id: string, caption: string): Promise<GeneratedPost> {
  const res = await fetch(`/api/generation/posts/${id}`, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ caption }),
  });
  const data = (await res.json()) as { post?: GeneratedPost; error?: string };
  if (!res.ok || !data.post) throw new Error(data.error ?? "Update failed");
  return data.post;
}

export async function approvePostImage(id: string): Promise<GeneratedPost> {
  const res = await fetch(`/api/generation/posts/${id}`, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ imageApproved: true }),
  });
  const data = (await res.json()) as { post?: GeneratedPost; error?: string };
  if (!res.ok || !data.post) throw new Error(data.error ?? "Update failed");
  return data.post;
}

export interface PlatformPublishOutcome {
  platform: string;
  success: boolean;
  skipped?: boolean;
  permalink?: string;
  error?: string;
}

export interface PublishPostResult {
  post: GeneratedPost | null;
  outcomes: PlatformPublishOutcome[];
  ok: boolean;
  error?: string;
}

export async function publishPost(
  id: string,
  projectStatus: string,
  accounts?: ConnectedAccount[],
  options?: {
    forcePublish?: boolean;
    quickPublish?: boolean;
    projectTimezone?: string;
    projectCountries?: string[];
    postsPerDay?: 1 | 2;
    scheduleSeed?: number;
    scheduleSaved?: boolean;
  },
): Promise<GeneratedPost> {
  const result = await publishPostWithOutcomes(id, projectStatus, accounts, options);
  if (!result.ok || !result.post) {
    const failed = result.outcomes.filter((o) => !o.success && !o.skipped);
    const detail = failed.map((o) => `${o.platform}: ${o.error ?? "failed"}`).join("; ");
    const err = new Error(detail || result.error || "Publish failed") as Error & { code?: string };
    throw err;
  }
  return result.post;
}

export async function publishPostWithOutcomes(
  id: string,
  projectStatus: string,
  accounts?: ConnectedAccount[],
  options?: {
    forcePublish?: boolean;
    quickPublish?: boolean;
    projectTimezone?: string;
    projectCountries?: string[];
    postsPerDay?: 1 | 2;
    scheduleSeed?: number;
    scheduleSaved?: boolean;
  },
): Promise<PublishPostResult> {
  const res = await fetch(`/api/generation/posts/${id}/publish`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      projectStatus,
      accounts,
      forcePublish: options?.forcePublish ?? options?.quickPublish ?? false,
      quickPublish: options?.quickPublish ?? false,
      projectTimezone: options?.projectTimezone,
      projectCountries: options?.projectCountries,
      postsPerDay: options?.postsPerDay,
      scheduleSeed: options?.scheduleSeed,
      scheduleSaved: options?.scheduleSaved,
    }),
  });
  const data = (await res.json()) as {
    post?: GeneratedPost;
    error?: string;
    code?: string;
    outcomes?: PlatformPublishOutcome[];
  };

  const outcomes = data.outcomes ?? [];

  if (!res.ok || !data.post) {
    return {
      ok: false,
      post: data.post ?? null,
      outcomes,
      error: data.error ?? "Publish failed",
    };
  }

  return { ok: true, post: data.post, outcomes };
}

export async function fetchAIConfig() {
  const res = await fetch("/api/ai/config");
  return res.json() as Promise<{
    provider: string;
    model: string;
    timeoutSeconds: number;
    imageProvider: string;
  }>;
}
