import { useCallback, useEffect, useRef, useState } from 'react';
import { apiFetch } from '../lib/api';

export type BlockedByDayEntry = {
  date: string;
  count: number;
};

export type BlockedByConnectionEntry = {
  connectionId: string;
  title: string | null;
  email: string;
  providerLabel: string;
  count: number;
};

type MailStatsState = {
  blockedByDay: BlockedByDayEntry[];
  blockedByConnection: BlockedByConnectionEntry[];
  loading: boolean;
};

type ConnectionAgeGranularity = 'too-new' | 'day' | 'week' | 'month';

function resolveGranularity(createdAt: string | null | undefined): ConnectionAgeGranularity {
  if (!createdAt) return 'day';
  const ageMs = Date.now() - new Date(createdAt).getTime();
  const ageH = ageMs / 3_600_000;
  if (ageH < 24) return 'too-new';
  const ageD = ageH / 24;
  if (ageD <= 14) return 'day';
  if (ageD <= 90) return 'week';
  return 'month';
}

type ConnectionStatsState = {
  data: BlockedByDayEntry[];
  granularity: ConnectionAgeGranularity;
  loading: boolean;
};

export function useMailConnectionStats(
  connectionId: string,
  createdAt: string | null | undefined,
  enabled: boolean,
) {
  const fetchedRef = useRef(false);
  const [state, setState] = useState<ConnectionStatsState>({
    data: [],
    granularity: resolveGranularity(createdAt),
    loading: false,
  });

  const granularity = resolveGranularity(createdAt);

  const fetch = useCallback(async () => {
    if (!enabled || !connectionId) return;
    setState((s) => ({ ...s, loading: true }));
    try {
      const ageDays = createdAt
        ? Math.max(1, Math.ceil((Date.now() - new Date(createdAt).getTime()) / 86_400_000))
        : 30;
      const days = Math.min(30, ageDays);

      const raw = await apiFetch<BlockedByDayEntry[]>(
        `/api/mail/stats/blocked-by-day?days=${days}&connectionId=${connectionId}`,
      );

      const nonEmpty = raw.filter((e) => e.count > 0);
      let data: BlockedByDayEntry[];

      if (granularity === 'week') {
        data = aggregateToWeeks(raw);
      } else if (granularity === 'month') {
        data = aggregateToMonths(raw);
      } else if (nonEmpty.length > 0) {
        // IMMER auf die echte Hit-Range zoomen — von erstem nonEmpty bis
        // letztem nonEmpty. Gaps dazwischen bleiben sichtbar (für realistische
        // Verteilung), aber 29 leere Slots am Anfang + 1 Bar am Ende wird
        // auf z.B. 1-3 Bars geschrumpft. Trim eliminiert das visuelle Rauschen.
        const firstDate = nonEmpty[0].date;
        const lastDate = nonEmpty[nonEmpty.length - 1].date;
        data = raw.filter((e) => e.date >= firstDate && e.date <= lastDate);
      } else {
        data = raw;
      }

      setState({ data, granularity, loading: false });
    } catch {
      setState((s) => ({ ...s, loading: false }));
    }
  }, [enabled, connectionId, granularity, createdAt]);

  useEffect(() => {
    if (!enabled) return;
    if (fetchedRef.current) return;
    fetchedRef.current = true;
    fetch();
  }, [enabled, fetch]);

  return { ...state, refresh: fetch };
}

function aggregateToWeeks(entries: BlockedByDayEntry[]): BlockedByDayEntry[] {
  const buckets: Map<string, number> = new Map();
  for (const e of entries) {
    const d = new Date(e.date + 'T00:00:00');
    const day = d.getDay();
    const diff = d.getDate() - day + (day === 0 ? -6 : 1);
    const monday = new Date(d);
    monday.setDate(diff);
    const key = monday.toISOString().slice(0, 10);
    buckets.set(key, (buckets.get(key) ?? 0) + e.count);
  }
  return [...buckets.entries()]
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([date, count]) => ({ date, count }));
}

function aggregateToMonths(entries: BlockedByDayEntry[]): BlockedByDayEntry[] {
  const buckets: Map<string, number> = new Map();
  for (const e of entries) {
    const key = e.date.slice(0, 7);
    buckets.set(key, (buckets.get(key) ?? 0) + e.count);
  }
  return [...buckets.entries()]
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([date, count]) => ({ date, count }));
}

export function useMailStats(enabled: boolean) {
  const [state, setState] = useState<MailStatsState>({
    blockedByDay: [],
    blockedByConnection: [],
    loading: false,
  });

  const fetch = useCallback(async () => {
    if (!enabled) return;
    setState((s) => ({ ...s, loading: true }));
    try {
      const [byDay, byConn] = await Promise.all([
        apiFetch<BlockedByDayEntry[]>('/api/mail/stats/blocked-by-day?days=30'),
        apiFetch<BlockedByConnectionEntry[]>('/api/mail/stats/blocked-by-connection'),
      ]);
      setState({ blockedByDay: byDay, blockedByConnection: byConn, loading: false });
    } catch {
      setState((s) => ({ ...s, loading: false }));
    }
  }, [enabled]);

  useEffect(() => {
    fetch();
  }, [fetch]);

  return { ...state, refresh: fetch };
}
