import type {
  Member,
  Alumnus,
  Publication,
  Patent,
  Semester,
  StandardsBody,
  ResearchProject,
  PubCategory,
  DocStatus,
} from "../content/types";

const API_BASE_URL = process.env.API_BASE_URL ?? "http://localhost:8080/api/v1";
const FETCH_TIMEOUT_MS = 3000;

interface APIResponse<T> {
  data: T;
}

// Raw backend response schemas (snake_case)
interface BackendResearchProject {
  id: number;
  slug: string;
  title: string;
  abstract: string;
  keywords: string[];
  organization?: string | null;
  standards_org?: string | null;
  period?: string | null;
  funder?: string | null;
}

interface BackendResearchArea {
  id: number;
  name_en: string;
  name_kr?: string | null;
  display_order: number;
}

interface BackendStatsSummary {
  intl_publications: number;
  standardization_docs: number;
  patents: number;
}

interface BackendMember {
  id: number;
  name_ko: string;
  name_en: string;
  degree: string;
  affiliation?: string | null;
  email?: string | null;
  is_advisor: boolean;
  display_order: number;
}

interface BackendAlumnus {
  id: number;
  name_ko: string;
  name_en: string;
  degree: string;
  graduated_at: string;
  major?: string | null;
  current_position?: string | null;
}

interface BackendPublication {
  id: number;
  category: string;
  title: string;
  authors?: string | null;
  venue: string;
  volume?: string | null;
  published_at: string;
  kci: boolean;
  doi?: string | null;
  is_highlight: boolean;
}

interface BackendPatent {
  id: number;
  title: string;
  inventors: string;
  application_no: string;
  application_at: string;
  registration_no?: string | null;
  registration_at?: string | null;
  country: string;
  published_at: string;
}

interface BackendCourse {
  id: number;
  semester_id: number;
  code: string;
  name_en: string;
  name_kr?: string | null;
  note?: string | null;
  display_order: number;
}

interface BackendSemester {
  id: number;
  year: number;
  term: string;
  courses: BackendCourse[];
}

interface BackendStandardDoc {
  id: number;
  body_id: number;
  wg: string;
  project_name: string;
  title: string;
  doc_ref: string;
  status: string;
  published_at?: string | null;
}

interface BackendStandardProject {
  wg: string;
  name: string;
  documents: BackendStandardDoc[];
}

interface BackendStandardsBody {
  id: number;
  org: string;
  full_name: string;
  scope: string;
  period: string;
  role?: string | null;
  display_order: number;
  projects: BackendStandardProject[];
}

/**
 * Generic fetch helper with bounded timeout and safe JSON handling.
 * Returns data payload or null on any failure (network, timeout, non-2xx, parse error).
 */
async function apiGet<T>(path: string): Promise<T | null> {
  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
    const res = await fetch(`${API_BASE_URL}${path}`, {
      signal: controller.signal,
      cache: "no-store",
    });
    clearTimeout(timeout);

    if (!res.ok) {
      return null;
    }

    const json = (await res.json()) as APIResponse<T>;
    return json?.data ?? null;
  } catch {
    return null;
  }
}

// --- Home Domain ---

export async function getResearchProjects(): Promise<ResearchProject[] | null> {
  const raw = await apiGet<BackendResearchProject[]>("/research-projects");
  if (!raw) return null;
  return raw.map((p) => ({
    slug: p.slug,
    title: p.title,
    abstract: p.abstract,
    keywords: p.keywords,
    standardsTrack: p.organization ?? undefined,
    standardsOrg: p.standards_org ?? undefined,
    period: p.period ?? undefined,
    funder: p.funder ?? undefined,
    deliverables: [],
  }));
}

export async function getResearchAreaNames(): Promise<string[] | null> {
  const raw = await apiGet<BackendResearchArea[]>("/research-areas");
  if (!raw) return null;
  return raw.map((a) => a.name_en);
}

export async function getStatsSummary(): Promise<{
  intlPubsCount: number;
  stdDocsCount: number;
  patentCount: number;
} | null> {
  const raw = await apiGet<BackendStatsSummary>("/stats/summary");
  if (!raw) return null;
  return {
    intlPubsCount: raw.intl_publications,
    stdDocsCount: raw.standardization_docs,
    patentCount: raw.patents,
  };
}

// --- Members Domain ---

export async function getMembers(): Promise<Member[] | null> {
  const raw = await apiGet<BackendMember[]>("/members");
  if (!raw) return null;
  return raw.map((m) => ({
    ko: m.name_ko,
    en: m.name_en,
    degree: m.degree as Member["degree"],
    affiliation: m.affiliation ?? undefined,
  }));
}

export async function getAlumni(): Promise<Alumnus[] | null> {
  const raw = await apiGet<BackendAlumnus[]>("/alumni");
  if (!raw) return null;
  return raw.map((a) => ({
    ko: a.name_ko,
    en: a.name_en,
    degree: a.degree as Alumnus["degree"],
    graduatedAt: a.graduated_at,
    major: a.major ?? undefined,
    currentPosition: a.current_position ?? undefined,
  }));
}

// --- Publications & Patents Domain ---

export async function getPublications(
  category?: "intl-journal-conf" | "domestic-journal-conf"
): Promise<Publication[] | null> {
  const raw = await apiGet<BackendPublication[]>(
    category ? `/publications?category=${category}` : "/publications"
  );
  if (!raw) return null;
  return raw.map((p) => ({
    category: p.category as PubCategory,
    title: p.title,
    authors: p.authors ?? undefined,
    venue: p.venue,
    volume: p.volume ?? undefined,
    publishedAt: p.published_at,
    kci: p.kci,
    doi: p.doi ?? undefined,
    isHighlight: p.is_highlight,
  }));
}

export async function getHighlights(): Promise<Publication[] | null> {
  const raw = await apiGet<BackendPublication[]>("/publications/highlights");
  if (!raw) return null;
  return raw.map((p) => ({
    category: p.category as PubCategory,
    title: p.title,
    authors: p.authors ?? undefined,
    venue: p.venue,
    volume: p.volume ?? undefined,
    publishedAt: p.published_at,
    kci: p.kci,
    doi: p.doi ?? undefined,
    isHighlight: p.is_highlight,
  }));
}

export async function getPatents(): Promise<Patent[] | null> {
  const raw = await apiGet<BackendPatent[]>("/patents");
  if (!raw) return null;
  return raw.map((p) => ({
    category: "patent",
    title: p.title,
    inventors: p.inventors,
    applicationNo: p.application_no,
    applicationAt: p.application_at,
    registrationNo: p.registration_no ?? undefined,
    registrationAt: p.registration_at ?? undefined,
    country: p.country,
    publishedAt: p.published_at,
  }));
}

// --- Lectures Domain ---

export async function getSemesters(): Promise<Semester[] | null> {
  const raw = await apiGet<BackendSemester[]>("/semesters");
  if (!raw) return null;
  return raw.map((s) => ({
    term: s.term as Semester["term"],
    year: s.year,
    courses: s.courses.map((c) => ({
      code: c.code,
      en: c.name_en,
      note: c.note ?? undefined,
    })),
  }));
}

// --- Standardization Domain ---

export async function getStandardsBodies(): Promise<StandardsBody[] | null> {
  const raw = await apiGet<BackendStandardsBody[]>("/standards-bodies");
  if (!raw) return null;
  return raw.map((b) => ({
    org: b.org,
    full: b.full_name,
    scope: b.scope as StandardsBody["scope"],
    period: b.period,
    role: b.role ?? undefined,
    projects: b.projects.map((p) => ({
      wg: p.wg,
      name: p.name,
      documents: p.documents.map((d) => ({
        title: d.title,
        ref: d.doc_ref,
        status: d.status as DocStatus,
        publishedAt: d.published_at ?? undefined,
      })),
    })),
  }));
}
