import AuthService from "../services/AuthService";

const API_BASE = process.env.NEXT_PUBLIC_API_URL || "https://45.93.137.91.nip.io/api";
const REPORT_API_BASE = process.env.NEXT_PUBLIC_REPORT_API_URL || "http://45.93.137.91/api";

function isFormData(value) {
  return typeof FormData !== "undefined" && value instanceof FormData;
}

class ApiBlockedError extends Error {
  constructor(message = "Your account is blocked") {
    super(message);
    this.name = "ApiBlockedError";
    this.status = 451;
  }
}

export function isApiBlockedError(error) {
  return error instanceof ApiBlockedError || error?.status === 451;
}

function redirectToBlockedPage() {
  if (
    typeof window !== "undefined" &&
    window.location.pathname !== "/blocked"
  ) {
    window.location.replace("/blocked");
  }
}

function assertNotBlocked(response) {
  if (response.status === 451) {
    redirectToBlockedPage();
    throw new ApiBlockedError();
  }
}

function buildApiUrl(base, endpoint) {
  return `${base.replace(/\/$/, "")}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`;
}

/**
 * Generic API fetch — attaches auth token, unwraps { data } envelope
 */
async function apiFetch(endpoint, options = {}) {
  const token = AuthService.getToken();

  const headers = {
    ...(token && { Authorization: `Bearer ${token}` }),
    ...(options.headers || {}),
  };

  const hasBody = options.body != null;
  const bodyIsFormData = isFormData(options.body);

  if (
    hasBody &&
    !bodyIsFormData &&
    !headers["Content-Type"] &&
    !headers["content-type"]
  ) {
    headers["Content-Type"] = "application/json";
  }

  const url = `${API_BASE}${endpoint}`;

  try {
    const res = await fetch(url, {
      ...options,
      headers,
      body:
        hasBody && !bodyIsFormData && typeof options.body !== "string"
          ? JSON.stringify(options.body)
          : options.body,
    });

    assertNotBlocked(res);

    if (!res.ok && res.status !== 206) {
      const text = await res.text().catch(() => "");
      throw new Error(`API ${res.status}: ${text || res.statusText}`);
    }

    const text = await res.text();
    if (!text) return null;

    try {
      const json = JSON.parse(text);
      if (json && typeof json === "object" && "data" in json) {
        return json.data;
      }
      return json;
    } catch {
      return text;
    }
  } catch (error) {
    if (error instanceof TypeError && error.message === 'Failed to fetch') {
      throw new Error(
        `تعذر الاتصال بالخادم. تحقق من اتصالك بالإنترنت أو حاول مرة أخرى لاحقاً. (${API_BASE}${endpoint})`,
      );
    }
    throw error;
  }
}

/**
 * Auth fetch — returns full { status, data, ok } for status-code handling
 */
async function authFetch(endpoint, body, token = null) {
  const headers = {};

  const bodyIsFormData = isFormData(body);
  if (!bodyIsFormData) {
    headers["Content-Type"] = "application/json";
  }

  if (token) {
    headers["Authorization"] = `Bearer ${token}`;
  }

  let res;
  try {
    res = await fetch(`${API_BASE}${endpoint}`, {
      method: "POST",
      headers,
      body: bodyIsFormData ? body : JSON.stringify(body),
    });
  } catch (err) {
    return { status: 0, data: null, ok: false, message: err.message };
  }

  assertNotBlocked(res);

  const text = await res.text();
  let data = null;

  try {
    data = text ? JSON.parse(text) : null;
    if (data && typeof data === "object" && "data" in data) {
      data = data.data;
    }
  } catch {
    data = text;
  }

  const message =
    typeof data === "object" && data?.message ? data.message : null;

  return {
    status: res.status,
    data,
    ok: res.ok || res.status === 206,
    message,
  };
}

async function reportFetch(endpoint, body) {
  let res;
  try {
    res = await fetch(buildApiUrl(REPORT_API_BASE, endpoint), {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
    });
  } catch (err) {
    return { status: 0, data: null, ok: false, message: err.message };
  }

  assertNotBlocked(res);

  const text = await res.text();
  let data = null;

  try {
    data = text ? JSON.parse(text) : null;
    if (data && typeof data === "object" && "data" in data) {
      data = data.data;
    }
  } catch {
    data = text;
  }

  const message =
    typeof data === "object" && data?.message ? data.message : null;

  return {
    status: res.status,
    data,
    ok: res.ok || res.status === 206,
    message,
  };
}

// ─── Rent Properties ───

export async function getRentProperties() {
  return apiFetch("/RentProperties/GetRentProperties");
}

export async function getRentProperty(id) {
  return apiFetch(`/RentProperties/GetRentPropertyById/${id}`);
}

export async function getRentPropertyLocations(params = {}) {
  const qs = new URLSearchParams();
  if (params.maxOffset != null) qs.set("maxOffset", params.maxOffset);
  if (params.minOffset != null) qs.set("minOffset", params.minOffset);
  const query = qs.toString();
  return apiFetch(
    `/RentProperties/GetRentPropertiesLocations${query ? `?${query}` : ""}`,
  );
}

// ─── Sale Properties ───

export async function getSaleProperties() {
  return apiFetch("/SaleProperties/GetSaleProperties");
}

export async function getSaleProperty(id) {
  const items = await apiFetch("/SaleProperties/GetSaleProperties");
  if (!Array.isArray(items)) return items;
  return items.find((p) => p.id == id) || items[0];
}

// ─── Properties (generic) ───

export async function getProperty(id) {
  return apiFetch(`/Properties/Get/${id}`);
}

// ─── Recommendations ───

export async function getRecommendations() {
  return apiFetch("/Recommendations/GetRecommendations");
}

export async function getTopRecommendations(count = 10) {
  return apiFetch(`/Recommendations/GetTopRecommendations?count=${count}`);
}

// ─── Reservations ───

export async function getAvailableDateRanges(
  propertyId,
  fromDate = null,
  toDate = null,
) {
  const qs = new URLSearchParams();
  if (fromDate) qs.set("fromDate", fromDate);
  if (toDate) qs.set("toDate", toDate);
  const query = qs.toString();

  return apiFetch(
    `/Reservations/GetAvailableDates/available/${propertyId}${query ? `?${query}` : ""}`,
  );
}

export async function getReservations() {
  return apiFetch("/Reservations/GetAllReservations");
}

export async function getReservation(id) {
  return apiFetch(`/Reservations/GetReservation?id=${id}`);
}

export async function checkAvailability(
  propertyId,
  fromDate = null,
  toDate = null,
) {
  const qs = new URLSearchParams();
  if (fromDate) qs.set("fromDate", fromDate);
  if (toDate) qs.set("toDate", toDate);
  const query = qs.toString();
  return apiFetch(
    `/Reservations/GetAvailable/${propertyId}${query ? `?${query}` : ""}`,
  );
}

export async function bookReservation(propertyInfoId, startDate, endDate) {
  return apiFetch("/Reservations/BookReservation/book", {
    method: "POST",
    body: {
      propertyInfoId,
      startDate,
      endDate,
    },
  });
}

// ─── Terms ───

export async function getARTerms() {
  return apiFetch("/Configuration/GetARTerms");
}

export async function getENTerms() {
  return apiFetch("/Configuration/GetENTerms");
}

// ─── Profile ───

export async function getCustomerByUserId(userId) {
  return apiFetch(`/Customer/GetByUserId/${userId}`);
}

export async function getOwnerByUserId(userId) {
  return apiFetch(`/Owner/GetByUserId/${userId}`);
}

// ─── Properties ───

export async function getMyRentListings() {
  return apiFetch("/RentProperties/GetMyRentListings");
}

export function buildRentPropertyPayload(data = {}) {
  const propertyInformation = data?.propertyInformation || {};
  const cityValue =
    data?.city ??
    data?.governorate ??
    propertyInformation?.city ??
    propertyInformation?.governorate ??
    "";
  const documentTypeValue =
    data?.documentType ?? propertyInformation?.documentType ?? "";

  return {
    ...data,
    city: cityValue,
    governorate: cityValue,
    documentType: documentTypeValue,
    propertyInformation: {
      ...propertyInformation,
      city: cityValue,
      governorate: propertyInformation?.governorate ?? cityValue,
      documentType: documentTypeValue,
    },
  };
}

export async function addRentProperty(data) {
  return apiFetch("/RentProperties/AddRentProperty", {
    method: "POST",
    body: buildRentPropertyPayload(data),
  });
}

export async function editRentProperty(id, data) {
  return apiFetch(`/RentProperties/EditRentProperty/${id}`, {
    method: "PUT",
    body: data,
  });
}

export async function editSaleProperty(id, data) {
  return apiFetch(`/SaleProperties/EditSaleProperty/${id}`, {
    method: "PUT",
    body: data,
  });
}

export async function addSaleProperty(data) {
  return apiFetch("/SaleProperties/AddSaleProperty", {
    method: "POST",
    body: data,
  });
}

export async function getMySaleListings() {
  return apiFetch("/SaleProperties/GetMySaleListings");
}

export async function getSalePropertyById(id) {
  return apiFetch(`/SaleProperties/${id}`);
}

export async function updateRentPropertyStatus(id, status) {
  return apiFetch(`/RentProperties/UpdateStatus/${id}`, {
    method: "PUT",
    body: { status },
  });
}

export async function updateSalePropertyStatus(id, status) {
  return apiFetch(`/SaleProperties/UpdateStatus/${id}`, {
    method: "PUT",
    body: { status },
  });
}

// ─── Currencies ───

export async function getCurrencies() {
  return apiFetch("/Currency/GetAll");
}

export async function getPaymentTypes() {
  return apiFetch("/PaymentType/GetAll");
}

// ─── Files ───

export async function uploadPicture(file) {
  const formData = new FormData();
  formData.append("image", file);

  const token = AuthService.getToken();

  let res;
  try {
    res = await fetch(`${API_BASE}/Files/UploadPicture`, {
      method: "POST",
      headers: {
        ...(token && { Authorization: `Bearer ${token}` }),
      },
      body: formData,
    });
  } catch (err) {
    throw new Error(`تعذر الاتصال بالخادم: ${err.message}`);
  }

  assertNotBlocked(res);

  const text = await res.text();

  if (!res.ok) throw new Error(`Upload failed: ${res.status} ${text}`);

  try {
    const json = JSON.parse(text);
    return json?.data || json;
  } catch {
    return text;
  }
}

// ─── Auth: Registration ───

async function multipartAuthFetch(endpoint, formData) {
  const token = AuthService.getToken();

  const res = await fetch(`${API_BASE}${endpoint}`, {
    method: "POST",
    headers: {
      ...(token && { Authorization: `Bearer ${token}` }),
    },
    body: formData,
  });

  assertNotBlocked(res);

  const text = await res.text();
  let data = null;

  try {
    data = text ? JSON.parse(text) : null;
    if (data && typeof data === "object" && "data" in data) {
      data = data.data;
    }
  } catch {
    data = text;
  }

  return {
    status: res.status,
    data,
    ok: res.ok || res.status === 206,
    message: data?.message,
  };
}

export async function addOwner(
  data,
  frontImage = null,
  backImage = null,
  licenseImage = null,
) {
  const formData = new FormData();

  formData.append("FirstName", data.firstName || data.FirstName || "");
  formData.append("LastName", data.lastName || data.LastName || "");
  formData.append("Email", data.email || data.Email || "");

  const phoneValue =
    data.phone || data.phoneNumber || data.Phone || data.PhoneNumber || "";
  const whatsappValue =
    data.whatsAppNumber ||
    data.whatsapp ||
    data.WhatsAppNumber ||
    data.WhatsApp ||
    "";

  formData.append("PhoneNumber", phoneValue);
  formData.append("Phone", phoneValue);
  formData.append("WhatsAppNumber", whatsappValue);

  formData.append(
    "NationalNumber",
    data.nationalNumber || data.NationalNumber || "",
  );
  formData.append("Password", data.password || data.Password || "");
  formData.append(
    "Type",
    String(data.type ?? data.ownerType ?? data.Type ?? 0),
  );
  formData.append("Language", String(data.language ?? data.Language ?? 1));

  if (frontImage) formData.append("FrontIdCarImagePath", frontImage);
  if (backImage) formData.append("RearIdCarImagePath", backImage);
  if (licenseImage) formData.append("LicenseImagePath", licenseImage);

  return multipartAuthFetch("/Owner/Add", formData);
}

export async function addCustomer(data, frontImage = null, backImage = null) {
  const formData = new FormData();
  formData.append("FirstName", data.firstName || data.FirstName || "");
  formData.append("LastName", data.lastName || data.LastName || "");
  formData.append("Email", data.email || "");
  formData.append("PhoneNumber", data.phoneNumber || "");
  formData.append("WhatsAppNumber", data.whatsAppNumber || "");
  formData.append("Phone", data.phone || "");
  formData.append("NationalNumber", data.nationalNumber || "");
  formData.append("Password", data.password || "");
  formData.append("Type", String(data.customerType ?? data.Type ?? 0));
  formData.append("Language", "0");

  if (frontImage) formData.append("FrontIdCarImagePath", frontImage);
  if (backImage) formData.append("RearIdCarImagePath", backImage);

  return multipartAuthFetch("/Customer/Add", formData);
}

// ─── Auth: Login ───

export async function loginWithEmail(credential, password) {
  return authFetch("/Auth/LogInWithEmail", {
    credential,
    password,
    device: 0,
    appVersion: "",
  });
}

export async function loginWithPhone(credential, password) {
  return authFetch("/Auth/LogInWithPhoneNumber", {
    credential,
    password,
    device: 0,
    appVersion: "",
  });
}

// ─── Auth: OTP ───

export async function sendEmailOTP() {
  return apiFetch("/Auth/SendEmailOTP", { method: "POST" });
}

export async function sendPhoneOTP() {
  return apiFetch("/Auth/SendPhoneNumberOTP", { method: "POST" });
}

export async function verifyEmail(code) {
  const token = AuthService.getToken();
  return authFetch(
    `/Auth/VerifyEmail?code=${encodeURIComponent(code)}`,
    {},
    token,
  );
}

export async function verifyPhone(code) {
  const token = AuthService.getToken();
  return authFetch(
    `/Auth/VerifyPhoneNumber?code=${encodeURIComponent(code)}`,
    {},
    token,
  );
}

// ─── Helpers ───

export function isEmail(value) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}

export function isPhoneNumber(value) {
  return /^\+?\d{7,15}$/.test(value.replace(/[\s\-()]/g, ""));
}

// ─── Favorites ───

export async function getUserFavoriteProperties() {
  return apiFetch("/FavoriteProperty/GetUserFavoriteProperties");
}

export async function addFavoriteProperty(propId) {
  return apiFetch(`/FavoriteProperty/Add?propId=${propId}`, { method: "POST" });
}

export async function removeFavoriteProperty(favePropId) {
  return apiFetch(`/FavoriteProperty/Remove?favePropId=${favePropId}`, {
    method: "DELETE",
  });
}

export async function getUserNotifications() {
  return apiFetch("/Notifications/GetUserNotifications");
}

// ─── Booking/Reservation Management ───

export async function confirmDepositPayment(bookingId) {
  return apiFetch("/Reservations/ConfirmDepositPayment", {
    method: "POST",
    body: { bookingId },
  });
}

export async function adminConfirmDeposit(
  reservationId,
  adminId,
  comment = null,
) {
  const token = AuthService.getToken();
  const normalizedComment =
    typeof comment === "string" && comment.trim() ? comment.trim() : null;
  const payload = {
    reservationId,
    adminId,
    comment: normalizedComment,
  };

  const res = await fetch(buildApiUrl(API_BASE, "/Reservations/AdminConfirmDeposit/admin-confirm-deposit"), {
    method: "PUT",
    headers: {
      "Content-Type": "application/json",
      ...(token && { Authorization: `Bearer ${token}` }),
    },
    body: JSON.stringify(payload),
  });

  const text = await res.text();
  let data = null;

  try {
    data = text ? JSON.parse(text) : null;
    if (data && typeof data === "object" && "data" in data) {
      data = data.data;
    }
  } catch {
    data = text;
  }

  const message =
    typeof data === "object" && data?.message ? data.message : null;

  return { status: res.status, data, ok: res.ok, message };
}

export async function updateBookingStatus(bookingId, status) {
  return apiFetch("/Reservations/UpdateStatus", {
    method: "PUT",
    body: { bookingId, status },
  });
}

// ─── Owner / Reservations ───

export async function getOwnerReservationRequests() {
  return apiFetch("/Reservations/GetOwnerResevationRequests");
}

export async function getOwnerReservationsByStatuses(filterStatuses) {
  return apiFetch("/Reservations/GetAllReservationsByStateForOwner", {
    method: "POST",
    body: { filterStatuses },
  });
}

export async function getUserReservations() {
  return apiFetch("/Reservations/GetUserResevations");
}

export async function ownerConfirmReservation(id) {
  return apiFetch(`/Reservations/OwnerConfirmReservation/owner-confirm/${id}`, {
    method: "PUT",
  });
}

// ─── Payments ───

export async function getMyTransaction() {
  return apiFetch("/Customer/GetMyTransaction");
}

export async function payDeposit(data) {
  const formData = new FormData();

  formData.append(
    "ReservationId",
    String(data.reservationId ?? data.ReservationId ?? "")
  );

  formData.append(
    "PaymentTypeId",
    String(data.paymentTypeId ?? data.PaymentTypeId ?? "")
  );

  if (data.comment) {
    formData.append("Comment", data.comment);
  } else {
    formData.append("Comment", "");
  }

  // صورة الوصل لطريقة الدفع Haram
  if (data.paymentImage) {
    formData.append("TransactionType", data.paymentImage);
    formData.append("paymentImage", data.paymentImage);
  }

  return apiFetch("/Reservations/PayDeposit/pay-deposit", {
    method: "POST",
    body: formData,
  });
}

// ─── Owner Contact & Stats ───

export async function getOwnerContactInformation(propertyInformationId) {
  return apiFetch(
    `/Owner/GetOwnerContactInformation?propertyInformationId=${propertyInformationId}`,
  );
}

export async function getOwnerStatistics() {
  return apiFetch("/Statistics/GetOwnerStatistics");
}

// ─── Agent Registration ───

export async function registerRealEstateAgent(formData) {
  const token = AuthService.getToken();

  const res = await fetch(`${API_BASE}/RealEstateAgent/Add`, {
    method: "POST",
    headers: {
      ...(token && { Authorization: `Bearer ${token}` }),
    },
    body: formData,
  });

  assertNotBlocked(res);

  const text = await res.text();
  let data = null;

  try {
    data = text ? JSON.parse(text) : null;
    if (data && typeof data === "object" && "data" in data) data = data.data;
  } catch {
    data = text;
  }

  return {
    status: res.status,
    data,
    ok: res.ok || res.status === 206,
    message: data?.message || (typeof data === "string" ? data : null),
  };
}

// ─── Change Password ───

export async function changePassword(oldPassword, newPassword) {
  return apiFetch(
    `/User/ChangePassword?oldPassword=${encodeURIComponent(oldPassword)}&newPassword=${encodeURIComponent(newPassword)}`,
    {
      method: "PUT",
    },
  );
}

// ─── Forget Password (OTP flow) ───

export async function requestForgetPasswordOtp(email) {
  return apiFetch(`/User/ForgetPassword?email=${encodeURIComponent(email)}`, {
    method: "POST",
  });
}

export async function verifyForgetPasswordOtp(email, code, newPassword) {
  return apiFetch(
    `/User/VerifyForgetPasswordOTP?email=${encodeURIComponent(email)}&code=${encodeURIComponent(code)}&newPassword=${encodeURIComponent(newPassword)}`,
    {
      method: "POST",
    },
  );
}

// ─── Reset Password (token flow) ───

export async function resetPassword(token) {
  return apiFetch(`/Auth/ResetPassword?token=${encodeURIComponent(token)}`);
}

// ─── Delete Account ───

export async function deleteMyAccount(password) {
  return apiFetch(
    `/User/DeleteMyAccount?password=${encodeURIComponent(password)}`,
    {
      method: "DELETE",
    },
  );
}

// ─── Set FCM Token ───

export async function setFCMToken(token, deviceType = 2) {
  return apiFetch("/User/SetFCMToken", {
    method: "POST",
    body: { token, deviceType },
  });
}

// ─── Filter Rent Properties ───

export async function filterRentProperties(params = {}) {
  const qs = new URLSearchParams();
  Object.entries(params).forEach(([k, v]) => {
    if (v != null && v !== "") qs.set(k, v);
  });
  const query = qs.toString();
  return apiFetch(
    `/RentProperties/FilterRentProperties${query ? `?${query}` : ""}`,
  );
}

// ─── Reports ───

export async function sendGeneralReport(subject, reportBody) {
  return reportFetch("/Reports/SendGeneralReport", {
    subject,
    body: reportBody,
  });
}

export async function submitReport(subject, body) {
  return apiFetch("/Reports/SendGeneralReport", {
    method: "POST",
    body: { subject, body },
  });
}

export async function submitReservationReport(data) {
  return apiFetch("/ReservationReports", {
    method: "POST",
    body: data,
  });
}

export async function updateReservationReport(id, data) {
  return apiFetch(`/ReservationReports/${id}`, {
    method: "PUT",
    body: data,
  });
}

export async function submitSaleReport(data) {
  return apiFetch("/SaleReports", {
    method: "POST",
    body: data,
  });
}

export async function updateSaleReport(id, data) {
  return apiFetch(`/SaleReports/${id}`, {
    method: "PUT",
    body: data,
  });
}

// ─── Terms (Add or Update) ───

export async function addOrUpdateTerms(terms) {
  return apiFetch("/Terms/AddOrUpdateTerms", {
    method: "POST",
    body: terms,
  });
}