'use client';

import {
  CollapsibleSection,
  FilterField,
  FilterHint,
  FilterInput,
  FilterVisibilityPicker,
  SampleSizeBanner,
  SectionLabel,
  StringMultiSelect,
  TriStateToggle,
  useFilterVisibility,
  type DynamicFilterValue,
  type FilterDef,
} from './_shared';
import { DateRangeInput, type DateRangeValue } from './DateRangeInput';
import { SchemaBrowser } from './SchemaBrowser';
import type { ColumnInfo } from '@/lib/crm/cumas-client';

export interface OrderFilterState {
  server: {
    invoiceNumber?: string;
    email?: string;
    clientName?: string;
    regDatetimeAfter?: string;
    regDatetimeBefore?: string;
  };
  client: {
    productContains?: string;
    productIn?: string[];
    hasEvbs?: boolean;
    totalMin?: number;
    totalMax?: number;
  };
}

export const DEFAULT_ORDER_STATE: OrderFilterState = {
  server: {},
  client: {},
};

const ORDER_FILTER_DEFS: FilterDef[] = [
  { key: 'email', label: 'Email', group: 'API-Filter', defaultVisible: true },
  { key: 'clientName', label: 'Kundenname', group: 'API-Filter' },
  { key: 'invoiceNumber', label: 'Rechnungs-Nr', group: 'API-Filter' },
  { key: 'regDatetime', label: 'Bestelldatum', group: 'API-Filter' },
  { key: 'productIn', label: 'Produkt (Multi-Select)', group: 'Produkt & Status', defaultVisible: true },
  { key: 'productContains', label: 'Produkt-Substring', group: 'Produkt & Status' },
  { key: 'advanced', label: 'Erweitert (collapsible)', group: 'Erweitert', defaultVisible: true },
  { key: 'hint', label: 'Info-Hinweis', group: 'Erweitert' },
  { key: 'schemaBrowser', label: 'Schema-Browser (ad-hoc)', group: 'Erweitert' },
];

export function OrderFilters({
  state,
  onChange,
  facets,
  facetCounts,
  schemaColumns,
  dynamicFilters,
  onDynamicFiltersChange,
  totalSampled,
  onLoadMoreSamples,
  loadingMoreSamples,
}: {
  state: OrderFilterState;
  onChange: (next: OrderFilterState) => void;
  facets: { orderProducts: string[] };
  facetCounts?: { orderProducts?: Record<string, number> };
  /** Optional: alle verfügbaren Spalten aus dem Schema-Endpoint (für SchemaBrowser). */
  schemaColumns?: ColumnInfo[];
  dynamicFilters?: DynamicFilterValue[];
  onDynamicFiltersChange?: (next: DynamicFilterValue[]) => void;
  totalSampled?: number;
  onLoadMoreSamples?: () => void;
  loadingMoreSamples?: boolean;
}) {
  const setServer = (patch: Partial<OrderFilterState['server']>) =>
    onChange({ ...state, server: { ...state.server, ...patch } });
  const setClient = (patch: Partial<OrderFilterState['client']>) =>
    onChange({ ...state, client: { ...state.client, ...patch } });

  const floatField = (raw: string): number | undefined => {
    if (!raw) return undefined;
    const n = parseFloat(raw);
    return isNaN(n) ? undefined : n;
  };

  const dateRange: DateRangeValue = {
    after: state.server.regDatetimeAfter,
    before: state.server.regDatetimeBefore,
  };

  const { isVisible } = useFilterVisibility('orders', ORDER_FILTER_DEFS);
  const apiVisible = isVisible('email') || isVisible('clientName') || isVisible('invoiceNumber') || isVisible('regDatetime');
  const productVisible = isVisible('productIn') || isVisible('productContains');

  return (
    <div className="space-y-1">
      <FilterVisibilityPicker tabKey="orders" defs={ORDER_FILTER_DEFS} />

      {totalSampled !== undefined && onLoadMoreSamples && (
        <SampleSizeBanner
          totalSampled={totalSampled}
          loading={loadingMoreSamples ?? false}
          onLoadMore={onLoadMoreSamples}
        />
      )}

      {apiVisible && <SectionLabel>API-Filter (Server-side)</SectionLabel>}
      {isVisible('email') && (
        <FilterField label="Email">
          <FilterInput
            value={state.server.email ?? ''}
            onChange={(v) => setServer({ email: v || undefined })}
            placeholder="exakt o. Substring"
          />
        </FilterField>
      )}
      {isVisible('clientName') && (
        <FilterField label="Kundenname">
          <FilterInput
            value={state.server.clientName ?? ''}
            onChange={(v) => setServer({ clientName: v || undefined })}
            placeholder="z.B. Mustermann"
          />
        </FilterField>
      )}
      {isVisible('invoiceNumber') && (
        <FilterField label="Rechnungs-Nr">
          <FilterInput
            value={state.server.invoiceNumber ?? ''}
            onChange={(v) => setServer({ invoiceNumber: v || undefined })}
            placeholder="z.B. O 142605/25"
          />
        </FilterField>
      )}
      {isVisible('regDatetime') && (
        <FilterField label="Bestelldatum">
          <DateRangeInput
            value={dateRange}
            onChange={(v) => setServer({ regDatetimeAfter: v.after, regDatetimeBefore: v.before })}
          />
        </FilterField>
      )}

      {productVisible && <SectionLabel>Produkt & Status (Client-side)</SectionLabel>}
      {isVisible('productIn') && (
        <FilterField
          label="Produkt"
          hint="Multi-Select · seltene Produkte manuell hinzufügen"
          layout="stacked"
        >
          <StringMultiSelect
            options={facets.orderProducts}
            value={state.client.productIn ?? []}
            onChange={(v) => {
              // Wir mappen Multi-Select auf productContains, falls genau 1 ausgewählt; sonst eigener Filter.
              // Da der API-Client nur productContains kennt, kombinieren wir hier per OR im Browser.
              setClient({ productIn: v.length ? v : undefined });
            }}
            counts={facetCounts?.orderProducts}
            emptyLabel="Lade Werte..."
            allowCustomAdd
            customAddPlaceholder="z.B. KZK, KZKA…"
          />
        </FilterField>
      )}
      {isVisible('productContains') && (
        <FilterField label="Produkt-Substring (alternativ)">
          <FilterInput
            value={state.client.productContains ?? ''}
            onChange={(v) => setClient({ productContains: v || undefined })}
            placeholder="z.B. KZK"
          />
        </FilterField>
      )}

      {isVisible('advanced') && (
        <CollapsibleSection title="Erweitert">
          <TriStateToggle
            label="Hat verknüpfte EVBs"
            value={state.client.hasEvbs}
            onChange={(v) => setClient({ hasEvbs: v })}
          />
          <div className="grid grid-cols-2 gap-1.5">
            <FilterField label="Total Min (€)" layout="stacked">
              <FilterInput
                type="number"
                value={state.client.totalMin?.toString() ?? ''}
                onChange={(v) => setClient({ totalMin: floatField(v) })}
                placeholder="z.B. 20"
              />
            </FilterField>
            <FilterField label="Total Max (€)" layout="stacked">
              <FilterInput
                type="number"
                value={state.client.totalMax?.toString() ?? ''}
                onChange={(v) => setClient({ totalMax: floatField(v) })}
                placeholder="z.B. 100"
              />
            </FilterField>
          </div>
        </CollapsibleSection>
      )}

      {isVisible('hint') && (
        <FilterHint>
          Bestellungen aus dem Privatkundenshop (~52.671 Records). Empfänger werden direkt aus der Bestellung
          (email + client_name) gebildet, dedupliziert auf Email.
        </FilterHint>
      )}

      {/* Schema-Browser für ad-hoc Filter auf zusätzliche Order-Spalten. */}
      {isVisible('schemaBrowser') && schemaColumns && onDynamicFiltersChange && (
        <SchemaBrowser
          columns={schemaColumns}
          excludeColumns={[
            'email', 'client_name', 'rechnr', 'reg_datetime', 'product',
            'gesamt', 'has_evbs',
          ]}
          value={dynamicFilters ?? []}
          onChange={onDynamicFiltersChange}
        />
      )}
    </div>
  );
}

export function serializeOrderFilter(s: OrderFilterState) {
  // productIn → wenn genau 1 Wert: in productContains gemappt; sonst lokal nachfiltern via productContains
  // (für Multi-Werte fallback: wir senden productContains nur, wenn explizit gesetzt; hasEvbs/total bleiben).
  const client: OrderFilterState['client'] & { productContains?: string } = { ...s.client };
  if (s.client.productIn?.length === 1 && !s.client.productContains) {
    client.productContains = s.client.productIn[0];
  }
  return { server: s.server, client };
}
