import { useRuntimeConfig } from "#app";
import type { FetchResponse } from "ofetch";
import { userFacingApiError } from "~/utils/workpulse-api-error";
import { workpulseApiRaw } from "~/utils/workpulse-api-fetch";
import { normalizeWorkpulseApiBase } from "~/utils/workpulse-api-base";
import { readWorkpulseAccessToken } from "~/utils/workpulse-session-user";
import { useAuth } from "./useAuth";

type ApiEnvelope<T> = {
  ok: boolean;
  data?: T;
  error?: { code?: string; message?: string };
};

export type MeProfile = {
  id: number;
  email: string;
  name: string;
  role: string;
  isActive: boolean;
  createdAt?: string | null;
  avatarUrl?: string | null;
  /** false jika login Google saja dan belum pernah set password */
  hasPassword?: boolean;
  permissions?: Partial<import("~/utils/workpulse-permissions").WorkpulsePermissions>;
};

export type MeSummaryPeriod = "month" | "week" | "all";

export type MeTodayReport = {
  id: number;
  status: string;
  reportDate?: string;
  updatedAt: string;
};

export type MeSummary = {
  period: string;
  reportsDraft: number;
  reportsSubmitted: number;
  reportsTotal: number;
  reportsExpected: number;
  productivityScore: number;
  goalProgressPercent: number;
  calendarEventsUpcoming: number;
  notificationsUnread: number;
  todayReport?: MeTodayReport | null;
};

export type MeFocusPreviewItem = {
  type: "notification" | "report";
  id: number;
  title: string;
  subtitle: string;
  at: string;
};

export type MeFocusPreviewData = {
  items: MeFocusPreviewItem[];
};

export type MeActivityItem = {
  type: "report" | "notification";
  id: number;
  title: string;
  description: string;
  at: string;
};

export type MeActivityData = {
  items: MeActivityItem[];
  total: number;
  limit: number;
  offset: number;
  hasMore: boolean;
};

function apiBase(): string {
  return normalizeWorkpulseApiBase(String(useRuntimeConfig().public.workpulseApiBase || ""));
}

function bearerHeaders(): { Authorization: string } | undefined {
  const { accessToken } = useAuth();
  const t = accessToken.value || readWorkpulseAccessToken();
  if (!t) return undefined;
  return { Authorization: `Bearer ${t}` };
}

async function parseEnvelope<T>(raw: FetchResponse<unknown>): Promise<{
  ok: boolean;
  status: number;
  data?: T;
  message?: string;
}> {
  const status = raw.status;
  let body = raw._data as ApiEnvelope<T> | string | undefined;
  if (typeof body === "string") {
    try {
      body = JSON.parse(body) as ApiEnvelope<T>;
    } catch {
      body = undefined;
    }
  }
  if (!body) return { ok: false, status, message: `HTTP ${status}` };
  if (!body.ok) {
    return {
      ok: false,
      status,
      message: body.error?.message || body.error?.code || `HTTP ${status}`
    };
  }
  return { ok: true, status, data: body.data as T };
}

export function useWorkpulseMe() {
  const getMe = async () => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const raw = await workpulseApiRaw(`${b}/api/v1/me`, {
      method: "GET",
      headers: bearerHeaders(),
      credentials: "include",
      ignoreResponseError: true
    });
    return parseEnvelope<MeProfile>(raw);
  };

  const patchMe = async (body: { name?: string; avatarUrl?: string }) => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const raw = await workpulseApiRaw(`${b}/api/v1/me`, {
      method: "PATCH",
      headers: bearerHeaders(),
      credentials: "include",
      body,
      ignoreResponseError: true
    });
    const parsed = await parseEnvelope<MeProfile>(raw);
    if (!parsed.ok) {
      return {
        ...parsed,
        message: userFacingApiError({
          code: (raw._data as ApiEnvelope<unknown>)?.error?.code,
          message: parsed.message,
          fallback: "Gagal menyimpan profil."
        })
      };
    }
    return parsed;
  };

  const uploadAvatar = async (file: File) => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const fd = new FormData();
    fd.append("avatar", file);
    const raw = await workpulseApiRaw(`${b}/api/v1/me/avatar`, {
      method: "POST",
      headers: bearerHeaders(),
      credentials: "include",
      body: fd,
      ignoreResponseError: true
    });
    const parsed = await parseEnvelope<MeProfile>(raw);
    if (!parsed.ok) {
      return {
        ...parsed,
        message: userFacingApiError({
          code: (raw._data as ApiEnvelope<unknown>)?.error?.code,
          message: parsed.message,
          fallback: "Gagal mengunggah foto."
        })
      };
    }
    return parsed;
  };

  const removeAvatar = async () => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const raw = await workpulseApiRaw(`${b}/api/v1/me/avatar`, {
      method: "DELETE",
      headers: bearerHeaders(),
      credentials: "include",
      ignoreResponseError: true
    });
    const parsed = await parseEnvelope<MeProfile>(raw);
    if (!parsed.ok) {
      return {
        ...parsed,
        message: userFacingApiError({
          code: (raw._data as ApiEnvelope<unknown>)?.error?.code,
          message: parsed.message,
          fallback: "Gagal menghapus foto."
        })
      };
    }
    return parsed;
  };

  const getMeSummary = async (params: { period?: MeSummaryPeriod; includeToday?: boolean } = {}) => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const qs = new URLSearchParams();
    if (params.period) qs.set("period", params.period);
    if (params.includeToday) qs.set("includeToday", "1");
    const q = qs.toString();
    const raw = await workpulseApiRaw(`${b}/api/v1/me/summary${q ? `?${q}` : ""}`, {
      method: "GET",
      headers: bearerHeaders(),
      credentials: "include",
      ignoreResponseError: true
    });
    return parseEnvelope<MeSummary>(raw);
  };

  const getFocusPreview = async (params: { limit?: number } = {}) => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const qs = new URLSearchParams();
    if (params.limit != null) qs.set("limit", String(params.limit));
    const q = qs.toString();
    const raw = await workpulseApiRaw(`${b}/api/v1/me/focus-preview${q ? `?${q}` : ""}`, {
      method: "GET",
      headers: bearerHeaders(),
      credentials: "include",
      ignoreResponseError: true
    });
    return parseEnvelope<MeFocusPreviewData>(raw);
  };

  const changePassword = async (body: { currentPassword?: string; newPassword: string }) => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const raw = await workpulseApiRaw(`${b}/api/v1/me/password`, {
      method: "POST",
      headers: bearerHeaders(),
      credentials: "include",
      body: {
        currentPassword: body.currentPassword?.trim() || undefined,
        newPassword: body.newPassword
      },
      ignoreResponseError: true
    });
    const parsed = await parseEnvelope<{ ok?: boolean }>(raw);
    if (!parsed.ok) {
      return {
        ...parsed,
        message: userFacingApiError({
          code: (raw._data as ApiEnvelope<unknown>)?.error?.code,
          message: parsed.message,
          fallback: "Gagal mengubah password."
        })
      };
    }
    return parsed;
  };

  const getMeActivity = async (params: { limit?: number; offset?: number } = {}) => {
    const b = apiBase();
    if (!b) return { ok: false as const, status: 0, message: "Layanan belum siap. Coba lagi nanti." };
    const qs = new URLSearchParams();
    if (params.limit != null) qs.set("limit", String(params.limit));
    if (params.offset != null) qs.set("offset", String(params.offset));
    const q = qs.toString();
    const raw = await workpulseApiRaw(`${b}/api/v1/me/activity${q ? `?${q}` : ""}`, {
      method: "GET",
      headers: bearerHeaders(),
      credentials: "include",
      ignoreResponseError: true
    });
    return parseEnvelope<MeActivityData>(raw);
  };

  return {
    getMe,
    patchMe,
    uploadAvatar,
    removeAvatar,
    changePassword,
    getMeSummary,
    getMeActivity,
    getFocusPreview
  };
}
