<template>
  <div class="flex flex-col gap-5 pt-4">
    <!-- Error state -->
    <div v-if="error" class="p-8 flex flex-col gap-4">
      <p class="gw-text">Erreur : {{ error }}</p>
    </div>

    <template v-else>
      <!-- Currency selector -->
      <div class="flex items-center justify-center gap-2">
        <span class="gw-text text-xs">DU</span>
        <label class="gw-toggle">
          <input
            type="checkbox"
            :checked="unit === 'G1'"
            @change="unit = ($event.target as HTMLInputElement).checked ? 'G1' : 'DU'"
          />
          <span class="gw-toggle-slider" />
        </label>
        <span class="gw-text text-xs">&#x11E;1</span>
      </div>

      <!-- Monetary data card -->
      <div ref="topRef" class="card-surface">
        <div class="flex flex-col items-center gap-3">
          <p class="gw-metric">Masse mon&eacute;taire / Membres</p>

          <span v-if="polygon" class="gw-chip">
            {{ activePerimeterName ?? 'S\u00e9lection manuelle' }}
          </span>

          <!-- Loading -->
          <div v-if="loading" class="flex flex-col items-center gap-2 py-4">
            <div class="gw-spinner" />
            <p class="gw-text text-sm">Connexion au r&eacute;seau...</p>
          </div>

          <!-- Data grid -->
          <div v-else-if="monetary" class="grid grid-cols-2 gap-2 w-full max-w-sm">
            <div :class="['text-center p-2 rounded-md text-xs', polygon ? 'bg-accent/10' : 'bg-surface-200']">
              <p class="gw-text">M (masse{{ polygon ? ' locale' : '' }})</p>
              <p class="gw-title mt-1">
                {{ mnIsLoading ? '...' : formatValue(displayM!, unit, duDaily) }}
              </p>
            </div>
            <div :class="['text-center p-2 rounded-md text-xs', polygon ? 'bg-accent/10' : 'bg-surface-200']">
              <p class="gw-text">N (membres{{ polygon ? ' locaux' : '' }})</p>
              <p class="gw-title mt-1">{{ displayN.toLocaleString('fr-FR') }}</p>
            </div>
            <div :class="['text-center p-2 rounded-md text-xs', polygon ? 'bg-accent/10' : 'bg-surface-200']">
              <p class="gw-text">M / N{{ polygon ? ' (local)' : '' }}</p>
              <p class="gw-title mt-1">
                {{ mnIsLoading ? '...' : formatValue(displayMN!, unit, duDaily) }}
              </p>
            </div>
            <div class="text-center p-2 rounded-md text-xs bg-surface-200">
              <p class="gw-text">DU journalier</p>
              <p class="gw-title mt-1">{{ fr(duDaily) }} &#x11E;1</p>
            </div>

            <!-- Extra cells when polygon is active -->
            <template v-if="polygon && nLocal > 0 && monetary">
              <div class="text-center p-2 rounded-md text-xs bg-surface-200">
                <p class="gw-text">M / N (r&eacute;seau)</p>
                <p class="gw-title mt-1">{{ formatValue(mnG1, unit, duDaily) }}</p>
              </div>
              <div class="text-center p-2 rounded-md text-xs bg-accent/10">
                <p class="gw-text">Part du r&eacute;seau</p>
                <p class="gw-title mt-1">{{ fr(nLocal / monetary.membersCount * 100) }} %</p>
              </div>
            </template>

            <div class="col-span-2 text-center">
              <p class="gw-text">
                Bloc #{{ monetary.blockNumber }} &mdash;
                {{ new Date(monetary.timestamp).toLocaleDateString('fr-FR', { dateStyle: 'long' }) }}
              </p>
            </div>
          </div>

          <!-- Clear selection button -->
          <div v-if="polygon" class="flex flex-col items-center gap-2">
            <button
              class="gw-btn gw-btn-danger"
              @click="handleClearSelection"
            >
              P&eacute;rim&egrave;tre monde
            </button>
          </div>

          <!-- Saved perimeters -->
          <GratewizardGwPerimeterList
            :perimeters="perimeters"
            @load="handleLoadPerimeter"
            @delete="deletePerimeter"
          />
        </div>
      </div>

      <!-- Map card -->
      <div class="card-surface">
        <div class="flex flex-col items-center gap-3">
          <p class="gw-metric">
            Carte des membres g&eacute;olocalis&eacute;s
            <span v-if="!geoLoading && v1Pubkeys" class="gw-chip ml-2">
              {{ geoMembers.length.toLocaleString('fr-FR') }}
            </span>
          </p>

          <p v-if="geoError" class="gw-text">Erreur Cesium+ : {{ geoError }}</p>

          <!-- Loading map -->
          <div v-if="geoLoading || !v1Pubkeys" class="flex flex-col items-center gap-2 py-4">
            <div class="gw-spinner" />
            <p class="gw-text text-sm">Chargement des profils g&eacute;olocalis&eacute;s...</p>
          </div>

          <!-- Map -->
          <template v-else>
            <GratewizardGwMap
              :members="geoMembers"
              :clear-trigger="clearTrigger"
              :load-polygon="loadPolygonTrigger"
              @polygon-change="handlePolygonChange"
            />

            <p v-if="!loading && monetary" class="gw-text">
              {{ geoMembers.length.toLocaleString('fr-FR') }} membres certifi&eacute;s g&eacute;olocalis&eacute;s sur
              {{ monetary.membersCount.toLocaleString('fr-FR') }} membres au total
            </p>

            <!-- Save perimeter form -->
            <div v-if="polygon" class="flex gap-2 items-center">
              <input
                v-model="perimeterName"
                type="text"
                placeholder="Nom du p&eacute;rim&egrave;tre"
                class="gw-input"
                @keydown.enter="handleSavePerimeter"
              />
              <button
                class="gw-btn gw-btn-accent"
                :disabled="!perimeterName.trim()"
                @click="handleSavePerimeter"
              >
                Sauvegarder
              </button>
            </div>
          </template>
        </div>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { duniter, type MonetaryData } from '~/services/duniter';
import { pointInPolygon, fr, formatValue, countUdSince, type CurrencyUnit } from '~/utils/gratewizard';
import type { GeoMember } from '~/composables/useCesiumProfiles';
import type { SavedPerimeter } from '~/composables/useSavedPerimeters';

const unit = useLocalStorage<CurrencyUnit>('gw-currency-unit', 'DU');

const monetary = ref<MonetaryData | null>(null);
const v1Pubkeys = ref<string[] | null>(null);
const loading = ref(true);
const error = ref<string | null>(null);
const polygon = ref<[number, number][] | null>(null);
const clearTrigger = ref(0);
const loadPolygonTrigger = ref<{ coords: [number, number][]; name: string } | null>(null);
const perimeterName = ref('');
const activePerimeterName = ref<string | null>(null);
const localMNg1 = ref<number | null>(null);
const mnLoading = ref(false);
const topRef = ref<HTMLDivElement | null>(null);

const { geoMembers, loading: geoLoading, error: geoError } = useCesiumProfiles(v1Pubkeys);
const { perimeters, savePerimeter, deletePerimeter } = useSavedPerimeters();

// Fetch monetary data on mount
onMounted(async () => {
  try {
    const [mon, pubkeys] = await Promise.all([
      duniter.fetchMonetary(),
      duniter.fetchMemberPubkeys(),
    ]);
    monetary.value = mon;
    v1Pubkeys.value = pubkeys;
  } catch (e: any) {
    error.value = e.message;
  } finally {
    loading.value = false;
  }
});

const duDaily = computed(() => monetary.value ? Number(monetary.value.amount) / 100 : 1);
const massG1 = computed(() => monetary.value ? Number(monetary.value.monetaryMass) / 100 : 0);
const mnG1 = computed(() => monetary.value && monetary.value.membersCount ? massG1.value / monetary.value.membersCount : 0);

const localMembers = computed(() => {
  if (!polygon.value) return [];
  return geoMembers.value.filter((m) => pointInPolygon(m.lat, m.lon, polygon.value!));
});

const nLocal = computed(() => localMembers.value.length);

// Compute local M/N based on member seniority
watch([polygon, localMembers, monetary], async ([poly, members, mon]) => {
  if (!poly || members.length === 0 || !mon) {
    localMNg1.value = null;
    return;
  }

  mnLoading.value = true;

  try {
    const pubkeys = members.map((m) => m.pubkey);
    const joinBlocks = await duniter.fetchMemberJoinBlocks(pubkeys);

    const udBlocks = mon.udBlockNumbers;
    let totalSeniority = 0;
    let validCount = 0;

    for (const pk of pubkeys) {
      const joinBlock = joinBlocks.get(pk);
      if (joinBlock === undefined) continue;
      totalSeniority += countUdSince(udBlocks, joinBlock);
      validCount++;
    }

    if (validCount > 0) {
      const localAvgSeniority = totalSeniority / validCount;
      const globalAvgSeniority =
        Number(mon.monetaryMass) / (Number(mon.amount) * mon.membersCount);
      localMNg1.value = mnG1.value * (localAvgSeniority / globalAvgSeniority);
    }
  } catch (e) {
    console.error('Failed to compute local M/N:', e);
  } finally {
    mnLoading.value = false;
  }
});

const displayN = computed(() => polygon.value ? nLocal.value : monetary.value?.membersCount ?? 0);
const displayMN = computed(() => polygon.value ? localMNg1.value : mnG1.value);
const displayM = computed(() => polygon.value ? (localMNg1.value !== null ? localMNg1.value * nLocal.value : null) : massG1.value);
const mnIsLoading = computed(() => polygon.value && (mnLoading.value || localMNg1.value === null));

function handlePolygonChange(poly: [number, number][] | null, name?: string) {
  polygon.value = poly;
  activePerimeterName.value = name ?? null;
  if (poly) nextTick(() => topRef.value?.scrollIntoView({ behavior: 'smooth' }));
}

function handleClearSelection() {
  polygon.value = null;
  activePerimeterName.value = null;
  localMNg1.value = null;
  clearTrigger.value++;
  loadPolygonTrigger.value = null;
}

function handleSavePerimeter() {
  if (!polygon.value || !perimeterName.value.trim()) return;
  savePerimeter(perimeterName.value.trim(), polygon.value);
  perimeterName.value = '';
}

function handleLoadPerimeter(p: SavedPerimeter) {
  loadPolygonTrigger.value = { coords: p.polygon, name: p.name };
}
</script>
