<script setup lang="ts">
import type { Bot, PaginatedResponse, Signal, SubscriptionStatus, User, UserBotAccess } from "~/types";

definePageMeta({
  middleware: "admin"
});

type AdminUser = User & {
  pushSubscriptions: { id: string; endpoint: string; active: boolean }[];
};

type AdminPushDashboard = {
  items: Array<{
    id: string;
    status: "ok" | "ready" | "error" | "inactive";
    endpointHost: string;
    user: {
      id: string;
      email: string;
    };
    latestEvent: {
      statusCode: number | null;
      reason: string | null;
    } | null;
  }>;
};

type SubscriptionDraft = {
  status: SubscriptionStatus;
  startsAt: string;
  expiresAt: string;
};

const { formatDateTime } = useBrowserDateTime();

const initialForm = () => ({
  eventId: "",
  sportType: "football",
  leagueName: "",
  homeTeam: "",
  awayTeam: "",
  eventStartTime: "",
  marketType: "1X2",
  selection: "",
  lineValue: "",
  odds: "1.90",
  signalTime: "",
  comment: ""
});

const fieldLabels: Record<keyof ReturnType<typeof initialForm>, string> = {
  eventId: "ID события",
  sportType: "Вид спорта",
  leagueName: "Лига",
  homeTeam: "Домашняя команда",
  awayTeam: "Гостевая команда",
  eventStartTime: "Время начала события",
  marketType: "Тип рынка",
  selection: "Выбор",
  lineValue: "Значение линии",
  odds: "Коэффициент",
  signalTime: "Время сигнала",
  comment: "Комментарий"
};

const getFieldLabel = (key: string) => fieldLabels[key as keyof typeof fieldLabels];
const getFormValue = (key: string) => form.value[key as keyof typeof form.value];
const handleFormInput = (event: Event, key: string) => {
  const target = event.target as HTMLInputElement | null;
  form.value[key as keyof typeof form.value] = target?.value ?? "";
};

const form = ref(initialForm());
const signals = ref<Signal[]>([]);
const users = ref<AdminUser[]>([]);
const bots = ref<Bot[]>([]);
const pushDashboard = ref<AdminPushDashboard | null>(null);
const pushDashboardLoading = ref(false);
const pushDashboardError = ref("");
const broadcastTitle = ref("");
const broadcastBody = ref("");
const userSearch = ref("");
const usersLoading = ref(false);
const userActionMessage = ref("");
const createSignalOpen = ref(false);
const subscriptionDrafts = ref<Record<string, SubscriptionDraft>>({});
const savingSubscriptionKey = ref<string | null>(null);
const togglingUserId = ref<string | null>(null);

const subscriptionStatusOptions: Array<{ value: SubscriptionStatus; label: string }> = [
  { value: "active", label: "Активна" },
  { value: "expired", label: "Истекла" },
  { value: "canceled", label: "Отменена" }
];

const statusLabel: Record<"ok" | "ready" | "error" | "inactive", string> = {
  ok: "OK",
  ready: "Готово",
  error: "Ошибка",
  inactive: "Неактивно"
};

const subscriptionStatusLabel: Record<SubscriptionStatus, string> = {
  active: "Активна",
  expired: "Истекла",
  canceled: "Отменена"
};

const userRoleLabel = (role: User["role"]) => (role === "admin" ? "Администратор" : "Пользователь");
const userActiveLabel = (active?: boolean) => (active ? "активен" : "отключен");

const statusBadgeClass = (status: "ok" | "ready" | "error" | "inactive") => {
  if (status === "error") return "signal-row__badge--manual_review";
  if (status === "inactive") return "signal-row__badge--inactive";
  return "signal-row__badge--win";
};

const subscriptionBadgeClass = (status: SubscriptionStatus, isActiveNow?: boolean) => {
  if (status === "canceled") return "signal-row__badge--inactive";
  if (status === "expired" || !isActiveNow) return "signal-row__badge--manual_review";
  return "signal-row__badge--win";
};

const subscriptionSelectClass = (status: SubscriptionStatus) => {
  if (status === "canceled") return "admin-subscription-select admin-subscription-select--canceled";
  if (status === "expired") return "admin-subscription-select admin-subscription-select--expired";
  return "admin-subscription-select admin-subscription-select--active";
};

const subscriptionsByUserId = computed(() => {
  const grouped = new Map<string, AdminPushDashboard["items"]>();

  for (const item of pushDashboard.value?.items ?? []) {
    const userItems = grouped.get(item.user.id) ?? [];
    userItems.push(item);
    grouped.set(item.user.id, userItems);
  }

  return grouped;
});

const toDateTimeLocal = (value?: string | null) => {
  if (!value) return "";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "";

  const pad = (part: number) => String(part).padStart(2, "0");
  const year = date.getFullYear();
  const month = pad(date.getMonth() + 1);
  const day = pad(date.getDate());
  const hours = pad(date.getHours());
  const minutes = pad(date.getMinutes());

  return `${year}-${month}-${day}T${hours}:${minutes}`;
};

const subscriptionDraftKey = (userId: string, botId: string) => `${userId}:${botId}`;

const createSubscriptionDraft = (access?: UserBotAccess): SubscriptionDraft => ({
  status: access?.status ?? "canceled",
  startsAt: toDateTimeLocal(access?.startsAt ?? new Date().toISOString()),
  expiresAt: toDateTimeLocal(access?.expiresAt ?? null)
});

const assignDrafts = (items: AdminUser[]) => {
  const nextDrafts: Record<string, SubscriptionDraft> = {};

  for (const user of items) {
    for (const bot of bots.value) {
      const access = (user.botAccesses ?? []).find((entry: UserBotAccess) => entry.bot.id === bot.id);
      nextDrafts[subscriptionDraftKey(user.id, bot.id)] = createSubscriptionDraft(access);
    }
  }

  subscriptionDrafts.value = nextDrafts;
};

const loadUsers = async () => {
  usersLoading.value = true;

  try {
    const query = userSearch.value.trim();
    const suffix = query ? `?q=${encodeURIComponent(query)}` : "";
    const usersData = await useApi<AdminUser[]>(`/admin/users${suffix}`);
    users.value = usersData;
    assignDrafts(usersData);
    userActionMessage.value = "";
  } finally {
    usersLoading.value = false;
  }
};

const loadCore = async () => {
  const [signalsData, botsData] = await Promise.all([
    useApi<PaginatedResponse<Signal>>("/signals?page=1&perPage=200&published=true"),
    useApi<Bot[]>("/admin/bots")
  ]);

  signals.value = signalsData.items;
  bots.value = botsData;
  await loadUsers();
};

const loadPushDashboard = async () => {
  pushDashboardLoading.value = true;

  try {
    pushDashboard.value = await useApi<AdminPushDashboard>("/admin/push-subscriptions");
    pushDashboardError.value = "";
  } catch (error) {
    pushDashboard.value = null;
    pushDashboardError.value = error instanceof Error ? error.message : "Не удалось загрузить статусы подписок";
  } finally {
    pushDashboardLoading.value = false;
  }
};

const load = async () => {
  await Promise.all([loadCore(), loadPushDashboard()]);
};

onMounted(async () => {
  await load();
});

const createSignal = async () => {
  await useApi("/admin/signals", {
    method: "POST",
    body: {
      ...form.value,
      eventStartTime: new Date(form.value.eventStartTime).toISOString(),
      signalTime: new Date(form.value.signalTime || form.value.eventStartTime).toISOString(),
      lineValue: form.value.lineValue ? Number(form.value.lineValue) : null,
      odds: Number(form.value.odds),
      sourceType: "manual",
      published: true
    }
  });

  form.value = initialForm();
  createSignalOpen.value = false;
  await loadCore();
};

const setStatus = async (signalId: string, status: Signal["status"]) => {
  await useApi(`/admin/signals/${signalId}/set-status`, {
    method: "POST",
    body: {
      status,
      explanation: `Статус был установлен вручную: ${status}`
    }
  });

  await loadCore();
};

const sendPush = async (signalId: string) => {
  await useApi(`/admin/signals/${signalId}/send-push`, {
    method: "POST",
    body: {}
  });
};

const sendBroadcast = async () => {
  await useApi("/admin/broadcast", {
    method: "POST",
    body: {
      title: broadcastTitle.value,
      body: broadcastBody.value
    }
  });

  broadcastTitle.value = "";
  broadcastBody.value = "";
};

const updateSubscriptionDraft = (userId: string, botId: string, patch: Partial<SubscriptionDraft>) => {
  const key = subscriptionDraftKey(userId, botId);
  subscriptionDrafts.value = {
    ...subscriptionDrafts.value,
    [key]: {
      ...createSubscriptionDraft(),
      ...(subscriptionDrafts.value[key] ?? {}),
      ...patch
    }
  };
};

const handleSubscriptionStatusChange = (event: Event, userId: string, botId: string) => {
  const target = event.target as HTMLSelectElement | null;
  updateSubscriptionDraft(userId, botId, { status: (target?.value as SubscriptionStatus | undefined) ?? "canceled" });
};

const handleSubscriptionStartsAtChange = (event: Event, userId: string, botId: string) => {
  const target = event.target as HTMLInputElement | null;
  updateSubscriptionDraft(userId, botId, { startsAt: target?.value ?? "" });
};

const handleSubscriptionExpiresAtChange = (event: Event, userId: string, botId: string) => {
  const target = event.target as HTMLInputElement | null;
  updateSubscriptionDraft(userId, botId, { expiresAt: target?.value ?? "" });
};

const findUserSubscription = (member: AdminUser, botId: string) =>
  (member.botAccesses ?? []).find((entry) => entry.bot.id === botId);

const addDays = (date: Date, days: number) => {
  const next = new Date(date);
  next.setDate(next.getDate() + days);
  return next;
};

const saveSubscription = async (userId: string, botId: string) => {
  const key = subscriptionDraftKey(userId, botId);
  const draft = subscriptionDrafts.value[key];
  if (!draft) return;

  savingSubscriptionKey.value = key;

  try {
    const savedSubscription = await useApi<UserBotAccess>(`/admin/users/${userId}/subscriptions/${botId}`, {
      method: "PATCH",
      body: {
        status: draft.status,
        startsAt: draft.startsAt ? new Date(draft.startsAt).toISOString() : new Date().toISOString(),
        expiresAt: draft.expiresAt ? new Date(draft.expiresAt).toISOString() : null
      }
    });

    users.value = users.value.map((user) => {
      if (user.id !== userId) return user;

      const existing = (user.botAccesses ?? []).filter((entry: UserBotAccess) => entry.bot.id !== botId);
      return {
        ...user,
        botAccesses: [...existing, savedSubscription].sort((left, right) => left.bot.name.localeCompare(right.bot.name, "ru"))
      };
    });

    updateSubscriptionDraft(userId, botId, createSubscriptionDraft(savedSubscription));

    const userEmail = users.value.find((entry) => entry.id === userId)?.email ?? "пользователя";
    const botName = bots.value.find((entry) => entry.id === botId)?.name ?? "бота";
    userActionMessage.value = `Подписка ${userEmail} на ${botName} обновлена`;
  } finally {
    savingSubscriptionKey.value = null;
  }
};

const activateMonthlySubscription = async (userId: string, botId: string) => {
  const now = new Date();
  const expiresAt = addDays(now, 30);

  updateSubscriptionDraft(userId, botId, {
    status: "active",
    startsAt: toDateTimeLocal(now.toISOString()),
    expiresAt: toDateTimeLocal(expiresAt.toISOString())
  });

  await saveSubscription(userId, botId);
};

const toggleUserActive = async (user: AdminUser) => {
  togglingUserId.value = user.id;

  try {
    const updated = await useApi<AdminUser>(`/admin/users/${user.id}/active`, {
      method: "PATCH",
      body: {
        active: !user.active
      }
    });

    users.value = users.value.map((entry) => (entry.id === user.id ? { ...entry, active: updated.active } : entry));
    userActionMessage.value = `${updated.email}: ${updated.active ? "доступ включен" : "доступ отключен"}`;
  } finally {
    togglingUserId.value = null;
  }
};
</script>

<template>
  <section class="page admin-grid">
    <!-- <div class="panel">
      <div class="page-header page-header--admin-section">
        <div>
          <h1>Создание сигнала</h1>
          <p class="muted">Разверните блок, чтобы добавить сигнал вручную.</p>
        </div>
        <button class="secondary" type="button" @click="createSignalOpen = !createSignalOpen">
          {{ createSignalOpen ? "Свернуть" : "Развернуть" }}
        </button>
      </div>

      <form v-if="createSignalOpen" class="admin-list" @submit.prevent="createSignal">
        <label v-for="(value, key) in form" :key="key">
          {{ getFieldLabel(String(key)) }}
          <input
            :value="getFormValue(String(key))"
            :type="String(key).includes('Time') ? 'datetime-local' : 'text'"
            @input="handleFormInput($event, String(key))"
          />
        </label>
        <button type="submit">Сохранить сигнал</button>
      </form>
    </div> -->

    <!-- <div class="panel">
      <h2>Действия с сигналами</h2>
      <div class="admin-list">
        <div v-for="signal in signals" :key="signal.id" class="admin-row">
          <div>
            <strong>{{ signal.homeTeam }} - {{ signal.awayTeam }}</strong>
            <p>{{ signal.selection }} @ {{ signal.odds }}</p>
            <p v-if="signal.forecast" class="muted">{{ signal.forecast }}</p>
            <p v-if="signal.rawPayload?.botName" class="muted">{{ signal.rawPayload.botName }}</p>
          </div>
          <div class="button-row">
            <button class="secondary" @click="sendPush(signal.id)">Отправить push</button>
            <button class="secondary" @click="setStatus(signal.id, 'win')">Выигрыш</button>
            <button class="secondary" @click="setStatus(signal.id, 'lose')">Проигрыш</button>
            <button class="secondary" @click="setStatus(signal.id, 'void')">Возврат</button>
          </div>
        </div>
      </div>
    </div> -->

    <div class="panel">
      <h2>Отправить уведомление со своим текстом</h2>
      <label>
        Заголовок
        <input v-model="broadcastTitle" />
      </label>
      <label>
        Текст
        <textarea v-model="broadcastBody" rows="4" />
      </label>
      <button @click="sendBroadcast">Отправить рассылку</button>
    </div>
<!-- 
    <div class="panel">
      <div class="page-header page-header--admin-section">
        <h2>Push-подписки</h2>
        <NuxtLink class="topbar__link" to="/admin/pushes">Открыть монитор</NuxtLink>
      </div>
      <p class="muted">Отдельная страница со всеми подписками, статусами доставки и автообновлением.</p>
      <p v-if="pushDashboardLoading" class="muted">Загрузка статусов подписок...</p>
      <p v-else-if="pushDashboardError" class="error">Статусы подписок недоступны: {{ pushDashboardError }}</p>
      <p v-else-if="pushDashboard" class="muted">
        {{ pushDashboard.items.length }} подписок, {{ pushDashboard.items.filter((item) => item.status === "ok").length }} OK,
        {{ pushDashboard.items.filter((item) => item.status === "ready").length }} готово,
        {{ pushDashboard.items.filter((item) => item.status === "error").length }} ошибок.
      </p>
    </div> -->

    <div class="panel">
      <div class="page-header page-header--admin-section">
        <div>
          <h2>Пользователи и подписки</h2>
          <p class="muted">Ищите пользователя по email и управляйте подпиской на каждого бота отдельно.</p>
        </div>
      </div>

      <div class="admin-users-toolbar">
        <input
          v-model="userSearch"
          class="admin-users-toolbar__search"
          placeholder="Поиск по email"
          @keyup.enter="loadUsers"
        />
        <button class="secondary" :disabled="usersLoading" @click="loadUsers">
          {{ usersLoading ? "Поиск..." : "Найти пользователя" }}
        </button>
      </div>

      <p v-if="userActionMessage" class="success">{{ userActionMessage }}</p>

      <div class="admin-list">
        <article v-for="member in users" :key="member.id" class="admin-user-card">
          <div class="admin-user-card__header">
            <div>
              <strong>{{ member.email }}</strong>
              <p class="muted">
                {{ userRoleLabel(member.role) }} · {{ userActiveLabel(member.active) }} · создан
                {{ formatDateTime(member.createdAt ?? "") }}
              </p>
            </div>

            <button
              class="secondary"
              :disabled="togglingUserId === member.id"
              @click="toggleUserActive(member)"
            >
              {{ togglingUserId === member.id ? "Сохранение..." : member.active ? "Отключить пользователя" : "Включить пользователя" }}
            </button>
          </div>

          <div class="admin-user-card__body">
            <div class="p-4 mt-2 border rounded-2xl border-(--border)">
              <p class="muted">Текущие подписки</p>
              <div class="admin-bot-chip-list">
                <span
                  v-for="access in member.botAccesses ?? []"
                  :key="access.id"
                  class="signal-row__badge"
                  :class="subscriptionBadgeClass(access.status, access.isActiveNow)"
                >
                  {{ access.bot.name }} · {{ subscriptionStatusLabel[access.status] }}
                </span>
                <span v-if="!(member.botAccesses ?? []).length" class="muted">Подписок пока нет</span>
              </div>

              <div v-if="subscriptionsByUserId.get(member.id)?.length" class="admin-user-subscriptions">
                <div
                  v-for="subscription in subscriptionsByUserId.get(member.id)"
                  :key="subscription.id"
                  class="admin-user-subscription"
                >
                  <span class="signal-row__badge" :class="statusBadgeClass(subscription.status)">
                    {{ statusLabel[subscription.status] }}
                  </span>
                  <span class="muted">{{ subscription.endpointHost }}</span>
                  <span v-if="subscription.latestEvent?.statusCode" class="muted">
                    {{ subscription.latestEvent.statusCode }}
                  </span>
                  <span v-if="subscription.latestEvent?.reason" class="muted">
                    {{ subscription.latestEvent.reason }}
                  </span>
                </div>
              </div>
            </div>

            <details class="admin-subscription-manager">
              <summary class="admin-subscription-manager__toggle">
                <span>Управление подписками по ботам</span>
                <span class="admin-subscription-manager__toggle-icon" aria-hidden="true">+</span>
              </summary>
              <div class="admin-subscription-grid admin-subscription-grid--mobile">
                <article v-for="bot in bots" :key="bot.id" class="admin-subscription-card">
                  <div class="admin-subscription-card__header">
                    <div>
                      <strong>{{ bot.name }}</strong>
                      <small>{{ bot.key }}</small>
                    </div>
                  </div>

                  <label>
                    Статус
                    <select
                      :class="subscriptionSelectClass(
                        subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.status ?? 'canceled'
                      )"
                      :value="subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.status ?? 'canceled'"
                      @change="handleSubscriptionStatusChange($event, member.id, bot.id)"
                    >
                      <option
                        v-for="option in subscriptionStatusOptions"
                        :key="option.value"
                        :value="option.value"
                      >
                        {{ option.label }}
                      </option>
                    </select>
                  </label>

                  <label>
                    Начало
                    <input
                      type="datetime-local"
                      :value="subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.startsAt ?? ''"
                      @input="handleSubscriptionStartsAtChange($event, member.id, bot.id)"
                    />
                  </label>

                  <label>
                    Окончание
                    <input
                      type="datetime-local"
                      :value="subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.expiresAt ?? ''"
                      @input="handleSubscriptionExpiresAtChange($event, member.id, bot.id)"
                    />
                  </label>

                  <div class="button-row">
                    <button
                      class="secondary"
                      :disabled="savingSubscriptionKey === subscriptionDraftKey(member.id, bot.id)"
                      @click="activateMonthlySubscription(member.id, bot.id)"
                    >
                      Активировать на месяц
                    </button>
                    <button
                      :disabled="savingSubscriptionKey === subscriptionDraftKey(member.id, bot.id)"
                      @click="saveSubscription(member.id, bot.id)"
                    >
                      {{
                        savingSubscriptionKey === subscriptionDraftKey(member.id, bot.id)
                          ? "Сохранение..."
                          : "Сохранить подписку"
                      }}
                    </button>
                  </div>
                </article>
              </div>

              <div class="admin-subscription-table-wrap">
                <table class="admin-subscription-table">
                  <thead>
                    <tr>
                      <th>Бот</th>
                      <th>Статус</th>
                      <th>Начало</th>
                      <th>Окончание</th>
                      <th>Действия</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="bot in bots" :key="`table-${bot.id}`">
                      <td class="admin-subscription-table__bot">
                        <strong>{{ bot.name }}</strong>
                        <small>{{ bot.key }}</small>
                      </td>
                      <td>
                        <div class="admin-subscription-table__field">
                          <select
                            :class="subscriptionSelectClass(
                              subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.status ?? 'canceled'
                            )"
                            :value="subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.status ?? 'canceled'"
                            @change="handleSubscriptionStatusChange($event, member.id, bot.id)"
                          >
                            <option
                              v-for="option in subscriptionStatusOptions"
                              :key="option.value"
                              :value="option.value"
                            >
                              {{ option.label }}
                            </option>
                          </select>
                        </div>
                      </td>
                      <td>
                        <input
                          type="datetime-local"
                          :value="subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.startsAt ?? ''"
                          @input="handleSubscriptionStartsAtChange($event, member.id, bot.id)"
                        />
                      </td>
                      <td>
                        <input
                          type="datetime-local"
                          :value="subscriptionDrafts[subscriptionDraftKey(member.id, bot.id)]?.expiresAt ?? ''"
                          @input="handleSubscriptionExpiresAtChange($event, member.id, bot.id)"
                        />
                      </td>
                      <td>
                        <div class="admin-subscription-table__actions">
                          <button
                            class="secondary"
                            :disabled="savingSubscriptionKey === subscriptionDraftKey(member.id, bot.id)"
                            @click="activateMonthlySubscription(member.id, bot.id)"
                          >
                            Добавить еще месяц
                          </button>
                          <button
                            :disabled="savingSubscriptionKey === subscriptionDraftKey(member.id, bot.id)"
                            @click="saveSubscription(member.id, bot.id)"
                          >
                            {{
                              savingSubscriptionKey === subscriptionDraftKey(member.id, bot.id)
                                ? "Сохранение..."
                                : "Сохранить"
                            }}
                          </button>
                        </div>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </details>
          </div>
        </article>
      </div>
    </div>
  </section>
</template>
