"use client";

import * as React from "react";
import { format, parseISO } from "date-fns";
import { Save } from "lucide-react";
import type { DateRange } from "react-day-picker";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { DateRangePicker } from "@/components/date-range-picker";

import { CashflowFiltersForm } from "@/app/customer/[tenant]/reports/cashflow/_components/cashflow-report/cashflow-filters-form";
import {
  buildDefaultCashflowFilters,
  cashflowServerFilterIds,
  DEFAULT_STRUCTURE_STATUS_IDS,
  type CashflowFilters,
  type StructureStatusId,
} from "@/app/customer/[tenant]/reports/cashflow/_components/cashflow-report/schema";
import { defaultCashflowEventTypes } from "@/app/customer/[tenant]/reports/cashflow/_lib/cashflow-event-type-filters";
import {
  CASHFLOW_WIDGET_MAX_RANGE_DAYS,
  cashflowWidgetRangeDayCount,
  defaultCashflowWidgetDateRange,
  isCashflowWidgetDateRangeValid,
} from "@/app/customer/[tenant]/reports/cashflow/_lib/cashflow-widget-date-range";
import {
  loadDashboardAssetWidgetSettings,
  updateDashboardAssetWidgetSettings,
} from "../../../_lib/dashboard-widgets-api";
import type { DashboardCashflowWidget } from "../../../_lib/dashboard-widgets-server-api";
import type { WidgetConfigPanelProps } from "../types";

function toFilters(
  widget: DashboardCashflowWidget | null,
  bankIds: string[],
  assetCodes: string[],
): CashflowFilters {
  if (!widget) {
    return buildDefaultCashflowFilters({ bankIds, assetClasses: assetCodes });
  }
  return {
    bankIds: widget.selected_bank_ids.length > 0 ? [...widget.selected_bank_ids] : [...bankIds],
    assetClasses: widget.selected_asset_ids.length > 0 ? [...widget.selected_asset_ids] : [...assetCodes],
    search: "",
    eventTypes: {
      ...defaultCashflowEventTypes,
      ...(widget.event_types ?? {}),
    },
    structureStatusIds:
      widget.structure_status_ids.length > 0
        ? ([...widget.structure_status_ids] as StructureStatusId[])
        : ([...DEFAULT_STRUCTURE_STATUS_IDS] as StructureStatusId[]),
  };
}

function toDateRange(widget: DashboardCashflowWidget | null): { dateFrom: string; dateTo: string } {
  const defaults = defaultCashflowWidgetDateRange();
  const dateFrom = widget?.date_from?.trim() || defaults.dateFrom;
  const dateTo = widget?.date_to?.trim() || defaults.dateTo;
  return { dateFrom, dateTo };
}

function parseIsoDate(value: string): Date | undefined {
  const raw = value.trim();
  if (!raw) return undefined;
  const parsed = parseISO(raw);
  return Number.isNaN(parsed.getTime()) ? undefined : parsed;
}

function toPickerRange(dateFrom: string, dateTo: string): DateRange | undefined {
  const from = parseIsoDate(dateFrom);
  if (!from) return undefined;
  const to = parseIsoDate(dateTo);
  return { from, to: to ?? from };
}

export function CashflowCalendarConfigPanel({
  tenant,
  widget,
  mode = "edit",
  onClose,
  onWidgetsChanged,
}: WidgetConfigPanelProps) {
  const isCreate = mode === "create" || !widget;
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [busy, setBusy] = React.useState(false);
  const [title, setTitle] = React.useState("");
  const [filters, setFilters] = React.useState<CashflowFilters | null>(null);
  const [dateFrom, setDateFrom] = React.useState(() => defaultCashflowWidgetDateRange().dateFrom);
  const [dateTo, setDateTo] = React.useState(() => defaultCashflowWidgetDateRange().dateTo);
  const [bankOptions, setBankOptions] = React.useState<{ id: string; name: string }[]>([]);
  const [assetClassOptions, setAssetClassOptions] = React.useState<Record<string, string>>({});
  const [currentWidgetId, setCurrentWidgetId] = React.useState<number>(widget?.widget_id ?? 0);

  React.useEffect(() => {
    let cancelled = false;
    void (async () => {
      setLoading(true);
      setError(null);
      try {
        const data = await loadDashboardAssetWidgetSettings(tenant);
        if (cancelled) return;
        const banks = data.banks.map((bank) => ({ id: bank.bank_id, name: bank.bank_name }));
        const bankIds = banks.map((bank) => bank.id);
        const assetOptions = data.cashflow_asset_class ?? {};
        const assetCodes = Object.keys(assetOptions);
        const match =
          !isCreate && widget
            ? (data.cashflow_widgets ?? []).find(
                (entry) => Number(entry.widget_id) === Number(widget.widget_id),
              ) ?? null
            : null;
        setBankOptions(banks);
        setAssetClassOptions(assetOptions);
        setCurrentWidgetId(match?.widget_id ?? widget?.widget_id ?? 0);
        setTitle(match?.title?.trim() || match?.name || widget?.name || "");
        setFilters(toFilters(match, bankIds, assetCodes));
        const range = toDateRange(match);
        setDateFrom(range.dateFrom);
        setDateTo(range.dateTo);
      } catch (loadError) {
        if (!cancelled) {
          setError(loadError instanceof Error ? loadError.message : "Cashflow settings could not be loaded.");
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [isCreate, tenant, widget]);

  if (loading) return <p className="text-muted-foreground text-sm">Loading configuration…</p>;
  if (error || !filters) {
    return <p className="text-destructive text-sm">{error ?? "Widget settings are unavailable."}</p>;
  }

  const bankIds = bankOptions.map((bank) => bank.id);
  const assetCodes = Object.keys(assetClassOptions);
  const rangeDays = cashflowWidgetRangeDayCount(dateFrom, dateTo);
  const rangeValid = isCashflowWidgetDateRangeValid(dateFrom, dateTo);
  const rangeError =
    !dateFrom || !dateTo
      ? "Select both start and end dates."
      : rangeDays == null
        ? "End date must be on or after the start date."
        : rangeDays > CASHFLOW_WIDGET_MAX_RANGE_DAYS
          ? `Date range cannot exceed ${CASHFLOW_WIDGET_MAX_RANGE_DAYS} days.`
          : null;

  function handleDateRangeChange(range: DateRange | undefined) {
    if (!range?.from) {
      setDateFrom("");
      setDateTo("");
      return;
    }
    setDateFrom(format(range.from, "yyyy-MM-dd"));
    setDateTo(format(range.to ?? range.from, "yyyy-MM-dd"));
  }

  async function save(operation: "cashflow-create" | "cashflow-save") {
    setBusy(true);
    try {
      if (!rangeValid) {
        toast.error(rangeError ?? `Date range cannot exceed ${CASHFLOW_WIDGET_MAX_RANGE_DAYS} days.`);
        return;
      }

      const selectedBankIds = cashflowServerFilterIds(filters!.bankIds, bankIds);
      const selectedAssetIds = cashflowServerFilterIds(filters!.assetClasses, assetCodes);
      await updateDashboardAssetWidgetSettings(tenant, {
        operation,
        widgetId: operation === "cashflow-create" ? "new" : currentWidgetId,
        title: title.trim(),
        selectedBankIds: selectedBankIds.length > 0 ? selectedBankIds : bankIds,
        selectedAssetIds: selectedAssetIds.length > 0 ? selectedAssetIds : assetCodes,
        eventTypes: filters!.eventTypes,
        structureStatusIds: filters!.structureStatusIds,
        dateFrom,
        dateTo,
      });
      toast.success(operation === "cashflow-create" ? "Cashflow widget added" : "Cashflow widget saved");
      onWidgetsChanged?.();
      onClose();
    } catch (saveError) {
      toast.error(saveError instanceof Error ? saveError.message : "Cashflow widget could not be saved.");
    } finally {
      setBusy(false);
    }
  }

  // Match AA / CH / DIY embedded Configure card chrome.
  return (
    <div className="overflow-hidden rounded-lg border bg-card">
      <div className="space-y-2 p-4">
        <Label>{isCreate ? "Widget title (optional)" : "Widget title"}</Label>
        <Input
          value={title}
          placeholder="Cashflow Calendar"
          onChange={(event) => setTitle(event.target.value)}
        />
      </div>

      <div className="space-y-2 border-t p-4">
        <Label>Date range</Label>
        <p className="text-muted-foreground text-xs">
          Limits calendar data loaded for this widget. Default is 15 days before and after today
          (max {CASHFLOW_WIDGET_MAX_RANGE_DAYS} days).
        </p>
        <DateRangePicker
          value={toPickerRange(dateFrom, dateTo)}
          onChange={handleDateRangeChange}
          placeholder="Select date range"
          align="start"
          className="h-9 w-full justify-start"
        />
        {rangeError ? (
          <p className="text-destructive text-xs">{rangeError}</p>
        ) : rangeDays != null ? (
          <p className="text-muted-foreground text-xs">
            {rangeDays} day{rangeDays === 1 ? "" : "s"} selected
          </p>
        ) : null}
      </div>

      <div className="p-4 pt-0">
        <CashflowFiltersForm
          value={filters}
          onChange={setFilters}
          bankOptions={bankOptions}
          assetClassOptions={assetClassOptions}
          variant="settings"
        />
      </div>

      <div className="flex justify-end border-t p-3">
        <Button
          type="button"
          size="sm"
          className="gap-2"
          disabled={busy || !rangeValid}
          onClick={() => void save(isCreate ? "cashflow-create" : "cashflow-save")}
        >
          <Save className="size-4" />
          {busy ? "Saving…" : isCreate ? "Add Widget" : "Save Widget"}
        </Button>
      </div>
    </div>
  );
}
