import { env } from "@/lib/env";
import { getLocalDb } from "@/lib/local-db";
import { computeRates } from "@/lib/metrics";
import { createClient } from "@/lib/supabase/server";
import { getPublicThumbnailUrl } from "@/lib/storage";
import type { KPISet, ViewerContext } from "@/lib/types";

type ImportRow = {
  id: number;
  file_name: string;
  status: string;
  total_rows: number;
  inserted_rows: number;
  updated_rows: number;
  failed_rows: number;
  created_at: string;
};

type EventRow = {
  sent_email_name: string;
  primary_country_code: string;
  approved_document_name: string;
  friendly_title: string | null;
  brand: string | null;
  thumbnail_path: string | null;
  campaign_group: string | null;
  last_open: string | null;
  opened: number | string;
  total_opens: number | string;
  last_click: string | null;
  clicked: number | string;
  total_clicks: number | string;
  thumbs_up: number | string;
  thumbs_down: number | string;
  sent_date: string | null;
  created_at: string | null;
};

type MetricLikeRow = {
  total_emails_sent: number;
  total_opened: number;
  total_opens: number;
  total_clicked: number;
  total_clicks: number;
};

export type DashboardFilters = {
  from: string;
  to: string;
  country: string;
  brand: string;
};

function normalizeCountryScope(scopeCountries?: string[]) {
  return [...new Set((scopeCountries ?? []).map((code) => code.trim().toUpperCase()).filter(Boolean))];
}

function toNumber(value: number | string | null | undefined) {
  return Number(value ?? 0);
}

function sortByMonth(a: string, b: string) {
  return new Date(a).getTime() - new Date(b).getTime();
}

function normalizeDateParam(value?: string | null) {
  if (!value) return "";
  const trimmed = value.trim();
  if (!/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) return "";
  return trimmed;
}

function toDateOnly(value: string | null | undefined) {
  if (!value) return "";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "";
  return date.toISOString().slice(0, 10);
}

function toMonthStart(value: string | null | undefined) {
  const dateOnly = toDateOnly(value);
  if (!dateOnly) return "";
  return `${dateOnly.slice(0, 7)}-01`;
}

function aggregateKpis(rows: MetricLikeRow[]): KPISet {
  const base = rows.reduce<MetricLikeRow>(
    (acc, row) => {
      acc.total_emails_sent += toNumber(row.total_emails_sent);
      acc.total_opened += toNumber(row.total_opened);
      acc.total_opens += toNumber(row.total_opens);
      acc.total_clicked += toNumber(row.total_clicked);
      acc.total_clicks += toNumber(row.total_clicks);
      return acc;
    },
    {
      total_emails_sent: 0,
      total_opened: 0,
      total_opens: 0,
      total_clicked: 0,
      total_clicks: 0,
    },
  );

  return computeRates(base);
}

function buildDashboardFromEvents({
  events,
  imports,
  minSent,
  filters,
  countryOptions,
}: {
  events: EventRow[];
  imports: ImportRow[];
  minSent: number;
  filters?: Partial<DashboardFilters>;
  countryOptions?: string[];
}) {
  const availableCountriesFromEvents = [...new Set(events.map((row) => (row.primary_country_code || "").toUpperCase()))]
    .filter(Boolean)
    .sort((a, b) => a.localeCompare(b));
  const configuredCountries = normalizeCountryScope(countryOptions).sort((a, b) => a.localeCompare(b));
  const availableCountries =
    configuredCountries.length > 0 ? configuredCountries : availableCountriesFromEvents;

  const availableBrands = [
    ...new Set(
      events.map((row) => (row.brand || "Unspecified").trim() || "Unspecified"),
    ),
  ].sort((a, b) => a.localeCompare(b));

  const allEventDates = events
    .map((row) => toDateOnly(row.sent_date || row.created_at))
    .filter((item): item is string => Boolean(item))
    .sort((a, b) => a.localeCompare(b));

  const minDate = allEventDates[0] ?? "";
  const maxDate = allEventDates[allEventDates.length - 1] ?? "";

  const requestedFrom = normalizeDateParam(filters?.from);
  const requestedTo = normalizeDateParam(filters?.to);
  const selectedCountry = (filters?.country || "").toUpperCase();
  const selectedBrand = (filters?.brand || "").trim();

  const from = requestedFrom || minDate;
  const to = requestedTo || maxDate;

  const activeCountry = availableCountries.includes(selectedCountry) ? selectedCountry : "";
  const activeBrand = availableBrands.includes(selectedBrand) ? selectedBrand : "";

  const filteredEvents = events.filter((row) => {
    const country = (row.primary_country_code || "").toUpperCase();
    if (activeCountry && country !== activeCountry) return false;

    const brand = (row.brand || "Unspecified").trim() || "Unspecified";
    if (activeBrand && brand !== activeBrand) return false;

    if (!from && !to) return true;

    const dateOnly = toDateOnly(row.sent_date || row.created_at);
    if (!dateOnly) return false;
    if (from && dateOnly < from) return false;
    if (to && dateOnly > to) return false;
    return true;
  });

  const kpis = aggregateKpis([
    {
      total_emails_sent: filteredEvents.length,
      total_opened: filteredEvents.reduce((sum, item) => sum + toNumber(item.opened), 0),
      total_opens: filteredEvents.reduce((sum, item) => sum + toNumber(item.total_opens), 0),
      total_clicked: filteredEvents.reduce((sum, item) => sum + toNumber(item.clicked), 0),
      total_clicks: filteredEvents.reduce((sum, item) => sum + toNumber(item.total_clicks), 0),
    },
  ]);

  const monthlyBuckets = new Map<
    string,
    {
      month_start: string;
      total_emails_sent: number;
      total_opened: number;
      total_clicked: number;
      total_thumbs_up: number;
      total_thumbs_down: number;
    }
  >();

  const documentBuckets = new Map<
    string,
    {
      approved_document_name: string;
      friendly_title: string;
      brand: string;
      thumbnail_path: string | null;
      campaign_group: string | null;
      total_emails_sent: number;
      total_opened: number;
      total_opens: number;
      total_clicked: number;
      total_clicks: number;
      total_thumbs_up: number;
      total_thumbs_down: number;
      latest_sent_at: string | null;
      countries: Set<string>;
    }
  >();

  const countryMonthBuckets = new Map<
    string,
    {
      month_start: string;
      country_code: string;
      total_emails_sent: number;
      total_opened: number;
      total_clicked: number;
    }
  >();

  const brandMonthBuckets = new Map<
    string,
    {
      month_start: string;
      brand: string;
      total_emails_sent: number;
      total_opened: number;
      total_clicked: number;
    }
  >();

  for (const event of filteredEvents) {
    const eventDate = event.sent_date || event.created_at;
    const monthStart = toMonthStart(eventDate);
    const countryCode = (event.primary_country_code || "").toUpperCase();
    const friendlyTitle = event.friendly_title || event.approved_document_name;
    const brand = (event.brand || "Unspecified").trim() || "Unspecified";

    if (monthStart) {
      const monthBucket = monthlyBuckets.get(monthStart) ?? {
        month_start: monthStart,
        total_emails_sent: 0,
        total_opened: 0,
        total_clicked: 0,
        total_thumbs_up: 0,
        total_thumbs_down: 0,
      };
      monthBucket.total_emails_sent += 1;
      monthBucket.total_opened += toNumber(event.opened);
      monthBucket.total_clicked += toNumber(event.clicked);
      monthBucket.total_thumbs_up += toNumber(event.thumbs_up);
      monthBucket.total_thumbs_down += toNumber(event.thumbs_down);
      monthlyBuckets.set(monthStart, monthBucket);

      if (countryCode) {
        const countryMonthKey = `${monthStart}::${countryCode}`;
        const countryMonthBucket = countryMonthBuckets.get(countryMonthKey) ?? {
          month_start: monthStart,
          country_code: countryCode,
          total_emails_sent: 0,
          total_opened: 0,
          total_clicked: 0,
        };
        countryMonthBucket.total_emails_sent += 1;
        countryMonthBucket.total_opened += toNumber(event.opened);
        countryMonthBucket.total_clicked += toNumber(event.clicked);
        countryMonthBuckets.set(countryMonthKey, countryMonthBucket);
      }

      const brandMonthKey = `${monthStart}::${brand}`;
      const brandMonthBucket = brandMonthBuckets.get(brandMonthKey) ?? {
        month_start: monthStart,
        brand,
        total_emails_sent: 0,
        total_opened: 0,
        total_clicked: 0,
      };
      brandMonthBucket.total_emails_sent += 1;
      brandMonthBucket.total_opened += toNumber(event.opened);
      brandMonthBucket.total_clicked += toNumber(event.clicked);
      brandMonthBuckets.set(brandMonthKey, brandMonthBucket);
    }

    const documentBucket = documentBuckets.get(event.approved_document_name) ?? {
      approved_document_name: event.approved_document_name,
      friendly_title: friendlyTitle,
      brand,
      thumbnail_path: event.thumbnail_path ?? null,
      campaign_group: event.campaign_group ?? null,
      total_emails_sent: 0,
      total_opened: 0,
      total_opens: 0,
      total_clicked: 0,
      total_clicks: 0,
      total_thumbs_up: 0,
      total_thumbs_down: 0,
      latest_sent_at: null,
      countries: new Set<string>(),
    };

    documentBucket.total_emails_sent += 1;
    documentBucket.total_opened += toNumber(event.opened);
    documentBucket.total_opens += toNumber(event.total_opens);
    documentBucket.total_clicked += toNumber(event.clicked);
    documentBucket.total_clicks += toNumber(event.total_clicks);
    documentBucket.total_thumbs_up += toNumber(event.thumbs_up);
    documentBucket.total_thumbs_down += toNumber(event.thumbs_down);
    if (!documentBucket.thumbnail_path && event.thumbnail_path) {
      documentBucket.thumbnail_path = event.thumbnail_path;
    }
    if (!documentBucket.campaign_group && event.campaign_group) {
      documentBucket.campaign_group = event.campaign_group;
    }
    if (documentBucket.friendly_title === documentBucket.approved_document_name && event.friendly_title) {
      documentBucket.friendly_title = event.friendly_title;
    }
    if ((!documentBucket.brand || documentBucket.brand === "Unspecified") && event.brand) {
      documentBucket.brand = event.brand;
    }
    if (countryCode) {
      documentBucket.countries.add(countryCode);
    }

    if (eventDate) {
      if (!documentBucket.latest_sent_at || new Date(eventDate) > new Date(documentBucket.latest_sent_at)) {
        documentBucket.latest_sent_at = eventDate;
      }
    }

    documentBuckets.set(event.approved_document_name, documentBucket);
  }

  const monthlySeries = [...monthlyBuckets.values()]
    .sort((a, b) => sortByMonth(a.month_start, b.month_start))
    .map((row) => ({
      month_start: row.month_start,
      total_emails_sent: row.total_emails_sent,
      total_thumbs_up: row.total_thumbs_up,
      total_thumbs_down: row.total_thumbs_down,
      open_rate: row.total_emails_sent > 0 ? row.total_opened / row.total_emails_sent : 0,
      ctr: row.total_emails_sent > 0 ? row.total_clicked / row.total_emails_sent : 0,
    }));

  const documentRows = [...documentBuckets.values()].map((row) => {
    const open_rate = row.total_emails_sent > 0 ? row.total_opened / row.total_emails_sent : 0;
    const ctr = row.total_emails_sent > 0 ? row.total_clicked / row.total_emails_sent : 0;
    const ctor = row.total_opened > 0 ? row.total_clicked / row.total_opened : 0;

    return {
      approved_document_name: row.approved_document_name,
      friendly_title: row.friendly_title,
      brand: row.brand,
      thumbnail_path: row.thumbnail_path,
      campaign_group: row.campaign_group,
      total_emails_sent: row.total_emails_sent,
      total_opened: row.total_opened,
      total_opens: row.total_opens,
      total_clicked: row.total_clicked,
      total_clicks: row.total_clicks,
      total_thumbs_up: row.total_thumbs_up,
      total_thumbs_down: row.total_thumbs_down,
      open_rate,
      ctr,
      ctor,
      latest_sent_at: row.latest_sent_at,
      country_scope: [...row.countries].sort((a, b) => a.localeCompare(b)).join(", "),
    };
  });

  const rankedPool = documentRows.filter((row) => row.total_emails_sent >= minSent);

  const topDocuments = [...rankedPool]
    .sort((a, b) => {
      const ctrDiff = b.ctr - a.ctr;
      if (ctrDiff !== 0) return ctrDiff;
      return b.open_rate - a.open_rate;
    })
    .slice(0, 8);

  const worstDocuments = [...rankedPool]
    .sort((a, b) => {
      const ctrDiff = a.ctr - b.ctr;
      if (ctrDiff !== 0) return ctrDiff;
      return a.open_rate - b.open_rate;
    })
    .slice(0, 8);

  const brandBreakdown = [...new Map(documentRows.map((row) => [row.brand, 0])).keys()]
    .map((brand) => ({
      brand,
      sent: documentRows
        .filter((row) => row.brand === brand)
        .reduce((sum, row) => sum + row.total_emails_sent, 0),
    }))
    .sort((a, b) => b.sent - a.sent)
    .slice(0, 10);

  const documentTable = [...documentRows]
    .sort((a, b) => b.total_emails_sent - a.total_emails_sent)
    .map((row) => ({
      ...row,
      thumbnail_url: getPublicThumbnailUrl(row.thumbnail_path),
    }));

  const countryMonthBreakdown = [...countryMonthBuckets.values()]
    .sort((a, b) => {
      const monthCompare = sortByMonth(a.month_start, b.month_start);
      if (monthCompare !== 0) return monthCompare;
      return a.country_code.localeCompare(b.country_code);
    })
    .map((row) => ({
      ...row,
      open_rate: row.total_emails_sent > 0 ? row.total_opened / row.total_emails_sent : 0,
      ctr: row.total_emails_sent > 0 ? row.total_clicked / row.total_emails_sent : 0,
    }));

  const brandMonthBreakdown = [...brandMonthBuckets.values()]
    .sort((a, b) => {
      const monthCompare = sortByMonth(a.month_start, b.month_start);
      if (monthCompare !== 0) return monthCompare;
      return a.brand.localeCompare(b.brand);
    })
    .map((row) => ({
      ...row,
      open_rate: row.total_emails_sent > 0 ? row.total_opened / row.total_emails_sent : 0,
      ctr: row.total_emails_sent > 0 ? row.total_clicked / row.total_emails_sent : 0,
    }));

  return {
    kpis,
    monthlySeries,
    topDocuments,
    worstDocuments,
    brandBreakdown,
    documentTable,
    recentImports: imports,
    countryMonthBreakdown,
    brandMonthBreakdown,
    availableCountries,
    availableBrands,
    selectedFilters: {
      from,
      to,
      country: activeCountry,
      brand: activeBrand,
    },
    minAvailableDate: minDate,
    maxAvailableDate: maxDate,
    filteredEventsCount: filteredEvents.length,
    rankingMinSent: minSent,
  };
}

function emptyDashboard(minSent: number) {
  return {
    kpis: computeRates({
      total_emails_sent: 0,
      total_opened: 0,
      total_opens: 0,
      total_clicked: 0,
      total_clicks: 0,
    }),
    monthlySeries: [],
    topDocuments: [],
    worstDocuments: [],
    brandBreakdown: [],
    documentTable: [],
    recentImports: [],
    countryMonthBreakdown: [],
    brandMonthBreakdown: [],
    availableCountries: [],
    availableBrands: [],
    selectedFilters: {
      from: "",
      to: "",
      country: "",
      brand: "",
    },
    minAvailableDate: "",
    maxAvailableDate: "",
    filteredEventsCount: 0,
    rankingMinSent: minSent,
  };
}

export async function fetchDashboardData(
  viewer: ViewerContext,
  filters?: Partial<DashboardFilters>,
  scopeCountries?: string[],
  countryOptions?: string[],
) {
  const minSent = Math.max(env.topRankingMinSent, 1);
  const normalizedScope = normalizeCountryScope(scopeCountries);
  const scopeSet = normalizedScope.length > 0 ? new Set(normalizedScope) : null;

  if (!env.hasSupabasePublicEnv) {
    const db = await getLocalDb();
    const allowedCountries =
      viewer.role === "admin"
        ? null
        : new Set(viewer.allowedCountries.map((country) => country.toUpperCase()));

    const metadataByDocument = new Map(db.email_metadata.map((item) => [item.approved_document_name, item]));
    const overridesByEvent = new Map(
      db.email_event_metadata_overrides.map((item) => [item.sent_email_name, item]),
    );
    const sentimentByEvent = new Map(
      db.email_sentiment.map((item) => [item.sent_email_name, item]),
    );

    const events: EventRow[] = db.raw_email_events
      .filter((event) => {
        const countryCode = (event.primary_country_code ?? "").toUpperCase();
        if (scopeSet && !scopeSet.has(countryCode)) return false;
        if (allowedCountries && !allowedCountries.has(countryCode)) return false;
        return true;
      })
      .map((event) => {
        const metadata = metadataByDocument.get(event.approved_document_name);
        const override = overridesByEvent.get(event.sent_email_name);
        const sentiment = sentimentByEvent.get(event.sent_email_name);

        return {
          sent_email_name: event.sent_email_name,
          primary_country_code: event.primary_country_code,
          approved_document_name: event.approved_document_name,
          friendly_title: override?.friendly_title ?? metadata?.friendly_title ?? event.approved_document_name,
          brand: override?.brand ?? metadata?.brand ?? "Unspecified",
          thumbnail_path: override?.thumbnail_path ?? metadata?.thumbnail_path ?? null,
          campaign_group: override?.campaign_group ?? metadata?.campaign_group ?? null,
          last_open: event.last_open,
          opened: event.opened,
          total_opens: event.total_opens,
          last_click: event.last_click,
          clicked: event.clicked,
          total_clicks: event.total_clicks,
          thumbs_up: sentiment?.thumbs_up ?? 0,
          thumbs_down: sentiment?.thumbs_down ?? 0,
          sent_date: event.sent_date,
          created_at: event.created_at,
        };
      });

    const imports: ImportRow[] = [...db.imports]
      .filter((item) => (viewer.role === "admin" ? true : item.uploaded_by === viewer.userId))
      .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
      .slice(0, 8)
      .map((item) => ({
        id: item.id,
        file_name: item.file_name,
        status: item.status,
        total_rows: item.total_rows,
        inserted_rows: item.inserted_rows,
        updated_rows: item.updated_rows,
        failed_rows: item.failed_rows,
        created_at: item.created_at,
      }));

    return {
      ...buildDashboardFromEvents({ events, imports, minSent, filters, countryOptions }),
      setupRequired: false,
      localMode: true,
    };
  }

  const supabase = await createClient();
  const isAffiliate = viewer.role !== "admin";

  if (isAffiliate && viewer.allowedCountries.length === 0) {
    return {
      ...emptyDashboard(minSent),
      setupRequired: false,
      localMode: false,
    };
  }

  let eventQuery = supabase
    .from("email_events_enriched")
    .select(
      "sent_email_name, primary_country_code, approved_document_name, friendly_title, brand, thumbnail_path, campaign_group, last_open, opened, total_opens, last_click, clicked, total_clicks, sent_date, created_at",
    );

  if (isAffiliate) {
    eventQuery = eventQuery.in("primary_country_code", viewer.allowedCountries);
  }
  if (normalizedScope.length > 0) {
    eventQuery = eventQuery.in("primary_country_code", normalizedScope);
  }

  const importsQuery = supabase
    .from("imports")
    .select("id, file_name, status, total_rows, inserted_rows, updated_rows, failed_rows, created_at")
    .order("created_at", { ascending: false })
    .limit(8);

  const scopedImportsQuery = isAffiliate ? importsQuery.eq("uploaded_by", viewer.userId) : importsQuery;

  const [eventsRes, importsRes] = await Promise.all([
    eventQuery,
    scopedImportsQuery,
  ]);

  if (eventsRes.error) throw new Error(eventsRes.error.message);
  if (importsRes.error) throw new Error(importsRes.error.message);

  const events = ((eventsRes.data ?? []) as EventRow[]).map((row) => ({
    ...row,
    thumbs_up: 0,
    thumbs_down: 0,
  }));
  const imports = (importsRes.data ?? []) as ImportRow[];

  return {
    ...buildDashboardFromEvents({ events, imports, minSent, filters, countryOptions }),
    setupRequired: false,
    localMode: false,
  };
}
