"use client";

import { useCallback, useMemo, useRef, useState } from "react";
import { toPng } from "html-to-image";
import { ImageIcon, Upload, Video, Volume2, VolumeX, X } from "lucide-react";
import { RemindMeButton } from "@/components/reminders/remind-me-button";
import { ReviewShareStudio, dataUrlToFile } from "@/components/reviews/review-share-studio";
import {
  BackgroundPicker,
  BackgroundVideoLayer,
  MindavioLogo,
  MindavioLogoCompact,
  useBackgroundPicker,
} from "@/components/shared/background-picker";
import { captureElementWithVideoBackground } from "@/lib/review-video-export";
import { cn } from "@/lib/utils";
import type { ChatSharePayload } from "@/components/chat/share-to-chat-modal";
import type { FinanceTransaction } from "@/types";

type PnLPeriod = "daily" | "weekly" | "monthly" | "yearly";

const PERIOD_LABELS: Record<PnLPeriod, string> = {
  daily: "Heute",
  weekly: "Diese Woche",
  monthly: "Dieser Monat",
  yearly: "Dieses Jahr",
};

function formatMoney(cents: number) {
  return new Intl.NumberFormat("de-DE", {
    currency: "EUR",
    minimumFractionDigits: 2,
    style: "currency",
  }).format(cents / 100);
}

function formatPercent(value: number) {
  if (!Number.isFinite(value)) return "—";
  const sign = value >= 0 ? "+" : "";
  return `${sign}${value.toFixed(1)}%`;
}

function getDateRange(period: PnLPeriod): {
  end: Date;
  prevEnd: Date;
  prevStart: Date;
  start: Date;
} {
  const now = new Date();
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());

  switch (period) {
    case "daily": {
      const start = new Date(today);
      const end = new Date(today);
      const prevStart = new Date(today);
      prevStart.setDate(prevStart.getDate() - 1);
      const prevEnd = new Date(prevStart);
      return { end, prevEnd, prevStart, start };
    }
    case "weekly": {
      const dayOfWeek = today.getDay() || 7;
      const start = new Date(today);
      start.setDate(start.getDate() - dayOfWeek + 1);
      const end = new Date(today);
      const prevStart = new Date(start);
      prevStart.setDate(prevStart.getDate() - 7);
      const prevEnd = new Date(start);
      prevEnd.setDate(prevEnd.getDate() - 1);
      return { end, prevEnd, prevStart, start };
    }
    case "monthly": {
      const start = new Date(today.getFullYear(), today.getMonth(), 1);
      const end = new Date(today);
      const prevStart = new Date(today.getFullYear(), today.getMonth() - 1, 1);
      const prevEnd = new Date(today.getFullYear(), today.getMonth(), 0);
      return { end, prevEnd, prevStart, start };
    }
    case "yearly": {
      const start = new Date(today.getFullYear(), 0, 1);
      const end = new Date(today);
      const prevStart = new Date(today.getFullYear() - 1, 0, 1);
      const prevEnd = new Date(today.getFullYear() - 1, 11, 31);
      return { end, prevEnd, prevStart, start };
    }
  }
}

function toDateKey(date: Date) {
  return date.toISOString().split("T")[0];
}

function filterTransactions(transactions: FinanceTransaction[], start: Date, end: Date) {
  return transactions.filter((transaction) => {
    const date = new Date(`${transaction.transaction_date}T00:00:00`);
    return date >= start && date <= end;
  });
}

function computePnL(transactions: FinanceTransaction[]) {
  const income = transactions
    .filter((transaction) => transaction.type === "income")
    .reduce((sum, transaction) => sum + transaction.amount_cents, 0);
  const expenses = transactions
    .filter((transaction) => transaction.type === "expense")
    .reduce((sum, transaction) => sum + transaction.amount_cents, 0);

  return { expenses, income, net: income - expenses };
}

interface PnLExportProps {
  transactions: FinanceTransaction[];
}

export function PnLExport({ transactions }: PnLExportProps) {
  const [period, setPeriod] = useState<PnLPeriod>("monthly");
  const [soundEnabled, setSoundEnabled] = useState(false);
  const cardRef = useRef<HTMLDivElement>(null);
  const mediaInputRef = useRef<HTMLInputElement>(null);
  const {
    bgStyle,
    customImage,
    customVideo,
    handleUpload,
    isCustom,
    isCustomVideo,
    presetId,
    removeCustom,
    setPresetId,
    theme,
  } = useBackgroundPicker("mb-dark");

  const { end, prevEnd, prevStart, start } = useMemo(() => getDateRange(period), [period]);
  const currentTransactions = useMemo(
    () => filterTransactions(transactions, start, end),
    [transactions, start, end],
  );
  const previousTransactions = useMemo(
    () => filterTransactions(transactions, prevStart, prevEnd),
    [transactions, prevStart, prevEnd],
  );
  const current = useMemo(() => computePnL(currentTransactions), [currentTransactions]);
  const previous = useMemo(() => computePnL(previousTransactions), [previousTransactions]);

  const incomeChange = previous.income > 0 ? ((current.income - previous.income) / previous.income) * 100 : 0;
  const expenseChange = previous.expenses > 0 ? ((current.expenses - previous.expenses) / previous.expenses) * 100 : 0;
  const isVideoExport = isCustomVideo && !!customVideo;
  const { accentColor, showLogo, subtleColor, textColor } = theme;

  const periodLabel = useMemo(() => {
    const opts: Intl.DateTimeFormatOptions = { day: "2-digit", month: "short", year: "numeric" };
    if (period === "daily") return start.toLocaleDateString("de-DE", opts);
    return `${start.toLocaleDateString("de-DE", opts)} - ${end.toLocaleDateString("de-DE", opts)}`;
  }, [end, period, start]);

  const handleMediaUpload = useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) => {
      const file = event.target.files?.[0];
      if (!file) return;
      setSoundEnabled(false); // reset sound on new upload
      handleUpload(file);
      event.target.value = "";
    },
    [handleUpload],
  );

  const handleRemoveCustom = useCallback(() => {
    setSoundEnabled(false);
    removeCustom();
  }, [removeCustom]);

  const buildSharePayload = useCallback(async (): Promise<ChatSharePayload> => {
    if (!cardRef.current) throw new Error("Die PnL-Karte ist noch nicht bereit.");

    const dateKey = toDateKey(start);
    const files: File[] = [];

    if (isVideoExport && customVideo) {
      files.push(
        await captureElementWithVideoBackground(cardRef.current, {
          durationMs: 6500,
          fileName: `Mindavio-PnL-${period}-${dateKey}.webm`,
          fps: 30,
          pixelRatio: 2,
          videoSrc: customVideo,
        }),
      );
    } else {
      const dataUrl = await toPng(cardRef.current, { cacheBust: true, pixelRatio: 3 });
      files.push(dataUrlToFile(dataUrl, `Mindavio-PnL-${period}-${dateKey}.png`));
    }

    return {
      files,
      message: isVideoExport
        ? `Hier ist mein PnL-Video für ${PERIOD_LABELS[period]} (${periodLabel}).`
        : `Hier ist mein PnL für ${PERIOD_LABELS[period]} (${periodLabel}).`,
    };
  }, [customVideo, isVideoExport, period, periodLabel, start]);

  const shareDescription = useMemo(
    () =>
      isVideoExport
        ? `Sende dein PnL-Video für ${PERIOD_LABELS[period]} direkt als Chat-Anhang.`
        : `Sende dein PnL-Bild für ${PERIOD_LABELS[period]} direkt als Chat-Anhang.`,
    [isVideoExport, period],
  );

  const mediaLabel = isVideoExport
    ? "Video-Hintergrund aktiv"
    : isCustom && customImage
      ? "Bild-Hintergrund aktiv"
      : "Preset-Hintergrund";

  // When a custom image or video is active the text must stay readable regardless
  // of what's behind it — apply a strong black drop-shadow to numbers & labels.
  const textShadow = isCustom
    ? "0 1px 4px rgba(0,0,0,0.95), 0 2px 12px rgba(0,0,0,0.85), 0 0 2px rgba(0,0,0,1)"
    : undefined;

  const controls = (
    <div className="flex flex-wrap items-end gap-5">
      <div>
        <p className="mb-2 text-xs text-muted-foreground">Zeitraum</p>
        <div className="flex items-center gap-1 rounded-xl border border-border/60 bg-background/60 p-1">
          {(Object.entries(PERIOD_LABELS) as [PnLPeriod, string][]).map(([key, label]) => (
            <button
              key={key}
              onClick={() => setPeriod(key)}
              className={cn(
                "rounded-lg px-3 py-1.5 text-xs font-medium transition-all",
                period === key
                  ? "bg-foreground text-background shadow-sm"
                  : "text-muted-foreground hover:text-foreground",
              )}
            >
              {label}
            </button>
          ))}
        </div>
      </div>

      <BackgroundPicker
        customImage={customImage}
        customVideo={customVideo}
        onRemoveCustom={handleRemoveCustom}
        onSelectPreset={setPresetId}
        onUpload={handleUpload}
        presetId={presetId}
      />

      <div>
        <p className="mb-2 text-xs text-muted-foreground">PnL Media</p>
        <div className="flex items-center gap-2 rounded-2xl border border-white/[0.08] bg-white/[0.035] p-1.5">
          <button
            onClick={() => mediaInputRef.current?.click()}
            className="flex items-center gap-2 rounded-xl bg-white px-3 py-2 text-[11px] font-semibold text-black transition hover:opacity-90"
          >
            <Upload className="h-3.5 w-3.5" />
            Bild / Video
          </button>
          <div className="flex min-w-[155px] items-center gap-2 px-2 text-[11px] text-white/45">
            {isVideoExport ? <Video className="h-3.5 w-3.5 text-emerald-300" /> : <ImageIcon className="h-3.5 w-3.5" />}
            <span>{mediaLabel}</span>
          </div>
          {isVideoExport && (
            <button
              onClick={() => setSoundEnabled((v) => !v)}
              className={cn(
                "flex h-8 w-8 items-center justify-center rounded-lg transition",
                soundEnabled
                  ? "bg-emerald-500/20 text-emerald-300 hover:bg-emerald-500/30"
                  : "text-white/35 hover:bg-white/[0.06] hover:text-white",
              )}
              title={soundEnabled ? "Ton aus" : "Ton an"}
            >
              {soundEnabled
                ? <Volume2 className="h-3.5 w-3.5" />
                : <VolumeX className="h-3.5 w-3.5" />}
            </button>
          )}
          {isCustom && (
            <button
              onClick={handleRemoveCustom}
              className="flex h-8 w-8 items-center justify-center rounded-lg text-white/35 transition hover:bg-white/[0.06] hover:text-white"
              title="Eigenen Hintergrund entfernen"
            >
              <X className="h-3.5 w-3.5" />
            </button>
          )}
        </div>
        <input
          ref={mediaInputRef}
          accept="image/*,video/*"
          className="hidden"
          onChange={handleMediaUpload}
          type="file"
        />
      </div>

      <RemindMeButton
        body={`PnL ${PERIOD_LABELS[period]} prüfen: ${periodLabel}`}
        className="border-white/[0.08] bg-transparent px-4 py-2 text-xs text-white/70 hover:bg-white/[0.05]"
        label="Remind me"
        sourceId={`pnl-${period}-${toDateKey(start)}`}
        sourceTitle={`PnL ${PERIOD_LABELS[period]}`}
        sourceType="finance"
        sourceUrl="/finances"
        title={`PnL prüfen: ${PERIOD_LABELS[period]}`}
      />
    </div>
  );

  return (
    <ReviewShareStudio
      artifactType="finance"
      buildPayload={buildSharePayload}
      controls={controls}
      defaultMessage={`Hier ist mein PnL für ${PERIOD_LABELS[period]} (${periodLabel}).`}
      description={
        isVideoExport
          ? "Bild/Video Upload System mit bewegtem PnL-Hintergrund"
          : "Bild/Video Upload System für deine PnL Share Card"
      }
      downloadLabel={isVideoExport ? "Als Video speichern" : "Als Bild speichern"}
      icon={isVideoExport ? <Video className="h-4 w-4 text-white" /> : <ImageIcon className="h-4 w-4 text-white" />}
      shareDescription={shareDescription}
      shareTitle="PnL an Chat senden"
      title="PnL Export"
      tone="emerald"
    >
      <div className="overflow-hidden rounded-2xl border border-white/[0.07]">
        <div
          ref={cardRef}
          className="relative min-h-[500px] overflow-hidden p-8 sm:p-10 lg:p-12"
          style={{
            ...bgStyle,
            fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
          }}
        >
          <BackgroundVideoLayer src={isVideoExport ? customVideo : null} muted={!soundEnabled} />
          {isCustom && <div className="absolute inset-0 bg-black/44" />}

          {!isVideoExport && (
            <div
              className="pointer-events-none absolute inset-0 flex items-center justify-center"
              style={{ opacity: showLogo ? 0.55 : 0.35 }}
            >
              <MindavioLogo color={accentColor} size={340} />
            </div>
          )}

          {!isCustom && (
            <>
              <div
                className="absolute -right-10 -top-10 h-72 w-72 rounded-full opacity-15 blur-3xl"
                style={{ background: accentColor }}
              />
              <div
                className="absolute -bottom-16 -left-16 h-56 w-56 rounded-full opacity-10 blur-3xl"
                style={{ background: accentColor }}
              />
            </>
          )}

          <div className="relative mb-8 flex items-center justify-between">
            <div className="flex items-center gap-3">
              <MindavioLogoCompact color={accentColor} size={28} />
              <span className="text-[15px] font-semibold" style={{ color: textColor, letterSpacing: "-0.01em", textShadow }}>
                Mindavio
              </span>
            </div>
            <span className="text-[11px] font-medium uppercase tracking-[0.12em]" style={{ color: subtleColor, textShadow }}>
              Profit &amp; Loss
            </span>
          </div>

          <div className="relative mb-9">
            <p className="text-xs font-medium" style={{ color: subtleColor, textShadow }}>
              {PERIOD_LABELS[period]}
            </p>
            <p className="mt-0.5 text-xs" style={{ color: subtleColor, textShadow }}>
              {periodLabel}
            </p>
          </div>

          <div className="relative mb-14">
            <p className="mb-1 text-xs font-medium" style={{ color: subtleColor, textShadow }}>
              Netto Profit / Loss
            </p>
            <p className="text-4xl font-bold tracking-tight" style={{ color: current.net >= 0 ? "#34d399" : "#fb7185", textShadow }}>
              {current.net >= 0 ? "+" : ""}
              {formatMoney(current.net)}
            </p>
          </div>

          <div className="relative grid grid-cols-2 gap-6">
            <div
              className="rounded-xl p-4 backdrop-blur-sm"
              style={{
                background: isCustom ? "rgba(0,0,0,0.45)" : `${accentColor}08`,
                boxShadow: isCustom ? "inset 0 0 0 1px rgba(255,255,255,0.10)" : `inset 0 0 0 1px ${accentColor}15`,
              }}
            >
              <div className="mb-2 flex items-center justify-between">
                <p className="text-xs font-medium" style={{ color: subtleColor, textShadow }}>
                  Einnahmen
                </p>
                {previous.income > 0 && (
                  <span className="text-xs font-medium" style={{ color: incomeChange >= 0 ? "#34d399" : "#fb7185", textShadow }}>
                    {formatPercent(incomeChange)}
                  </span>
                )}
              </div>
              <p className="text-xl font-bold" style={{ color: "#34d399", textShadow }}>
                {formatMoney(current.income)}
              </p>
            </div>

            <div
              className="rounded-xl p-4 backdrop-blur-sm"
              style={{
                background: isCustom ? "rgba(0,0,0,0.45)" : `${accentColor}08`,
                boxShadow: isCustom ? "inset 0 0 0 1px rgba(255,255,255,0.10)" : `inset 0 0 0 1px ${accentColor}15`,
              }}
            >
              <div className="mb-2 flex items-center justify-between">
                <p className="text-xs font-medium" style={{ color: subtleColor, textShadow }}>
                  Ausgaben
                </p>
                {previous.expenses > 0 && (
                  <span className="text-xs font-medium" style={{ color: expenseChange <= 0 ? "#34d399" : "#fb7185", textShadow }}>
                    {formatPercent(expenseChange)}
                  </span>
                )}
              </div>
              <p className="text-xl font-bold" style={{ color: "#fb7185", textShadow }}>
                {formatMoney(current.expenses)}
              </p>
            </div>
          </div>

          <div
            className="relative mt-8 flex items-center justify-between pt-5"
            style={{ borderTop: `1px solid ${isCustom ? "rgba(255,255,255,0.12)" : `${accentColor}15`}` }}
          >
            <span className="text-[10px]" style={{ color: subtleColor, textShadow }}>
              mindavio.app
            </span>
            <span className="text-[10px]" style={{ color: subtleColor, textShadow }}>
              Generiert am{" "}
              {new Date().toLocaleDateString("de-DE", {
                day: "2-digit",
                month: "short",
                year: "numeric",
              })}
            </span>
          </div>
        </div>
      </div>
    </ReviewShareStudio>
  );
}
