"use client";

import * as React from "react";
import { Building2, Coins, Layers, Plus, Save } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";

import { GlassMultiSelectCard } from "@/app/customer/_components/glass-multi-select-card";
import type {
  DashboardAssetWidget,
  DashboardAssetWidgetBank,
  DashboardConsolidatedWidget,
  DashboardDiyWidget,
} from "../../_lib/dashboard-widgets-server-api";

export type Option = { id: string; label: string };
export type DiyDraft = DashboardDiyWidget & { isNew?: boolean };

export function uniqueStrings(values: unknown[]): string[] {
  return [...new Set(values.map((value) => String(value ?? "").trim()).filter(Boolean))];
}

export function optionsFromRecord(values: Record<string, string> | undefined): Option[] {
  return Object.entries(values ?? {})
    .map(([id, label]) => ({ id: String(id).trim(), label: String(label ?? id).trim() }))
    .filter((option) => option.id !== "");
}

export function normalizeBanks(values: DashboardAssetWidgetBank[]): DashboardAssetWidgetBank[] {
  const seen = new Set<string>();
  return values.flatMap((bank) => {
    const id = String(bank.bank_id ?? "").trim();
    if (!id || id === "0" || id === "NaN" || seen.has(id)) return [];
    seen.add(id);
    return [{ bank_id: id, bank_name: String(bank.bank_name ?? "").trim() || id }];
  });
}

export function normalizeSelected(values: unknown[], available: string[], emptyMeansAll = false): string[] {
  const availableSet = new Set(available);
  const normalized = uniqueStrings(values).filter((id) => availableSet.has(id));
  return normalized.length === 0 && emptyMeansAll ? available : normalized;
}

function Checklist({
  title,
  options,
  selected,
  onChange,
  searchPlaceholder,
}: {
  title: string;
  options: Option[];
  selected: string[];
  onChange: (ids: string[]) => void;
  searchPlaceholder: string;
}) {
  const [query, setQuery] = React.useState("");
  const items = React.useMemo(
    () => options.map((option) => ({ id: option.id, label: option.label })),
    [options],
  );
  const icon = React.useMemo(() => {
    const key = title.trim().toLowerCase();
    if (key.includes("bank")) return <Building2 className="size-3.5" />;
    if (key.includes("currenc")) return <Coins className="size-3.5" />;
    if (key.includes("asset") || key.includes("class")) return <Layers className="size-3.5" />;
    return <Building2 className="size-3.5" />;
  }, [title]);

  return (
    <GlassMultiSelectCard
      title={title}
      icon={icon}
      search={query}
      onSearchChange={setQuery}
      items={items}
      selectedIds={selected}
      onToggle={(id, checked) => {
        const next = new Set(selected);
        if (checked) next.add(id);
        else next.delete(id);
        onChange([...next]);
      }}
      onSelectAll={() => onChange(options.map((option) => option.id))}
      onSelectNone={() => onChange([])}
      searchPlaceholder={searchPlaceholder}
      listClassName="max-h-60 min-h-40"
    />
  );
}

export function BankWidgetCard({
  kind,
  widget,
  banks,
  reportTypes,
  busy,
  onChange,
  onSave,
  embedded = false,
  saveLabel,
}: {
  kind: "asset" | "consolidated";
  widget: DashboardAssetWidget | DashboardConsolidatedWidget;
  banks: Option[];
  reportTypes: Record<string, string>;
  busy: boolean;
  onChange: (patch: Partial<DashboardAssetWidget & DashboardConsolidatedWidget>) => void;
  onSave: () => void;
  /** When true, omit outer card chrome for use inside a sheet. */
  embedded?: boolean;
  saveLabel?: string;
}) {
  const isAsset = kind === "asset";
  const title = isAsset
    ? (widget as DashboardAssetWidget).allocation_title
    : (widget as DashboardConsolidatedWidget).title;

  const body = (
    <>
      <div className={`grid gap-4 ${embedded ? "" : "border-b bg-muted/20"} p-4 sm:grid-cols-[minmax(0,1fr)_180px]`}>
        <div className="space-y-2">
          <Label>{isAsset ? "Asset Allocation Title" : "Widget title (optional)"}</Label>
          <Input
            value={title}
            placeholder={isAsset ? "Asset Allocation Title" : "Widget title"}
            onChange={(event) =>
              onChange(isAsset ? { allocation_title: event.target.value } : { title: event.target.value })
            }
          />
        </div>
        <div className="space-y-2">
          <Label>Report type</Label>
          <Select value={widget.report_type} onValueChange={(reportType) => onChange({ report_type: reportType })}>
            <SelectTrigger><SelectValue /></SelectTrigger>
            <SelectContent>
              {Object.entries(reportTypes).map(([value, label]) => (
                <SelectItem key={value} value={value}>{label}</SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      </div>
      <div className="p-4">
        <Checklist
          title="Select Bank"
          options={banks}
          selected={widget.selected_bank_ids}
          onChange={(selected_bank_ids) => onChange({ selected_bank_ids })}
          searchPlaceholder="Search banks…"
        />
      </div>
      <div className={`flex justify-end ${embedded ? "border-t" : "border-t bg-muted/10"} p-3`}>
        <Button type="button" size="sm" className="gap-2" disabled={busy} onClick={onSave}>
          <Save className="size-4" /> {busy ? "Saving…" : (saveLabel ?? "Save Widget")}
        </Button>
      </div>
    </>
  );

  if (embedded) {
    return <div className="overflow-hidden rounded-lg border bg-card">{body}</div>;
  }

  return (
    <section
      id={isAsset ? `aaw-${widget.widget_id}` : `chw-${widget.widget_id}`}
      className="overflow-hidden rounded-xl border bg-card shadow-sm scroll-mt-24"
    >
      {body}
    </section>
  );
}

export function DiyWidgetCard({
  widget,
  banks,
  assets,
  currencies,
  levelOptions,
  busy,
  onChange,
  onSave,
  embedded = false,
}: {
  widget: DiyDraft;
  banks: Option[];
  assets: Option[];
  currencies: Option[];
  levelOptions: Record<string, string>;
  busy: boolean;
  onChange: (patch: Partial<DiyDraft>) => void;
  onSave: () => void;
  embedded?: boolean;
}) {
  const body = (
    <>
      <div className={`space-y-4 ${embedded ? "" : "border-b bg-muted/20"} p-4`}>
        {!embedded ? (
          <div className="flex items-center justify-between gap-3">
            <h3 className="font-semibold">
              {widget.isNew ? "Add New DIY Widget" : widget.title.trim() || widget.name}
            </h3>
            {widget.isNew && <Plus className="size-5 text-muted-foreground" />}
          </div>
        ) : null}
        <div className="grid gap-4 lg:grid-cols-2">
          <div className="space-y-2 lg:col-span-2">
            <Label>{widget.isNew ? "Widget title (must be unique)" : "Widget title (optional)"}</Label>
            <Input
              value={widget.title}
              placeholder={widget.isNew ? "e.g. Holdings by Bank" : "DIY Consolidated Holdings"}
              onChange={(event) => onChange({ title: event.target.value })}
            />
          </div>
          <div className="space-y-2">
            <Label>Level 1 Grouping</Label>
            <Select
              value={widget.level1}
              onValueChange={(level1) =>
                onChange({
                  level1,
                  ...(level1 === widget.level2
                    ? {
                        level2:
                          Object.keys(levelOptions).find((key) => key !== level1) ??
                          widget.level2,
                      }
                    : {}),
                })
              }
            >
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                {Object.entries(levelOptions).map(([value, label]) => (
                  <SelectItem key={value} value={value}>{label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label>Level 2 Grouping</Label>
            <Select
              value={widget.level2}
              onValueChange={(level2) =>
                onChange({
                  level2,
                  ...(level2 === widget.level1
                    ? {
                        level1:
                          Object.keys(levelOptions).find((key) => key !== level2) ??
                          widget.level1,
                      }
                    : {}),
                })
              }
            >
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                {Object.entries(levelOptions).map(([value, label]) => (
                  <SelectItem key={value} value={value} disabled={value === widget.level1}>
                    {label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>
        <div className="flex flex-wrap items-end gap-6">
          <div className="space-y-2">
            <Label>Sort Order</Label>
            <div className="flex gap-4 text-sm">
              {(["desc", "asc"] as const).map((sort) => (
                <label key={sort} className="flex cursor-pointer items-center gap-2">
                  <input
                    type="radio"
                    name={`diy-sort-${widget.widget_id}-${widget.isNew ? "new" : "edit"}`}
                    checked={widget.sort === sort}
                    onChange={() => onChange({ sort })}
                  />
                  {sort === "desc" ? "Descending" : "Ascending"}
                </label>
              ))}
            </div>
          </div>
        </div>
      </div>

      <div className="grid gap-4 p-4">
        <Checklist
          title="Asset Class"
          options={assets}
          selected={widget.selected_asset_ids}
          onChange={(selected_asset_ids) => onChange({ selected_asset_ids })}
          searchPlaceholder="Search asset classes…"
        />
        <Checklist
          title="Bank"
          options={banks}
          selected={widget.selected_bank_ids}
          onChange={(selected_bank_ids) => onChange({ selected_bank_ids })}
          searchPlaceholder="Search banks…"
        />
        <Checklist
          title="Currency"
          options={currencies}
          selected={widget.selected_currency_ids}
          onChange={(selected_currency_ids) => onChange({ selected_currency_ids })}
          searchPlaceholder="Search currencies…"
        />
      </div>

      <div className={`flex justify-end ${embedded ? "border-t" : "border-t bg-muted/10"} p-3`}>
        <Button type="button" size="sm" className="gap-2" disabled={busy} onClick={onSave}>
          {widget.isNew ? <Plus className="size-4" /> : <Save className="size-4" />}
          {busy ? "Saving…" : widget.isNew ? "Add Widget" : "Save Widget"}
        </Button>
      </div>
    </>
  );

  if (embedded) {
    return <div className="overflow-hidden rounded-lg border bg-card">{body}</div>;
  }

  return (
    <section
      id={widget.isNew ? undefined : `diyw-${widget.widget_id}`}
      className={`overflow-hidden rounded-xl bg-card shadow-sm scroll-mt-24 ${widget.isNew ? "border-2 border-dashed" : "border"}`}
    >
      {body}
    </section>
  );
}
