import * as React from "react";
import { useState } from "react";
import { Pencil, Plus, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import { Field, FieldLabel } from "@/components/ui/field";
import { LoanOptionGroup } from "@/components/ui/loan-option-group";
import { InterestRateInput } from "@/components/ui/interest-rate-input";
import {
  AddressAutocomplete,
  CurrencyInputWithSlider,
  OwnershipSplit,
  type AddressOption,
  type OwnershipOwner,
} from "@/components/ui/form-primitives";
import { FREQUENCY_OPTIONS, YES_NO_OPTIONS } from "@/lib/loan-constants";
import { formatCurrency } from "@/lib/format-currency";

// ─── Types ──────────────────────────────────────────────────────────────────

export type AssetOwner = OwnershipOwner;

export type AssetItem = {
  id: string;
  /** Summary label shown in the collapsed row (address for a property). */
  description: string;
  estimatedValue: number;
  /** Secondary line in the collapsed row (e.g. "Owner Occupied"). */
  subLabel?: string;
  // ── Property / asset detail fields (edited via the inline form) ──
  address?: string;
  category?: "owner-occupier" | "investment" | "";
  rentalIncome?: number;
  rentalIncomeFrequency?: "monthly" | "weekly";
  hasMortgage?: boolean;
  mortgageOwing?: number;
  mortgageOriginal?: number;
  mortgageRepayment?: number;
  mortgageRepaymentFrequency?: "monthly" | "weekly";
  mortgageInterestRate?: number;
  owners?: AssetOwner[];
};

export type AssetGroup = {
  assetType: string;
  label: string;
  items: AssetItem[];
};

export type AssetAccordionProps = {
  groups: AssetGroup[];
  /** Which group values are expanded (controlled). */
  openGroups?: string[];
  onToggleGroup?: (assetType: string) => void;
  /** Create/update an item. `item.id === ""` means a newly-added item. */
  onSaveItem?: (assetType: string, item: AssetItem) => void;
  onDeleteItem?: (assetType: string, itemId: string) => void;
  /** Applicants used to seed the ownership split on a new item. */
  owners?: AssetOwner[];
  /** Address suggestions for the property autocomplete. */
  addressSuggestions?: AddressOption[];
  /** Accessible label for the accordion landmark region. */
  "aria-label"?: string;
  className?: string;
};

const NEW_ITEM_ID = "__new__";

const CATEGORY_OPTIONS = [
  { value: "owner-occupier", label: "Owner Occupier" },
  { value: "investment", label: "Investment" },
];

function blankAssetItem(assetType: string, owners: AssetOwner[]): AssetItem {
  return {
    id: "",
    description: "",
    estimatedValue: assetType === "property" ? 600_000 : 0,
    address: "",
    category: "",
    rentalIncome: 0,
    rentalIncomeFrequency: "monthly",
    hasMortgage: false,
    mortgageOwing: 0,
    mortgageOriginal: 0,
    mortgageRepayment: 0,
    mortgageRepaymentFrequency: "monthly",
    mortgageInterestRate: 0,
    owners,
  };
}

// ─── Component ──────────────────────────────────────────────────────────────

export function AssetAccordion({
  groups,
  openGroups,
  onToggleGroup,
  onSaveItem,
  onDeleteItem,
  owners = [{ id: "main", name: "Main Applicant", share: 100 }],
  addressSuggestions,
  "aria-label": ariaLabel = "Asset list",
  className,
}: AssetAccordionProps) {
  // Which item is currently open in the inline edit form (or a new draft).
  const [editing, setEditing] = useState<{
    assetType: string;
    itemId: string;
  } | null>(null);
  const [draft, setDraft] = useState<AssetItem | null>(null);

  const totalAssets = groups
    .flatMap((g) => g.items)
    .reduce((sum, item) => sum + item.estimatedValue, 0);

  const startAdd = (assetType: string) => {
    setDraft(blankAssetItem(assetType, owners));
    setEditing({ assetType, itemId: NEW_ITEM_ID });
  };
  const startEdit = (assetType: string, item: AssetItem) => {
    // Pre-fill the form from the row summary for items that predate the
    // detailed form (e.g. seed mock data only has description + value).
    setDraft({
      ...item,
      address:
        item.address ?? (assetType === "property" ? item.description : ""),
      category: item.category ?? "",
      owners: item.owners ?? owners,
    });
    setEditing({ assetType, itemId: item.id });
  };
  const cancel = () => {
    setEditing(null);
    setDraft(null);
  };
  const save = (assetType: string, item: AssetItem) => {
    onSaveItem?.(assetType, item);
    cancel();
  };

  return (
    <div className={cn("flex flex-col gap-4 font-sans", className)}>
      <div className="flex items-center justify-between pb-2">
        <h3 className="text-h3 text-foreground">Assets</h3>
        <span className="text-label-medium text-foreground">
          Total: {formatCurrency(totalAssets)}
        </span>
      </div>

      <Accordion
        multiple
        aria-label={ariaLabel}
        value={openGroups}
        onValueChange={(vals) => {
          const prev = new Set(openGroups ?? []);
          const next = new Set(vals as string[]);
          for (const v of next) {
            if (!prev.has(v)) onToggleGroup?.(v);
          }
          for (const v of prev) {
            if (!next.has(v)) onToggleGroup?.(v);
          }
        }}
      >
        {groups.map((group) => {
          const isAdding =
            editing?.assetType === group.assetType &&
            editing.itemId === NEW_ITEM_ID;
          // One form element per group — at most one is shown at a time
          // (editing an existing item, or the new draft).
          const form =
            editing?.assetType === group.assetType && draft ? (
              <AssetItemForm
                assetType={group.assetType}
                initial={draft}
                addressSuggestions={addressSuggestions}
                onSave={(updated) => save(group.assetType, updated)}
                onCancel={cancel}
              />
            ) : null;
          return (
            <AccordionItem key={group.assetType} value={group.assetType}>
              <AccordionTrigger>
                <div className="flex w-full items-center justify-between pr-2">
                  <span>{group.label}</span>
                  <span className="text-caption text-muted-foreground">
                    {group.items.length}{" "}
                    {group.items.length === 1 ? "item" : "items"} ·{" "}
                    {formatCurrency(
                      group.items.reduce((s, i) => s + i.estimatedValue, 0),
                    )}
                  </span>
                </div>
              </AccordionTrigger>
              <AccordionContent>
                <div className="flex flex-col gap-2 pb-2">
                  {group.items.length === 0 && !isAdding ? (
                    <p className="text-caption text-muted-foreground">
                      No {group.label.toLowerCase()} added yet.
                    </p>
                  ) : (
                    group.items.map((item) =>
                      editing?.assetType === group.assetType &&
                      editing.itemId === item.id &&
                      form ? (
                        React.cloneElement(form, { key: item.id })
                      ) : (
                        <AssetItemRow
                          key={item.id}
                          item={item}
                          onEdit={() => startEdit(group.assetType, item)}
                          onDelete={() =>
                            onDeleteItem?.(group.assetType, item.id)
                          }
                        />
                      ),
                    )
                  )}

                  {isAdding && form}

                  {!isAdding && (
                    <Button
                      variant="secondary"
                      size="sm"
                      className="mt-1 self-start text-body-small"
                      onClick={() => startAdd(group.assetType)}
                    >
                      <Plus className="size-4" />
                      Add {group.label}
                    </Button>
                  )}
                </div>
              </AccordionContent>
            </AccordionItem>
          );
        })}
      </Accordion>
    </div>
  );
}

// ─── Collapsed summary row ──────────────────────────────────────────────────

function AssetItemRow({
  item,
  onEdit,
  onDelete,
}: {
  item: AssetItem;
  onEdit?: () => void;
  onDelete?: () => void;
}) {
  return (
    <div className="flex items-center justify-between border border-border p-3">
      <div className="flex flex-col gap-0.5">
        <span className="text-label-medium text-foreground">
          {item.description || "Untitled asset"}
        </span>
        {item.subLabel && (
          <span className="text-caption text-muted-foreground">
            {item.subLabel}
          </span>
        )}
        <span className="text-body-small text-foreground">
          {formatCurrency(item.estimatedValue)}
        </span>
      </div>
      <div className="flex items-center gap-1">
        <Button
          variant="ghost"
          size="icon-sm"
          aria-label={`Edit ${item.description}`}
          onClick={onEdit}
        >
          <Pencil className="size-4" />
        </Button>
        <Button
          variant="ghost"
          size="icon-sm"
          className="text-destructive hover:text-destructive"
          aria-label={`Delete ${item.description}`}
          onClick={onDelete}
        >
          <Trash2 className="size-4" />
        </Button>
      </div>
    </div>
  );
}

// ─── Inline add / edit form ─────────────────────────────────────────────────

function AssetItemForm({
  assetType,
  initial,
  addressSuggestions,
  onSave,
  onCancel,
}: {
  assetType: string;
  initial: AssetItem;
  addressSuggestions?: AddressOption[];
  onSave: (item: AssetItem) => void;
  onCancel: () => void;
}) {
  const [item, setItem] = useState<AssetItem>(initial);
  const set = (patch: Partial<AssetItem>) =>
    setItem((prev) => ({ ...prev, ...patch }));

  const isProperty = assetType === "property";
  const estimateLabel = isProperty ? "Property estimate" : "Value estimate";

  const canSave = isProperty
    ? Boolean(item.address && item.category) && item.estimatedValue > 0
    : item.estimatedValue > 0;

  const handleSave = () => {
    // Keep the collapsed-row summary in sync with the form values.
    const subLabel = isProperty
      ? item.category === "investment"
        ? "Investment"
        : item.category === "owner-occupier"
          ? "Owner Occupied"
          : undefined
      : item.subLabel;
    onSave({
      ...item,
      description: isProperty
        ? item.address || item.description
        : item.description,
      subLabel,
    });
  };

  return (
    <div className="flex flex-col gap-5 border border-border p-4">
      {isProperty && (
        <Field>
          <FieldLabel>Property Address</FieldLabel>
          <AddressAutocomplete
            value={item.address ?? ""}
            suggestions={addressSuggestions}
            onValueChange={(v) => set({ address: v })}
            onSelect={(opt) => set({ address: opt.label })}
          />
        </Field>
      )}

      {isProperty && (
        <Field>
          <FieldLabel>How is the property used?</FieldLabel>
          <LoanOptionGroup
            options={CATEGORY_OPTIONS}
            value={item.category || undefined}
            onChange={(v) => set({ category: v as AssetItem["category"] })}
          />
        </Field>
      )}

      {isProperty && item.category === "investment" && (
        <Field>
          <FieldLabel>How much is your rental income?</FieldLabel>
          <div className="flex flex-col gap-2">
            <CurrencyInputWithSlider
              value={item.rentalIncome ?? 0}
              min={0}
              max={15_000}
              step={100}
              onValueChange={(n) => set({ rentalIncome: n })}
            />
            <LoanOptionGroup
              options={FREQUENCY_OPTIONS}
              value={item.rentalIncomeFrequency ?? "monthly"}
              onChange={(v) =>
                set({
                  rentalIncomeFrequency:
                    v as AssetItem["rentalIncomeFrequency"],
                })
              }
            />
          </div>
        </Field>
      )}

      <Field>
        <FieldLabel>{estimateLabel}</FieldLabel>
        <CurrencyInputWithSlider
          value={item.estimatedValue}
          min={0}
          max={3_000_000}
          step={10_000}
          onValueChange={(n) => set({ estimatedValue: n })}
        />
      </Field>

      {isProperty && (
        <Field>
          <FieldLabel>Does this property have a mortgage?</FieldLabel>
          <LoanOptionGroup
            options={YES_NO_OPTIONS}
            value={
              item.hasMortgage == null
                ? undefined
                : item.hasMortgage
                  ? "yes"
                  : "no"
            }
            onChange={(v) => set({ hasMortgage: v === "yes" })}
          />
        </Field>
      )}

      {isProperty && item.hasMortgage && (
        <div className="flex flex-col gap-4 border-l-2 border-border pl-4">
          <Field>
            <FieldLabel>Current amount owing</FieldLabel>
            <CurrencyInputWithSlider
              value={item.mortgageOwing ?? 0}
              min={0}
              max={3_000_000}
              step={10_000}
              onValueChange={(n) => set({ mortgageOwing: n })}
            />
          </Field>
          <Field>
            <FieldLabel>Original loan amount</FieldLabel>
            <CurrencyInputWithSlider
              value={item.mortgageOriginal ?? 0}
              min={0}
              max={3_000_000}
              step={10_000}
              onValueChange={(n) => set({ mortgageOriginal: n })}
            />
          </Field>
          <Field>
            <FieldLabel>How much are your loan repayments?</FieldLabel>
            <div className="flex flex-col gap-2">
              <CurrencyInputWithSlider
                value={item.mortgageRepayment ?? 0}
                min={0}
                max={20_000}
                step={100}
                onValueChange={(n) => set({ mortgageRepayment: n })}
              />
              <LoanOptionGroup
                options={FREQUENCY_OPTIONS}
                value={item.mortgageRepaymentFrequency ?? "monthly"}
                onChange={(v) =>
                  set({
                    mortgageRepaymentFrequency:
                      v as AssetItem["mortgageRepaymentFrequency"],
                  })
                }
              />
            </div>
          </Field>
          <Field>
            <FieldLabel>Interest rate</FieldLabel>
            <InterestRateInput
              value={item.mortgageInterestRate ?? 0}
              max={20}
              onChange={(n) => set({ mortgageInterestRate: n })}
            />
          </Field>
        </div>
      )}

      {item.owners && item.owners.length > 1 && (
        <Field>
          <FieldLabel>Ownership</FieldLabel>
          <OwnershipSplit
            owners={item.owners}
            onOwnersChange={(ow) => set({ owners: ow })}
          />
        </Field>
      )}

      <div className="flex items-center gap-2">
        <Button size="sm" disabled={!canSave} onClick={handleSave}>
          Save &amp; Collapse
        </Button>
        <Button size="sm" variant="ghost" onClick={onCancel}>
          Cancel
        </Button>
      </div>
    </div>
  );
}
