import Link from "next/link";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { getViewerContext } from "@/lib/auth";
import { ROLES, ROUTES } from "@/lib/constants";
import { env } from "@/lib/env";
import { getLocalDb } from "@/lib/local-db";
import { createClient } from "@/lib/supabase/server";
import { getPublicSourceAssetUrl, getPublicThumbnailUrl, isPdfMetaAsset } from "@/lib/storage";
import { formatInteger } from "@/lib/utils";
import { saveMetadataAction } from "@/app/(app)/admin/metadata/actions";
import { FormSubmitButton } from "@/components/ui/form-submit-button";

const PAGE_SIZE = 30;

type GroupedMetadataRow = {
  group_key: string;
  email_name: string;
  approved_document_names: string[];
  latest_sent_email_name: string | null;
  countries: string[];
  last_sent_at: string | null;
  total_events: number;
  total_opened: number;
  total_clicked: number;
  brand: string;
  notes: string | null;
  thumbnail_path: string | null;
  campaign_group: string | null;
};

type MetadataFilters = {
  q: string;
  country: string;
  brand: string;
  page: number;
  group: string;
};

function normalizeFilters(input: {
  q?: string;
  country?: string;
  brand?: string;
  page?: string;
  group?: string;
}): MetadataFilters {
  return {
    q: (input.q ?? "").trim(),
    country: (input.country ?? "").trim().toUpperCase(),
    brand: (input.brand ?? "").trim(),
    page: Math.max(1, Number(input.page ?? "1") || 1),
    group: (input.group ?? "").trim(),
  };
}

function buildMetadataHref(filters: Partial<MetadataFilters>) {
  const params = new URLSearchParams();
  if (filters.q) params.set("q", filters.q);
  if (filters.country) params.set("country", filters.country);
  if (filters.brand) params.set("brand", filters.brand);
  if (filters.page && filters.page > 1) params.set("page", String(filters.page));
  if (filters.group) params.set("group", filters.group);
  const query = params.toString();
  return query ? `${ROUTES.metadata}?${query}` : ROUTES.metadata;
}

function normalizeEmailName(value: string) {
  return value
    .trim()
    .replace(/\s+/g, " ")
    .replace(/\s*-\s*/g, " - ")
    .toLowerCase();
}

function parseDate(value: string | null) {
  if (!value) return 0;
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return 0;
  return date.getTime();
}

function formatSentDate(value: string | null) {
  if (!value) return "No sent date";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "No sent date";
  return date.toLocaleString("en-GB");
}

function matchesSearch(row: GroupedMetadataRow, q: string) {
  if (!q) return true;
  const term = q.toLowerCase();
  return (
    row.email_name.toLowerCase().includes(term) ||
    row.brand.toLowerCase().includes(term) ||
    row.countries.join(",").toLowerCase().includes(term) ||
    row.approved_document_names.join(" ").toLowerCase().includes(term) ||
    (row.latest_sent_email_name ?? "").toLowerCase().includes(term)
  );
}

function groupByEmailName(
  rows: Array<{
    approved_document_name: string;
    friendly_title: string | null;
    brand: string | null;
    notes: string | null;
    thumbnail_path: string | null;
    campaign_group: string | null;
    country_code: string | null;
    total_events: number;
    total_opened: number;
    total_clicked: number;
    latest_sent_email_name: string | null;
    last_sent_at: string | null;
  }>,
) {
  const grouped = new Map<string, GroupedMetadataRow>();

  for (const item of rows) {
    const displayName = (item.friendly_title || item.approved_document_name || "").trim();
    if (!displayName) continue;
    const groupKey = normalizeEmailName(displayName);
    if (!groupKey) continue;

    const current = grouped.get(groupKey) ?? {
      group_key: groupKey,
      email_name: displayName,
      approved_document_names: [],
      latest_sent_email_name: item.latest_sent_email_name,
      countries: [],
      last_sent_at: item.last_sent_at,
      total_events: 0,
      total_opened: 0,
      total_clicked: 0,
      brand: item.brand || "Unspecified",
      notes: item.notes || null,
      thumbnail_path: item.thumbnail_path || null,
      campaign_group: item.campaign_group || null,
    };

    current.total_events += Number(item.total_events ?? 0);
    current.total_opened += Number(item.total_opened ?? 0);
    current.total_clicked += Number(item.total_clicked ?? 0);
    if (item.approved_document_name && !current.approved_document_names.includes(item.approved_document_name)) {
      current.approved_document_names.push(item.approved_document_name);
    }
    if (item.country_code && !current.countries.includes(item.country_code)) {
      current.countries.push(item.country_code);
    }
    if (parseDate(item.last_sent_at) > parseDate(current.last_sent_at)) {
      current.last_sent_at = item.last_sent_at;
      current.latest_sent_email_name = item.latest_sent_email_name || current.latest_sent_email_name;
    }
    if (!current.notes && item.notes) current.notes = item.notes;
    if (!current.thumbnail_path && item.thumbnail_path) current.thumbnail_path = item.thumbnail_path;
    if (!current.campaign_group && item.campaign_group) current.campaign_group = item.campaign_group;
    if ((!current.brand || current.brand === "Unspecified") && item.brand) current.brand = item.brand;
    if (current.email_name.length < displayName.length) current.email_name = displayName;

    grouped.set(groupKey, current);
  }

  return [...grouped.values()].map((row) => ({
    ...row,
    approved_document_names: [...row.approved_document_names].sort((a, b) => a.localeCompare(b)),
    countries: [...row.countries].sort((a, b) => a.localeCompare(b)),
    brand: row.brand || "Unspecified",
  }));
}

async function fetchLocalWorkspace(filters: MetadataFilters, allowedCountries: string[] = []) {
  const db = await getLocalDb();
  const metadataByDocument = new Map(db.email_metadata.map((item) => [item.approved_document_name, item]));
  const allowedCountrySet = new Set(allowedCountries.map((country) => country.toUpperCase()));
  const scopedEvents =
    allowedCountrySet.size > 0
      ? db.raw_email_events.filter((event) => allowedCountrySet.has(event.primary_country_code.toUpperCase()))
      : db.raw_email_events;

  const sourceRows = scopedEvents.map((event) => {
    const metadata = metadataByDocument.get(event.approved_document_name);
    return {
      approved_document_name: event.approved_document_name,
      friendly_title: metadata?.friendly_title ?? event.approved_document_name,
      brand: metadata?.brand ?? "Unspecified",
      notes: metadata?.notes ?? null,
      thumbnail_path: metadata?.thumbnail_path ?? null,
      campaign_group: metadata?.campaign_group ?? null,
      country_code: event.primary_country_code,
      total_events: 1,
      total_opened: Number(event.opened ?? 0),
      total_clicked: Number(event.clicked ?? 0),
      latest_sent_email_name: event.sent_email_name || null,
      last_sent_at: event.sent_date || event.created_at || null,
    };
  });

  const groupedRows = groupByEmailName(sourceRows);
  const availableCountries = [
    ...new Set(groupedRows.flatMap((row) => row.countries).filter(Boolean)),
  ].sort((a, b) => a.localeCompare(b));
  const availableBrands = [...new Set(groupedRows.map((row) => row.brand).filter(Boolean))].sort((a, b) =>
    a.localeCompare(b),
  );

  const filtered = groupedRows
    .filter((row) => (filters.country ? row.countries.includes(filters.country) : true))
    .filter((row) => (filters.brand ? row.brand === filters.brand : true))
    .filter((row) => matchesSearch(row, filters.q))
    .sort((a, b) => parseDate(b.last_sent_at) - parseDate(a.last_sent_at));

  const totalRows = filtered.length;
  const totalPages = Math.max(1, Math.ceil(totalRows / PAGE_SIZE));
  const page = Math.min(filters.page, totalPages);
  const start = (page - 1) * PAGE_SIZE;
  const rows = filtered.slice(start, start + PAGE_SIZE);
  const selected =
    (filters.group ? filtered.find((row) => row.group_key === filters.group) : null) ?? rows[0] ?? null;

  return {
    rows,
    selected,
    totalRows,
    page,
    totalPages,
    availableCountries,
    availableBrands,
  };
}

async function fetchSupabaseWorkspace(filters: MetadataFilters) {
  const supabase = await createClient();

  let metricsQuery = supabase
    .from("document_country_metrics")
    .select("approved_document_name, friendly_title, brand, country_code, total_emails_sent, total_opened, total_clicked, latest_sent_at");

  if (filters.country) metricsQuery = metricsQuery.eq("country_code", filters.country);
  if (filters.brand) metricsQuery = metricsQuery.eq("brand", filters.brand);

  const search = filters.q.replace(/[%,]/g, "").trim();
  if (search) {
    const like = `%${search}%`;
    metricsQuery = metricsQuery.or(
      `approved_document_name.ilike.${like},friendly_title.ilike.${like},brand.ilike.${like},country_code.ilike.${like}`,
    );
  }

  const { data: metricsRows, error: metricsError } = await metricsQuery.limit(6000);
  if (metricsError) throw new Error(metricsError.message);

  const { data: metadataRows, error: metadataError } = await supabase
    .from("email_metadata")
    .select("approved_document_name, notes, thumbnail_path, campaign_group, friendly_title, brand");
  if (metadataError) throw new Error(metadataError.message);
  const metadataByDocument = new Map(
    (metadataRows ?? []).map((row) => {
      const item = row as {
        approved_document_name: string;
        notes: string | null;
        thumbnail_path: string | null;
        campaign_group: string | null;
        friendly_title: string | null;
        brand: string | null;
      };
      return [item.approved_document_name, item];
    }),
  );

  const { data: rawEventsRows, error: rawEventsError } = await supabase
    .from("raw_email_events")
    .select("approved_document_name, sent_email_name, sent_date, created_at");
  if (rawEventsError) throw new Error(rawEventsError.message);

  const latestEventByDocument = new Map<string, { sent_email_name: string | null; last_sent_at: string | null }>();
  for (const item of rawEventsRows ?? []) {
    const row = item as {
      approved_document_name: string;
      sent_email_name: string | null;
      sent_date: string | null;
      created_at: string | null;
    };
    const key = row.approved_document_name;
    if (!key) continue;
    const candidateDate = row.sent_date || row.created_at || null;
    const current = latestEventByDocument.get(key) ?? { sent_email_name: null, last_sent_at: null };
    if (parseDate(candidateDate) > parseDate(current.last_sent_at)) {
      latestEventByDocument.set(key, {
        sent_email_name: row.sent_email_name || null,
        last_sent_at: candidateDate,
      });
    } else if (!latestEventByDocument.has(key)) {
      latestEventByDocument.set(key, current);
    }
  }

  const sourceRows = (metricsRows ?? []).map((item) => {
    const row = item as {
      approved_document_name: string;
      friendly_title: string | null;
      brand: string | null;
      country_code: string | null;
      total_emails_sent: number | null;
      total_opened: number | null;
      total_clicked: number | null;
      latest_sent_at: string | null;
    };
    const meta = metadataByDocument.get(row.approved_document_name);
    const latestEvent = latestEventByDocument.get(row.approved_document_name);

    return {
      approved_document_name: row.approved_document_name,
      friendly_title: meta?.friendly_title ?? row.friendly_title ?? row.approved_document_name,
      brand: meta?.brand ?? row.brand ?? "Unspecified",
      notes: meta?.notes ?? null,
      thumbnail_path: meta?.thumbnail_path ?? null,
      campaign_group: meta?.campaign_group ?? null,
      country_code: row.country_code,
      total_events: Number(row.total_emails_sent ?? 0),
      total_opened: Number(row.total_opened ?? 0),
      total_clicked: Number(row.total_clicked ?? 0),
      latest_sent_email_name: latestEvent?.sent_email_name ?? null,
      last_sent_at: latestEvent?.last_sent_at ?? row.latest_sent_at,
    };
  });

  const groupedRows = groupByEmailName(sourceRows).sort((a, b) => parseDate(b.last_sent_at) - parseDate(a.last_sent_at));
  const availableCountries = [
    ...new Set(groupedRows.flatMap((row) => row.countries).filter(Boolean)),
  ].sort((a, b) => a.localeCompare(b));
  const availableBrands = [...new Set(groupedRows.map((row) => row.brand).filter(Boolean))].sort((a, b) =>
    a.localeCompare(b),
  );

  const totalRows = groupedRows.length;
  const totalPages = Math.max(1, Math.ceil(totalRows / PAGE_SIZE));
  const page = Math.min(filters.page, totalPages);
  const start = (page - 1) * PAGE_SIZE;
  const rows = groupedRows.slice(start, start + PAGE_SIZE);
  const selected =
    (filters.group ? groupedRows.find((row) => row.group_key === filters.group) : null) ?? rows[0] ?? null;

  return {
    rows,
    selected,
    totalRows,
    page,
    totalPages,
    availableCountries,
    availableBrands,
  };
}

export default async function MetadataPage({
  searchParams,
}: {
  searchParams: Promise<{ q?: string; country?: string; brand?: string; page?: string; group?: string; saved?: string }>;
}) {
  const viewer = await getViewerContext();
  const rawParams = await searchParams;
  const filters = normalizeFilters(rawParams);
  const saveSuccess = rawParams.saved === "1";
  const localScopeCountries =
    viewer.role === ROLES.affiliate ? viewer.allowedCountries.map((country) => country.toUpperCase()) : [];
  const workspace = env.hasSupabasePublicEnv
    ? await fetchSupabaseWorkspace(filters)
    : await fetchLocalWorkspace(filters, localScopeCountries);

  const selected = workspace.selected;
  const canEditDocumentMetadata = viewer.role === ROLES.admin;
  const canSaveRegionalMetadata = canEditDocumentMetadata || Boolean(selected?.latest_sent_email_name);
  const from = workspace.totalRows === 0 ? 0 : (workspace.page - 1) * PAGE_SIZE + 1;
  const to = Math.min(workspace.totalRows, workspace.page * PAGE_SIZE);
  const selectedThumbnailUrl = getPublicThumbnailUrl(selected?.thumbnail_path ?? null);
  const selectedSourceAssetUrl = getPublicSourceAssetUrl(selected?.thumbnail_path ?? null);
  const selectedIsPdfAsset = isPdfMetaAsset(selected?.thumbnail_path ?? null);
  const canonicalBrands = workspace.availableBrands.filter((brand) => brand && brand !== "Unspecified");
  const selectedBrand = selected && selected.brand && selected.brand !== "Unspecified" ? selected.brand : "";
  const brandSelectValue = selectedBrand && canonicalBrands.includes(selectedBrand) ? selectedBrand : "";
  const brandCustomValue = selectedBrand && !canonicalBrands.includes(selectedBrand) ? selectedBrand : "";
  const returnTo = selected
    ? buildMetadataHref({ ...filters, page: workspace.page, group: selected.group_key })
    : buildMetadataHref({ ...filters, page: workspace.page });

  return (
    <div className="space-y-4">
      <Card className="bg-[linear-gradient(120deg,#ffffff_0%,#f4f9ff_62%,#fff4e9_100%)]">
        <h2 className="text-2xl font-black tracking-tight text-slate-900">VEEVA Metadata Studio</h2>
        <p className="mt-2 text-sm text-slate-600">
          {viewer.role === ROLES.admin
            ? "Grouped by email name with duplicate variants merged."
            : "Regional mode: grouped by email name inside your assigned region."}
        </p>
        {viewer.role === ROLES.affiliate ? (
          <p className="mt-2 rounded-lg border border-[#d6e4f3] bg-[#f4f9ff] px-3 py-2 text-xs text-slate-600">
            Regional updates save as event-level overrides scoped to your visible region.
          </p>
        ) : null}

        <form className="mt-4 grid gap-2 md:grid-cols-2 xl:grid-cols-6">
          <Input name="q" defaultValue={filters.q} placeholder="Search email name, brand, country..." className="xl:col-span-2" />
          <Select name="country" defaultValue={filters.country}>
            <option value="">All countries</option>
            {workspace.availableCountries.map((country) => (
              <option key={country} value={country}>
                {country}
              </option>
            ))}
          </Select>
          <Select name="brand" defaultValue={filters.brand}>
            <option value="">All brands</option>
            {workspace.availableBrands.map((brand) => (
              <option key={brand} value={brand}>
                {brand}
              </option>
            ))}
          </Select>
          <Button type="submit">Filter</Button>
          <Link
            href={ROUTES.metadata}
            className="inline-flex h-10 items-center justify-center rounded-xl border border-slate-300 bg-white px-4 text-sm font-semibold text-slate-700 transition hover:border-[#F7993A] hover:bg-[#fff4e8]"
          >
            Reset
          </Link>
        </form>

        <p className="mt-3 text-xs text-slate-500">
          Showing {formatInteger(from)}-{formatInteger(to)} of {formatInteger(workspace.totalRows)} grouped email names
          {!env.hasSupabasePublicEnv ? " (local mode)" : ""}.
        </p>
      </Card>

      <section className="grid gap-4 xl:grid-cols-[420px_minmax(0,1fr)]">
        <Card className="max-h-[78vh] overflow-hidden p-0">
          <div className="border-b border-[#deebf8] px-4 py-3">
            <h3 className="text-sm font-semibold text-slate-900">Email Name List</h3>
          </div>
          <div className="max-h-[calc(78vh-115px)] overflow-auto">
            {workspace.rows.length === 0 ? (
              <p className="p-4 text-sm text-slate-500">No email names found for this filter.</p>
            ) : (
              <div className="divide-y divide-[#e3edf8]">
                {workspace.rows.map((row) => {
                  const active = selected?.group_key === row.group_key;
                  return (
                    <Link
                      key={row.group_key}
                      href={buildMetadataHref({
                        ...filters,
                        page: workspace.page,
                        group: row.group_key,
                      })}
                      className={`block px-4 py-3 transition ${active ? "bg-[#edf4ff]" : "hover:bg-[#f6faff]"}`}
                    >
                      <p className="mt-1 text-sm font-semibold text-slate-900">{row.email_name}</p>
                      <p className="mt-1 text-xs text-slate-500">
                        {row.brand} · {row.countries.join(", ") || "N/A"} · {formatInteger(row.total_events)} sends
                      </p>
                    </Link>
                  );
                })}
              </div>
            )}
          </div>
          <div className="flex items-center justify-between border-t border-[#deebf8] px-4 py-2 text-xs">
            <Link
              href={buildMetadataHref({
                ...filters,
                page: Math.max(1, workspace.page - 1),
                group: selected?.group_key ?? "",
              })}
              className={`font-semibold ${workspace.page <= 1 ? "pointer-events-none text-slate-300" : "text-[#2663AC]"}`}
            >
              Previous
            </Link>
            <span className="text-slate-500">
              Page {workspace.page} / {workspace.totalPages}
            </span>
            <Link
              href={buildMetadataHref({
                ...filters,
                page: Math.min(workspace.totalPages, workspace.page + 1),
                group: selected?.group_key ?? "",
              })}
              className={`font-semibold ${workspace.page >= workspace.totalPages ? "pointer-events-none text-slate-300" : "text-[#2663AC]"}`}
            >
              Next
            </Link>
          </div>
        </Card>

        <Card>
          {!selected ? (
            <p className="text-sm text-slate-500">Select an email name from the left to edit metadata.</p>
          ) : (
            <>
              <div className="flex flex-wrap items-start justify-between gap-3">
                <div>
                  <h3 className="text-lg font-semibold text-slate-900">{selected.email_name}</h3>
                  <p className="mt-1 text-xs text-slate-500">
                    Countries: {selected.countries.join(", ") || "N/A"} · Sends: {formatInteger(selected.total_events)}
                  </p>
                  <p className="mt-1 text-xs text-slate-500">
                    Last send: {formatSentDate(selected.last_sent_at)}
                    {selected.latest_sent_email_name ? ` · ${selected.latest_sent_email_name}` : ""}
                  </p>
                  <p className="mt-1 text-xs text-slate-500">
                    Variants merged: {selected.approved_document_names.length}
                  </p>
                </div>
                {selectedThumbnailUrl ? (
                  selectedSourceAssetUrl && selectedIsPdfAsset ? (
                    <a href={selectedSourceAssetUrl} target="_blank" rel="noreferrer" className="block">
                      {/* eslint-disable-next-line @next/next/no-img-element */}
                      <img
                        src={selectedThumbnailUrl}
                        alt={selected.email_name}
                        className="h-20 w-32 rounded-lg border border-[#d7e3f2] object-cover"
                      />
                    </a>
                  ) : (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img
                      src={selectedThumbnailUrl}
                      alt={selected.email_name}
                      className="h-20 w-32 rounded-lg border border-[#d7e3f2] object-cover"
                    />
                  )
                ) : selectedSourceAssetUrl && selectedIsPdfAsset ? (
                  <a
                    href={selectedSourceAssetUrl}
                    target="_blank"
                    rel="noreferrer"
                    className="inline-flex h-20 items-center rounded-lg border border-[#d7e3f2] bg-white px-3 text-xs font-semibold text-[#2663AC]"
                  >
                    Open PDF
                  </a>
                ) : null}
              </div>

              <form key={selected.group_key} action={saveMetadataAction} className="mt-4 grid gap-3">
                <input type="hidden" name="approved_document_name" value={selected.approved_document_names[0] ?? ""} />
                <input
                  type="hidden"
                  name="approved_document_names"
                  value={JSON.stringify(selected.approved_document_names)}
                />
                <input type="hidden" name="sent_email_name" value={selected.latest_sent_email_name ?? ""} />
                <input type="hidden" name="group_key" value={selected.group_key} />
                <input type="hidden" name="return_to" value={returnTo} />
                <div className="grid gap-3 lg:grid-cols-3">
                  <Input name="friendly_title" defaultValue={selected.email_name} placeholder="Email name / friendly title" />
                  <div className="space-y-1">
                    <Select name="brand" defaultValue={brandSelectValue}>
                      <option value="">Choose existing brand</option>
                      {canonicalBrands.map((brand) => (
                        <option key={brand} value={brand}>
                          {brand}
                        </option>
                      ))}
                    </Select>
                    <Input
                      name="brand_custom"
                      defaultValue={brandCustomValue}
                      placeholder="Or add new brand"
                      autoComplete="off"
                    />
                    <p className="text-xs text-slate-500">Choose existing brand or enter a new one.</p>
                  </div>
                  <Input name="campaign_group" defaultValue={selected.campaign_group ?? ""} placeholder="Campaign group" />
                </div>
                <Textarea name="notes" defaultValue={selected.notes ?? ""} placeholder="Notes / description" rows={4} />
                <div className="flex flex-wrap items-center gap-3">
                  {canEditDocumentMetadata ? (
                    <div className="flex flex-wrap items-center gap-2">
                      <input
                        type="file"
                        name="thumbnail"
                        accept="image/png,image/jpeg,image/webp,application/pdf"
                        className="block rounded-lg border border-slate-300 bg-slate-50 px-3 py-2 text-xs text-slate-600"
                      />
                      <Input
                        type="number"
                        name="thumbnail_page"
                        min={1}
                        defaultValue={1}
                        placeholder="PDF page"
                        className="h-10 w-28"
                      />
                    </div>
                  ) : null}
                  <FormSubmitButton
                    idleLabel={viewer.role === ROLES.admin ? "Save Metadata" : "Save Regional Metadata"}
                    pendingLabel="Saving..."
                    variant="secondary"
                    disabled={!canSaveRegionalMetadata}
                  />
                  {canEditDocumentMetadata && selected.thumbnail_path ? (
                    <FormSubmitButton
                      idleLabel="Remove Asset"
                      pendingLabel="Removing..."
                      variant="danger"
                      name="thumbnail_intent"
                      value="remove"
                      disabled={!canSaveRegionalMetadata}
                    />
                  ) : null}
                  {!canEditDocumentMetadata ? (
                    <p className="text-xs text-slate-500">
                      {selected.latest_sent_email_name
                        ? `Updates will apply to ${selected.latest_sent_email_name}.`
                        : "No sent email event is available for this group yet."}
                    </p>
                  ) : null}
                </div>
              </form>
              {saveSuccess ? (
                <p className="mt-3 rounded-lg border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-700">
                  Metadata saved.
                </p>
              ) : null}
            </>
          )}
        </Card>
      </section>
    </div>
  );
}
