import type { SupabaseClient } from "@supabase/supabase-js";
import type {
  Issue,
  IssueComment,
  IssueStatus,
  NoteCategory,
} from "@/lib/types";
import { NOTE_BUCKET } from "@/lib/constants";

const SIGNED_URL_TTL = 60 * 60;

interface IssueRow {
  id: string;
  project_id: string;
  category: string;
  content: string;
  image_path: string | null;
  status: string;
  action_to: string[] | null;
  prev_action_to: string[] | null;
  author_email: string | null;
  created_at: string;
}

export async function getIssues(
  supabase: SupabaseClient,
  projectId: string,
): Promise<Issue[]> {
  const { data } = await supabase
    .from("issues")
    .select(
      "id, project_id, category, content, image_path, status, action_to, prev_action_to, author_email, created_at",
    )
    .eq("project_id", projectId)
    .order("created_at", { ascending: false });

  const rows = (data as IssueRow[] | null) ?? [];
  const issueIds = rows.map((r) => r.id);

  // Comments for these issues.
  let commentRows: {
    id: string;
    issue_id: string;
    content: string;
    image_path: string | null;
    author_email: string | null;
    created_at: string;
  }[] = [];
  if (issueIds.length > 0) {
    const { data: c } = await supabase
      .from("issue_comments")
      .select("id, issue_id, content, image_path, author_email, created_at")
      .in("issue_id", issueIds)
      .order("created_at", { ascending: true });
    commentRows = (c as typeof commentRows | null) ?? [];
  }

  // Sign all image paths (issues + their comments) in one batch.
  const paths = [
    ...rows.flatMap((r) => (r.image_path ? [r.image_path] : [])),
    ...commentRows.flatMap((c) => (c.image_path ? [c.image_path] : [])),
  ];
  const signed = new Map<string, string>();
  if (paths.length > 0) {
    const { data: s } = await supabase.storage
      .from(NOTE_BUCKET)
      .createSignedUrls(paths, SIGNED_URL_TTL);
    for (const it of s ?? []) {
      if (it.path && it.signedUrl) signed.set(it.path, it.signedUrl);
    }
  }

  const commentsByIssue = new Map<string, IssueComment[]>();
  for (const c of commentRows) {
    const list = commentsByIssue.get(c.issue_id) ?? [];
    list.push({
      id: c.id,
      issue_id: c.issue_id,
      content: c.content,
      image_url: c.image_path ? signed.get(c.image_path) ?? null : null,
      author_email: c.author_email,
      created_at: c.created_at,
    });
    commentsByIssue.set(c.issue_id, list);
  }

  return rows.map((r) => ({
    id: r.id,
    project_id: r.project_id,
    category: r.category as NoteCategory,
    content: r.content,
    image_url: r.image_path ? signed.get(r.image_path) ?? null : null,
    status: r.status as IssueStatus,
    action_to: r.action_to ?? [],
    prev_action_to: r.prev_action_to ?? [],
    author_email: r.author_email,
    created_at: r.created_at,
    comments: commentsByIssue.get(r.id) ?? [],
  }));
}

/** Emails of users that can be assigned in "Action To". */
export async function getProjectUsers(
  supabase: SupabaseClient,
): Promise<string[]> {
  const { data } = await supabase
    .from("profiles")
    .select("email")
    .order("email", { ascending: true });

  return (data ?? [])
    .map((p) => p.email as string | null)
    .filter((e): e is string => Boolean(e));
}
