import { Badge } from "@/components/ui/badge";
import {
  Card,
  CardBody,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  listMobileCrashes,
  getMobileCrashSummary,
  getMobileCrashFilterOptions,
  type MobileCrashFilters,
  type MobileCrashKind,
} from "@/lib/db/queries/mobile-crashes";
import { logActivity } from "@/lib/db/audit";
import { getSession } from "@/lib/auth/session";
import { CrashFilters } from "./_components/crash-filters";

export const dynamic = "force-dynamic";

const LIST_LIMIT = 200;

const dateTimeFmt = new Intl.DateTimeFormat("fr-FR", {
  day: "2-digit",
  month: "short",
  year: "numeric",
  hour: "2-digit",
  minute: "2-digit",
});

const VALID_KINDS: MobileCrashKind[] = ["render", "fatal", "rejection"];

// Coercion défensive des searchParams (entrée non fiable) en filtres typés.
// On ne garde une valeur que si elle est plausible — un `kind` inconnu ou un
// `tenant` non numérique est ignoré plutôt que poussé tel quel en SQL.
function parseFilters(sp: Record<string, string | string[] | undefined>): {
  filters: MobileCrashFilters;
  raw: {
    kind: string;
    tenant: string;
    version: string;
    instance: string;
    from: string;
    to: string;
  };
} {
  const one = (v: string | string[] | undefined): string =>
    (Array.isArray(v) ? v[0] : v) ?? "";

  const kindRaw = one(sp.kind);
  const tenantRaw = one(sp.tenant);
  const versionRaw = one(sp.version);
  const instanceRaw = one(sp.instance);
  const fromRaw = one(sp.from);
  const toRaw = one(sp.to);

  const isDate = (s: string) => /^\d{4}-\d{2}-\d{2}$/.test(s);
  const tenantId = Number.parseInt(tenantRaw, 10);

  const filters: MobileCrashFilters = {};
  if ((VALID_KINDS as string[]).includes(kindRaw))
    filters.kind = kindRaw as MobileCrashKind;
  if (Number.isFinite(tenantId) && tenantId > 0) filters.tenantId = tenantId;
  if (versionRaw) filters.appVersion = versionRaw;
  if (instanceRaw) filters.instanceUrl = instanceRaw;
  if (isDate(fromRaw)) filters.from = fromRaw;
  if (isDate(toRaw)) filters.to = toRaw;

  return {
    filters,
    raw: {
      kind: filters.kind ?? "",
      tenant: filters.tenantId ? String(filters.tenantId) : "",
      version: filters.appVersion ?? "",
      instance: filters.instanceUrl ?? "",
      from: filters.from ?? "",
      to: filters.to ?? "",
    },
  };
}

function kindTone(kind: MobileCrashKind): "danger" | "warning" | "info" {
  if (kind === "fatal") return "danger";
  if (kind === "render") return "warning";
  return "info"; // rejection
}

function kindLabel(kind: MobileCrashKind): string {
  if (kind === "fatal") return "Fatal";
  if (kind === "render") return "Rendu";
  return "Rejet";
}

export default async function CrashsMobilePage({
  searchParams,
}: {
  searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
  const sp = await searchParams;
  const { filters, raw } = parseFilters(sp);
  const session = await getSession();

  let rows: Awaited<ReturnType<typeof listMobileCrashes>> = [];
  let summary: Awaited<ReturnType<typeof getMobileCrashSummary>> = {
    total: 0,
    fatal: 0,
    render: 0,
    rejection: 0,
  };
  let options: Awaited<ReturnType<typeof getMobileCrashFilterOptions>> = {
    versions: [],
    instances: [],
    tenants: [],
  };
  let loadError: string | null = null;

  try {
    [rows, summary, options] = await Promise.all([
      listMobileCrashes(filters, LIST_LIMIT),
      getMobileCrashSummary(filters),
      getMobileCrashFilterOptions(),
    ]);
    void logActivity({
      type: "superadmin.mobile_crashes_view",
      title: "Vue crashs mobile",
      description: `filtres=${JSON.stringify(raw)} · ${summary.total} crash(s)`,
      user_id: session?.user.id,
      tenant_id: filters.tenantId,
    });
  } catch (err) {
    loadError = err instanceof Error ? err.message : "Erreur inconnue";
  }

  const capped = summary.total > LIST_LIMIT;

  return (
    <div className="px-6 py-6 lg:px-10">
      <header className="mb-6">
        <h1 className="text-2xl font-semibold">Crashs mobile</h1>
        <p className="text-sm text-muted-foreground">
          Incidents remontés par l&apos;app mobile (rendu, fatals, rejets de
          promesse). Lecture directe de{" "}
          <code className="font-mono text-xs">mobile_crash_reports</code>.
        </p>
      </header>

      {loadError && (
        <div className="rounded-md border border-red-200 bg-danger-subtle px-4 py-3 text-sm text-danger">
          Impossible de charger les crashs : {loadError}
        </div>
      )}

      {!loadError && (
        <>
          <section className="mb-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
            <SummaryCard
              label="Total (filtré)"
              value={summary.total}
              tone="neutral"
            />
            <SummaryCard label="Fatals" value={summary.fatal} tone="danger" />
            <SummaryCard label="Rendu" value={summary.render} tone="warning" />
            <SummaryCard
              label="Rejets"
              value={summary.rejection}
              tone="info"
            />
          </section>

          <div className="mb-6">
            <CrashFilters options={options} current={raw} />
          </div>

          {rows.length === 0 ? (
            <div className="rounded-md border border-border bg-surface px-4 py-8 text-center text-sm text-muted-foreground">
              Aucun crash ne correspond à ces filtres.
            </div>
          ) : (
            <>
              {capped && (
                <p className="mb-2 text-xs text-warning">
                  {summary.total} crashs correspondent ; seuls les{" "}
                  {LIST_LIMIT} plus récents sont affichés. Affinez les filtres
                  (dates, tenant…) pour réduire la liste.
                </p>
              )}
              <div className="overflow-hidden rounded-lg border border-border bg-surface">
                <table className="w-full text-sm">
                  <thead className="bg-surface-2 text-left text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
                    <tr>
                      <th className="px-4 py-2.5">Quand</th>
                      <th className="px-4 py-2.5">Type</th>
                      <th className="px-4 py-2.5">Message</th>
                      <th className="px-4 py-2.5">Tenant</th>
                      <th className="px-4 py-2.5">Version / Plateforme</th>
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-border">
                    {rows.map((c) => (
                      <tr key={c.id} className="hover:bg-surface-2/60">
                        <td className="px-4 py-2 align-top text-xs text-muted-foreground tabular-nums whitespace-nowrap">
                          {dateTimeFmt.format(new Date(c.created_at))}
                          {c.client_timestamp && (
                            <div
                              className="text-[10px] text-subtle-foreground"
                              title="Horodatage côté client (peut différer de l'ingestion serveur)"
                            >
                              client :{" "}
                              {dateTimeFmt.format(new Date(c.client_timestamp))}
                            </div>
                          )}
                        </td>
                        <td className="px-4 py-2 align-top">
                          <Badge tone={kindTone(c.kind)}>
                            {kindLabel(c.kind)}
                          </Badge>
                          {c.is_fatal === 1 && c.kind !== "fatal" && (
                            <div className="mt-1 text-[10px] font-medium text-danger">
                              fatal
                            </div>
                          )}
                        </td>
                        <td className="px-4 py-2 align-top">
                          <div className="max-w-md break-words text-sm font-medium">
                            {c.message || (
                              <span className="italic text-muted-foreground">
                                (sans message)
                              </span>
                            )}
                          </div>
                          {(c.stack || c.component_stack) && (
                            <details className="mt-1">
                              <summary className="cursor-pointer text-[11px] text-accent hover:underline">
                                Stack
                              </summary>
                              {c.stack && (
                                <pre className="mt-1 max-h-64 overflow-auto rounded border border-border bg-surface-2 p-2 text-[10px] leading-relaxed text-muted-foreground whitespace-pre-wrap break-words">
                                  {c.stack}
                                </pre>
                              )}
                              {c.component_stack && (
                                <>
                                  <div className="mt-1 text-[10px] font-medium uppercase tracking-wider text-subtle-foreground">
                                    Component stack
                                  </div>
                                  <pre className="mt-0.5 max-h-64 overflow-auto rounded border border-border bg-surface-2 p-2 text-[10px] leading-relaxed text-muted-foreground whitespace-pre-wrap break-words">
                                    {c.component_stack}
                                  </pre>
                                </>
                              )}
                            </details>
                          )}
                        </td>
                        <td className="px-4 py-2 align-top text-xs">
                          {c.tenant_name ? (
                            <>
                              <div>{c.tenant_name}</div>
                              <div className="font-mono text-[10px] text-muted-foreground">
                                {c.tenant_slug}
                              </div>
                            </>
                          ) : (
                            <span className="italic text-muted-foreground">
                              hors-tenant
                            </span>
                          )}
                          {c.user_name?.trim() && (
                            <div className="mt-0.5 text-[10px] text-muted-foreground">
                              {c.user_name}
                            </div>
                          )}
                        </td>
                        <td className="px-4 py-2 align-top text-xs">
                          <div className="font-mono">
                            {c.app_version ?? "—"}
                          </div>
                          {c.platform && (
                            <div className="text-[10px] text-muted-foreground">
                              {c.platform}
                            </div>
                          )}
                          {c.instance_url && (
                            <div
                              className="mt-0.5 max-w-[12rem] truncate font-mono text-[10px] text-subtle-foreground"
                              title={c.instance_url}
                            >
                              {c.instance_url}
                            </div>
                          )}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </>
          )}
        </>
      )}
    </div>
  );
}

function SummaryCard({
  label,
  value,
  tone,
}: {
  label: string;
  value: number;
  tone: "neutral" | "danger" | "warning" | "info";
}) {
  const valueTone =
    tone === "danger"
      ? "text-danger"
      : tone === "warning"
        ? "text-warning"
        : tone === "info"
          ? "text-info"
          : "text-foreground";
  return (
    <Card>
      <CardHeader>
        <CardTitle className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
          {label}
        </CardTitle>
      </CardHeader>
      <CardBody>
        <p className={`text-3xl font-semibold tabular-nums ${valueTone}`}>
          {value}
        </p>
      </CardBody>
    </Card>
  );
}
