"use client";

import type {
  DecisionIssueItem,
  MinistryRgcDecisionRow,
  MinistryRgcDecisionStatus,
} from "../data/ministry-rgc-decision-data";

const API_BASE_URL =
  process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, "") ??
  "http://localhost:3001/api/v1";

type ApiUser = {
  id?: number | string;
  userId?: number | string;
  sub?: number | string;
};

type AuthMeResponse = {
  message?: string | string[];
  data?: ApiUser | { user?: ApiUser };
  user?: ApiUser;
};

type ApiStakeholder = {
  id?: number | string;
  name?: string | null;
  logo?: string | null;
};

type ApiCategory = {
  id?: number | string;
  name?: string | null;
};

type ApiIndicator = {
  id?: number | string;
  name?: string | null;
  description?: string | null;
};

type ApiIssueItem = {
  id?: number | string;
  title?: string | null;
  name?: string | null;
  description?: string | null;
};

type ApiDecision = {
  id?: number | string;
  plenaryId?: number | string | null;

  stakeholderId?: number | string | null;
  stakeholder?: ApiStakeholder | null;

  categoryId?: number | string | null;
  category?: string | ApiCategory | null;
  categoryInfo?: ApiCategory | null;

  indicatorId?: number | string | null;
  indicator?: ApiIndicator | null;
  indicatorName?: string | null;

  meetingDate?: string | null;
  status?: string | null;
  statusCode?: string | null;

  focalPerson?: string | null;
  decision?: string | null;

  verificationSource?: string | null;
  sourceOfVerification?: string | null;
  verificationLink?: string | null;

  issues?: ApiIssueItem[]; // 🔥 បន្ថែម Type សម្រាប់ Issues ពី API
};

type ApiListData<T> = {
  items?: T[];
  data?: T[];
};

type ApiResponse<T> = {
  message?: string | string[];
  data?: T;
  items?: ApiDecision[];
};

function toPositiveNumber(value: unknown): number | null {
  const numberValue = Number(value);

  return Number.isInteger(numberValue) && numberValue > 0
    ? numberValue
    : null;
}

function getAccessToken(): string {
  if (typeof window === "undefined") {
    return "";
  }

  return (
    localStorage.getItem("accessToken") ||
    localStorage.getItem("access_token") ||
    localStorage.getItem("authToken") ||
    localStorage.getItem("token") ||
    localStorage.getItem("gpsf_access_token") ||
    sessionStorage.getItem("accessToken") ||
    sessionStorage.getItem("access_token") ||
    sessionStorage.getItem("authToken") ||
    sessionStorage.getItem("token") ||
    ""
  );
}

function getMessage(
  message: string | string[] | undefined,
  fallback: string,
): string {
  return Array.isArray(message)
    ? message.join(", ")
    : message?.trim() || fallback;
}

function readUserId(value: unknown): string | null {
  if (!value || typeof value !== "object") {
    return null;
  }

  const record = value as Record<string, unknown>;
  const id = toPositiveNumber(
    record.id ?? record.userId ?? record.sub,
  );

  return id ? String(id) : null;
}

async function getCurrentUserId(): Promise<string> {
  const token = getAccessToken();

  const response = await fetch(`${API_BASE_URL}/auth/me`, {
    method: "GET",
    credentials: "include",
    cache: "no-store",
    headers: {
      Accept: "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
  });

  const payload = (await response.json()) as AuthMeResponse;

  if (!response.ok) {
    throw new Error(
      getMessage(
        payload.message,
        "Your login session has expired. Please login again.",
      ),
    );
  }

  const nestedUser =
    payload.data &&
    typeof payload.data === "object" &&
    "user" in payload.data
      ? payload.data.user
      : null;

  const userId =
    readUserId(payload.data) ??
    readUserId(nestedUser) ??
    readUserId(payload.user);

  if (!userId) {
    throw new Error(
      "Authenticated user ID was not returned by /auth/me.",
    );
  }

  return userId;
}

function mapStatus(value?: string | null): MinistryRgcDecisionStatus {
  const normalized = value
    ?.trim()
    .toUpperCase()
    .replaceAll("_", " ")
    .replaceAll("-", " ");

  if (normalized === "SOLVED") {
    return "Solved";
  }

  if (normalized === "IN PROGRESS") {
    return "In Progress";
  }

  return "Not Addressed";
}

function extractItems(
  payload: ApiResponse<ApiListData<ApiDecision> | ApiDecision[]>,
): ApiDecision[] {
  if (Array.isArray(payload.data)) {
    return payload.data;
  }

  if (payload.data && typeof payload.data === "object") {
    if (Array.isArray(payload.data.items)) {
      return payload.data.items;
    }

    if (Array.isArray(payload.data.data)) {
      return payload.data.data;
    }
  }

  return Array.isArray(payload.items) ? payload.items : [];
}

function getCategoryName(item: ApiDecision): string {
  if (item.categoryInfo?.name) {
    return item.categoryInfo.name.trim();
  }

  if (
    item.category &&
    typeof item.category === "object" &&
    item.category.name
  ) {
    return item.category.name.trim();
  }

  return typeof item.category === "string"
    ? item.category.trim()
    : "";
}

function getCategoryId(item: ApiDecision): number | null {
  return (
    toPositiveNumber(item.categoryId) ??
    toPositiveNumber(item.categoryInfo?.id) ??
    (typeof item.category === "object"
      ? toPositiveNumber(item.category?.id)
      : null)
  );
}

export async function getMinistryRgcDecisions(): Promise<
  MinistryRgcDecisionRow[]
> {
  const token = getAccessToken();
  const userId = await getCurrentUserId();

  const response = await fetch(
    `${API_BASE_URL}/rgc-decisions?limit=100`,
    {
      method: "GET",
      credentials: "include",
      cache: "no-store",
      headers: {
        Accept: "application/json",
        "x-user-id": userId,
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
      },
    },
  );

  const payload =
    (await response.json()) as ApiResponse<
      ApiListData<ApiDecision> | ApiDecision[]
    >;

  if (!response.ok) {
    throw new Error(
      getMessage(
        payload.message,
        "Unable to load Ministry RGC Decisions.",
      ),
    );
  }

  return extractItems(payload)
    .map((item): MinistryRgcDecisionRow | null => {
      const id = toPositiveNumber(item.id);

      if (!id) {
        return null;
      }

      // 🔥 Map issues safely without using any
      const mappedIssues: DecisionIssueItem[] = Array.isArray(item.issues)
        ? item.issues.map((issue) => ({
            id: Number(issue.id) || 0,
            title: issue.title?.trim() || issue.name?.trim() || `Issue ${issue.id ?? 1}`,
            description: issue.description?.trim() || null,
          }))
        : [];

      return {
        id,
        plenaryId: toPositiveNumber(item.plenaryId),

        ministryId:
          toPositiveNumber(item.stakeholderId) ??
          toPositiveNumber(item.stakeholder?.id),

        ministry: item.stakeholder?.name?.trim() || "",
        ministryLogo: item.stakeholder?.logo ?? null,

        decision: item.decision?.trim() || "",
        meetingDate: item.meetingDate?.slice(0, 10) || "",

        categoryId: getCategoryId(item),
        category: getCategoryName(item),

        status: mapStatus(item.statusCode ?? item.status),

        indicator:
          item.indicator?.name?.trim() ||
          item.indicatorName?.trim() ||
          "",

        focalPerson: item.focalPerson?.trim() || "",

        sourceOfVerification:
          item.verificationSource?.trim() ||
          item.sourceOfVerification?.trim() ||
          "",

        verificationLink:
          item.verificationLink?.trim() || null,

        issues: mappedIssues, // 🔥 បញ្ជូន issues ដែលបាន map រួច
      };
    })
    .filter(
      (item): item is MinistryRgcDecisionRow => item !== null,
    );
}