// static/js/globals.jsx

// Достаём хуки из React один раз и делаем их глобальными
const { useState, useEffect, createContext, useContext } = React;

// Базовый URL API — тот же домен, с которого открыт фронт
const API_URL = window.location.origin;

// Глобальный контекст авторизации
const AuthContext = createContext(null);

/**
 * Централизованный слой работы с API.
 *
 * Здесь собраны все вызовы к бэкенду, чтобы:
 *  - не размазывать fetch по компонентам,
 *  - проще было потом менять урлы / заголовки / авторизацию.
 */
const API = {
  // --------- АУТЕНТИФИКАЦИЯ / РЕГИСТРАЦИЯ ---------

  /**
   * Логин по email/паролю.
   * Возвращает access_token или кидает Error с текстом.
   */
  async login(email, password) {
    const formData = new FormData();
    formData.append("username", email);
    formData.append("password", password);

    const res = await fetch(`${API_URL}/token`, {
      method: "POST",
      body: formData,
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка авторизации");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка авторизации");
    }

    return data.access_token;
  },

  /**
   * Регистрация пользователя.
   * (Сейчас без invite_code — форма регистрации пока не использует коды.)
   */
  async register({ email, password, first_name, last_name, invite_code }) {
    const res = await fetch(`${API_URL}/register`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        email,
        first_name,
        last_name,
        password,
        invite_code, // отправляем код приглашения в бэк
      }),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка регистрации");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка регистрации");
    }

    return data;
     },


       /**
   * Получение текущего пользователя (/users/me).
   */
  async getCurrentUser(token) {
    const res = await fetch(`${API_URL}/users/me`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка загрузки профиля");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка загрузки профиля");
    }

    return data;
  },

  
  /**
   * Обновление профиля текущего пользователя.
   * Возвращает обновлённый объект пользователя.
   */
  async updateProfile(token, { email, first_name, last_name }) {
    const res = await fetch(`${API_URL}/users/me`, {
      method: "PUT",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        email,
        first_name,
        last_name,
      }),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка сохранения профиля");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка сохранения профиля");
    }

    return data;
  },

  /**
   * Смена пароля текущего пользователя.
   */
  async changePassword(token, { old_password, new_password }) {
    const res = await fetch(`${API_URL}/users/me/change_password`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        old_password,
        new_password,
      }),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка смены пароля");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка смены пароля");
    }

    return data;
  },

  // --------- ПРОФИЛЬ КОМПАНИИ / ОРГАНИЗАЦИИ ---------

  /**
   * Получить профиль компании текущего пользователя.
   * GET /organization/me
   */
  async getOrganization(token) {
    const res = await fetch(`${API_URL}/organization/me`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка загрузки профиля компании");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка загрузки профиля компании");
    }

    return data;
  },

  /**
   * Обновить профиль компании.
   * PUT /organization/me
   */
  async updateOrganization(
    token,
    { name, description, contact_email, contact_phone, website, logo_url }
  ) {
    const res = await fetch(`${API_URL}/organization/me`, {
      method: "PUT",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        name,
        description,
        contact_email,
        contact_phone,
        website,
        logo_url,
      }),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка сохранения профиля компании");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка сохранения профиля компании");
    }

    return data;
  },

  /**
   * Сгенерировать новый инвайт-код компании.
   * POST /organization/me/invite/regenerate
   */
  async regenerateInviteCode(token) {
    const res = await fetch(
      `${API_URL}/organization/me/invite/regenerate`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка генерации инвайт-кода");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка генерации инвайт-кода");
    }

    return data;
  },

  // --------- ТЕСТЫ ДЛЯ СОТРУДНИКА ---------

  /**
   * Список доступных тестов для сотрудника.
   */
  async getAvailableTests(token) {
    const res = await fetch(`${API_URL}/tests/available`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      throw new Error("Ошибка загрузки доступных тестов");
    }

    return await res.json();
  },

  /**
   * Запуск теста для сотрудника.
   * POST /tests/{test_id}/start
   * Возвращает структуру теста + attempt_id.
   */
  async userStartTest(token, testId) {
    const res = await fetch(`${API_URL}/tests/${testId}/start`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка запуска теста");
    }

    if (!res.ok) {
      // Попробуем вытащить detail, если он есть
      throw new Error(data.detail || "Ошибка запуска теста");
    }

    return data;
  },

  /**
   * Отправка ответа на один вопрос в рамках попытки.
   * POST /tests/submit_answer?attempt_id=...
   *
   * payload:
   *  - question_id
   *  - selected_options: number[]
   *  - text_answer: string
   *  - time_spent: number (секунды)
   */
  async userSubmitAnswer(token, attemptId, payload) {
    const res = await fetch(
      `${API_URL}/tests/submit_answer?attempt_id=${attemptId}`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(payload),
      }
    );

    let data = null;
    try {
      data = await res.json();
    } catch (e) {
      // Бэк раньше и так не всегда возвращал тело, поэтому просто
      // даём общее сообщение, если статус не ок
    }

    if (!res.ok) {
      throw new Error(
        (data && data.detail) || "Ошибка отправки ответа по тесту"
      );
    }

    // Здесь обычно можно ничего не возвращать, но вдруг бэк что-то шлёт
    return data;
  },

  /**
   * Завершение попытки теста.
   * POST /tests/{attempt_id}/finish
   * Возвращает итог результата (score, percent, passed и т.п.).
   */
  async userFinishAttempt(token, attemptId) {
    const res = await fetch(`${API_URL}/tests/${attemptId}/finish`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка завершения теста");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка завершения теста");
    }

    return data;
  },

  // --------- АДМИН: СОТРУДНИКИ ---------

  /**
   * Получить список сотрудников для админа.
   */
  async adminGetUsers(token) {
    const res = await fetch(`${API_URL}/admin/users`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      throw new Error("Ошибка загрузки списка сотрудников");
    }

    const data = await res.json();
    return Array.isArray(data) ? data : [];
  },

  /**
   * Создать нового сотрудника.
   */
  async adminCreateUser(token, payload) {
    const res = await fetch(`${API_URL}/admin/users`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка создания сотрудника");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка создания сотрудника");
    }

    return data;
  },

  /**
   * Обновить сотрудника по id.
   * В payload можно не передавать password, если он не меняется.
   */
  async adminUpdateUser(token, id, payload) {
    const res = await fetch(`${API_URL}/admin/users/${id}`, {
      method: "PUT",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка обновления сотрудника");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка обновления сотрудника");
    }

    return data;
  },

  /**
   * Удалить сотрудника по id.
   */
  async adminDeleteUser(token, id) {
    const res = await fetch(`${API_URL}/admin/users/${id}`, {
      method: "DELETE",
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      let data = null;
      try {
        data = await res.json();
      } catch (e) {
        // ignore
      }
      const msg =
        data && data.detail ? data.detail : "Ошибка удаления сотрудника";
      throw new Error(msg);
    }

    return true;
  },

  // --------- АДМИН: ТЕСТЫ ---------

  /**
   * Получить список тестов для админа.
   */
  async adminGetTests(token) {
    const res = await fetch(`${API_URL}/admin/tests`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      throw new Error("Ошибка загрузки списка тестов");
    }

    const data = await res.json();
    return Array.isArray(data) ? data : [];
  },

  /**
   * Получить тест с вопросами по id.
   */
  async adminGetTestById(token, id) {
    const res = await fetch(`${API_URL}/admin/tests/${id}`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      throw new Error("Ошибка загрузки теста");
    }

    return await res.json();
  },

  /**
   * Создать новый тест.
   */
  async adminCreateTest(token, payload) {
    const res = await fetch(`${API_URL}/admin/tests`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка создания теста");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка создания теста");
    }

    return data;
  },

  /**
   * Обновить существующий тест.
   */
  async adminUpdateTest(token, id, payload) {
    const res = await fetch(`${API_URL}/admin/tests/${id}`, {
      method: "PUT",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка обновления теста");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка обновления теста");
    }

    return data;
  },

  /**
   * Удалить тест.
   */
  async adminDeleteTest(token, id) {
    const res = await fetch(`${API_URL}/admin/tests/${id}`, {
      method: "DELETE",
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      let data = null;
      try {
        data = await res.json();
      } catch (e) {
        // ignore
      }
      const msg =
        data && data.detail ? data.detail : "Ошибка удаления теста";
      throw new Error(msg);
    }

    return true;
  },

  /**
   * Обновить статус активности теста.
   */
  async adminUpdateTestStatus(token, id, is_active) {
    const res = await fetch(`${API_URL}/admin/tests/${id}/status`, {
      method: "PATCH",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ is_active }),
    });

    if (!res.ok) {
      let data = null;
      try {
        data = await res.json();
      } catch (e) {
        // ignore
      }
      const msg =
        data && data.detail ? data.detail : "Ошибка обновления статуса теста";
      throw new Error(msg);
    }

    return await res.json();
  },

  // --------- АДМИН: АНАЛИТИКА ---------

  /**
   * Получить детальную аналитику по тесту.
   * GET /admin/analytics/test/{test_id}
   */
  async adminGetTestAnalytics(token, testId) {
    const res = await fetch(`${API_URL}/admin/analytics/test/${testId}`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    let data;
    try {
      data = await res.json();
    } catch (e) {
      throw new Error("Ошибка при загрузке аналитики");
    }

    if (!res.ok) {
      throw new Error(data.detail || "Ошибка при загрузке аналитики");
    }

    return data;
  },

  /**
   * Скачать CSV-отчёт по тесту.
   * GET /admin/analytics/test/{test_id}/csv
   * Возвращает Blob.
   */
  async adminDownloadTestCsv(token, testId) {
    const res = await fetch(`${API_URL}/admin/analytics/test/${testId}/csv`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!res.ok) {
      throw new Error("Не удалось скачать отчет");
    }

    return await res.blob();
  },
};
