// web/src/pages/settings/PlansPage.tsx
import {
  useMemo,
  useState,
  useEffect,
  type FormEvent,
  type ReactNode,
} from "react";
import { useDashboard } from "../../hooks/useDashboard";
import SettingsNav from "./_SettingsNav";
import {
  useCreatePlan,
  useUpdatePlan,
  useDeletePlan,
} from "../../hooks/useFixedPlans";
import { Money } from "../../components/ui";
import { useToast } from "../../components/Toast";
import { getTodayInTimezone, dateStringToUTCMidnight, isoToDateString, getBrowserTimezone, formatDateInTimezone } from "../../utils/timezone";

function daysUntil(iso: string, userTimezone: string) {
  const today = getTodayInTimezone(userTimezone);
  const due = isoToDateString(iso, userTimezone);
  const todayDate = new Date(today);
  const dueDate = new Date(due);
  const diffMs = dueDate.getTime() - todayDate.getTime();
  return Math.round(diffMs / (24 * 60 * 60 * 1000));
}

function DueBadge({ dueISO, userTimezone }: { dueISO: string; userTimezone: string }) {
  const d = daysUntil(dueISO, userTimezone);
  if (d < 0)
    return (
      <span
        className="badge"
        style={{ borderColor: "#7f1d1d" }}
      >
        Overdue
      </span>
    );
  if (d <= 7) return <span className="badge">Due in {d}d</span>;
  return (
    <span className="badge" aria-hidden="true">
      On track
    </span>
  );
}

export default function SettingsPlansPage() {
  const { data, isLoading, error, refetch, isFetching } = useDashboard();
  const createM = useCreatePlan();
  const updateM = useUpdatePlan();
  const deleteM = useDeletePlan();
  const { push } = useToast();
  
  // Get user timezone from dashboard data
  const userTimezone = data?.user?.timezone || getBrowserTimezone();

  // Add form state
  const [name, setName] = useState("");
  const [total, setTotal] = useState("");
  const [funded, setFunded] = useState("");
  const [priority, setPriority] = useState("");
  const [due, setDue] = useState(getTodayInTimezone(userTimezone));
  
  // Auto-payment form state
  const [autoPayEnabled, setAutoPayEnabled] = useState(false);
  const [frequency, setFrequency] = useState<"weekly" | "biweekly" | "monthly" | "daily" | "custom">("monthly");
  const [dayOfMonth, setDayOfMonth] = useState(1);
  const [dayOfWeek, setDayOfWeek] = useState(0);
  const [everyNDays, setEveryNDays] = useState(30);
  const [minFundingPercent, setMinFundingPercent] = useState(100);

  const totals = useMemo(() => {
    if (!data) return { funded: 0, total: 0, remaining: 0 };
    const funded = data.fixedPlans.reduce(
      (s, p) => s + p.fundedCents,
      0,
    );
    const total = data.fixedPlans.reduce(
      (s, p) => s + p.totalCents,
      0,
    );
    return {
      funded,
      total,
      remaining: Math.max(0, total - funded),
    };
  }, [data]);

  const overallPctFunded = useMemo(() => {
    if (!totals.total) return 0;
    return Math.round((totals.funded / totals.total) * 100);
  }, [totals.funded, totals.total]);

  if (isLoading)
    return (
      <div className="card max-w-3xl">
        <SettingsNav />
        <div className="muted">Loading…</div>
      </div>
    );

  if (error || !data) {
    return (
      <div className="card max-w-3xl">
        <SettingsNav />
        <p className="mb-3">Couldn't load fixed expenses.</p>
        <button
          className="btn"
          onClick={() => refetch()}
          disabled={isFetching}
        >
          {isFetching ? "Retrying…" : "Retry"}
        </button>
      </div>
    );
  }

  const onAdd = (e: FormEvent) => {
    e.preventDefault();
    const totalCents = Math.max(
      0,
      Math.round((parseFloat(total || "0")) * 100),
    );
    const fundedCents = Math.max(
      0,
      Math.round((parseFloat(funded || "0")) * 100),
    );
    const paymentSchedule = autoPayEnabled ? {
      frequency,
      ...(frequency === "monthly" ? { dayOfMonth } : {}),
      ...(frequency === "weekly" || frequency === "biweekly" ? { dayOfWeek } : {}),
      ...(frequency === "custom" ? { everyNDays } : {}),
      minFundingPercent,
    } : undefined;
    
    const body = {
      name: name.trim(),
      totalCents,
      fundedCents: Math.min(fundedCents, totalCents),
      priority: Math.max(
        0,
        Math.floor(Number(priority) || 0),
      ),
      dueOn: dateStringToUTCMidnight(due, userTimezone),
      autoPayEnabled,
      paymentSchedule,
    };
    if (!body.name || totalCents <= 0) return;
    createM.mutate(body, {
      onSuccess: () => {
        push("ok", "Plan created");
        setName("");
        setTotal("");
        setFunded("");
        setPriority("");
        setDue(getTodayInTimezone(userTimezone));
        setAutoPayEnabled(false);
        setFrequency("monthly");
        setDayOfMonth(1);
        setDayOfWeek(0);
        setEveryNDays(30);
        setMinFundingPercent(100);
      },
      onError: (err: any) =>
        push("err", err?.message ?? "Create failed"),
    });
  };

  const onEdit = (
    id: string,
    patch: Partial<{
      name: string;
      totalCents: number;
      fundedCents: number;
      priority: number;
      dueOn: string;
    }>,
  ) => {
    if (
      "totalCents" in patch &&
      "fundedCents" in patch &&
      (patch.totalCents ?? 0) < (patch.fundedCents ?? 0)
    ) {
      patch.fundedCents = patch.totalCents;
    }
    updateM.mutate(
      { id, body: patch },
      {
        onSuccess: () => push("ok", "Plan updated"),
        onError: (err: any) =>
          push("err", err?.message ?? "Update failed"),
      },
    );
  };

  const onDelete = (id: string) => {
    deleteM.mutate(id, {
      onSuccess: () => push("ok", "Plan deleted"),
      onError: (err: any) =>
        push("err", err?.message ?? "Delete failed"),
    });
  };

  const addDisabled =
    !name || !total || createM.isPending;

  return (
    <div className="grid gap-4 max-w-5xl">
      <section className="card">
        <SettingsNav />

        {/* Header */}
        <header className="mb-4 space-y-1">
          <h1 className="text-lg font-semibold">
            Fixed expenses
          </h1>
          <p className="text-sm muted">
            Long-term goals and obligations you’re funding over
            time.
          </p>
        </header>

        {/* KPI strip */}
        <div className="grid gap-2 sm:grid-cols-4 mb-4">
          <KpiCard label="Funded">
            <Money cents={totals.funded} />
          </KpiCard>
          <KpiCard label="Total">
            <Money cents={totals.total} />
          </KpiCard>
          <KpiCard label="Remaining">
            <Money cents={totals.remaining} />
          </KpiCard>
          <KpiCard label="Overall progress">
            <span className="text-xl font-semibold">
              {overallPctFunded}%
            </span>
          </KpiCard>
        </div>

        {/* Overall progress bar */}
        <div className="mb-4 space-y-1">
          <div className="row text-xs muted">
            <span>All fixed expenses funded</span>
            <span className="ml-auto">
              {overallPctFunded}% of target
            </span>
          </div>
          <div className="h-2 w-full rounded-full bg-[--color-panel] overflow-hidden">
            <div
              className="h-full bg-[--color-accent]"
              style={{
                width: `${Math.min(100, overallPctFunded)}%`,
              }}
            />
          </div>
        </div>

        {/* Add form */}
        <form
          onSubmit={onAdd}
          className="row gap-2 mb-4 flex-wrap items-end"
        >
          <input
            className="input w-full sm:w-48"
            placeholder="Name"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
          <input
            className="input w-full sm:w-28"
            placeholder="Total $"
            type="number"
            min={0}
            step="0.01"
            value={total}
            onChange={(e) => setTotal(e.target.value)}
          />
          <input
            className="input w-full sm:w-28"
            placeholder="Funded $"
            type="number"
            min={0}
            step="0.01"
            value={funded}
            onChange={(e) => setFunded(e.target.value)}
          />
          <input
            className="input w-full sm:w-24"
            placeholder="Priority"
            type="number"
            min={0}
            value={priority}
            onChange={(e) => setPriority(e.target.value)}
          />
          <input
            className="input w-full sm:w-40"
            type="date"
            value={due}
            onChange={(e) => setDue(e.target.value)}
          />
          <label className="row gap-2 items-center text-sm cursor-pointer px-3 py-2 rounded-lg bg-[--color-panel] w-full sm:w-auto">
            <input
              type="checkbox"
              checked={autoPayEnabled}
              onChange={(e) => setAutoPayEnabled(e.target.checked)}
            />
            <span>Auto-fund</span>
          </label>
          <button className="btn w-full sm:w-auto" disabled={addDisabled}>
            Add
          </button>
        </form>

        {/* Auto-payment configuration */}
        {autoPayEnabled && (
          <div className="card bg-[--color-panel] p-4 mb-4">
            <h4 className="section-title text-sm mb-3">Auto-Fund Schedule</h4>
            <div className="row gap-4 flex-wrap items-end">
              <label className="stack text-sm">
                <span className="muted text-xs">Frequency</span>
                <select
                  className="input w-32"
                  value={frequency}
                  onChange={(e) => setFrequency(e.target.value as any)}
                >
                  <option value="weekly">Weekly</option>
                  <option value="biweekly">Biweekly</option>
                  <option value="monthly">Monthly</option>
                  <option value="daily">Daily</option>
                  <option value="custom">Custom</option>
                </select>
              </label>

              {(frequency === "weekly" || frequency === "biweekly") && (
                <label className="stack text-sm">
                  <span className="muted text-xs">Day of Week</span>
                  <select
                    className="input w-32"
                    value={dayOfWeek}
                    onChange={(e) => setDayOfWeek(Number(e.target.value))}
                  >
                    <option value={0}>Sunday</option>
                    <option value={1}>Monday</option>
                    <option value={2}>Tuesday</option>
                    <option value={3}>Wednesday</option>
                    <option value={4}>Thursday</option>
                    <option value={5}>Friday</option>
                    <option value={6}>Saturday</option>
                  </select>
                </label>
              )}

              {frequency === "monthly" && (
                <label className="stack text-sm">
                  <span className="muted text-xs">Day of Month</span>
                  <input
                    className="input w-24"
                    type="number"
                    min="1"
                    max="31"
                    value={dayOfMonth}
                    onChange={(e) => setDayOfMonth(Number(e.target.value) || 1)}
                  />
                </label>
              )}

              {frequency === "custom" && (
                <label className="stack text-sm">
                  <span className="muted text-xs">Every N Days</span>
                  <input
                    className="input w-24"
                    type="number"
                    min="1"
                    value={everyNDays}
                    onChange={(e) => setEveryNDays(Number(e.target.value) || 30)}
                  />
                </label>
              )}

              <label className="stack text-sm">
                <span className="muted text-xs">Min. Funding %</span>
                <input
                  className="input w-24"
                  type="number"
                  min="0"
                  max="100"
                  value={minFundingPercent}
                  onChange={(e) => setMinFundingPercent(Math.max(0, Math.min(100, Number(e.target.value) || 0)))}
                />
              </label>
            </div>
            <p className="text-xs muted mt-2">
              Automatic payments will only occur if the expense is funded to at least the minimum percentage.
            </p>
          </div>
        )}

        {/* Table */}
        {data.fixedPlans.length === 0 ? (
          <div className="muted text-sm">
            No fixed expenses yet.
          </div>
        ) : (
          <table className="table">
            <thead>
              <tr>
                <th>Name</th>
                <th>Due</th>
                <th>Priority</th>
                <th>Funded</th>
                <th>Total</th>
                <th>Remaining</th>
                <th>Status</th>
                <th>Auto-Pay</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {data.fixedPlans
                .slice()
                .sort(
                  (a, b) =>
                    a.priority - b.priority ||
                    new Date(a.dueOn).getTime() -
                      new Date(b.dueOn).getTime(),
                )
                .map((p) => {
                  const remaining = Math.max(
                    0,
                    p.totalCents - p.fundedCents,
                  );
                  const pctFunded = p.totalCents
                    ? Math.round(
                        (p.fundedCents / p.totalCents) * 100,
                      )
                    : 0;
                  return (
                    <tr key={p.id}>
                      <td className="rounded-l-[--radius-xl] px-3 py-2">
                        <InlineEditText
                          value={p.name}
                          onChange={(v) =>
                            onEdit(p.id, { name: v })
                          }
                        />
                      </td>
                      <td className="px-3 py-2">
                        <InlineEditDate
                          value={p.dueOn}
                          timezone={userTimezone}
                          onChange={(iso) =>
                            onEdit(p.id, { dueOn: iso })
                          }
                        />
                      </td>
                      <td className="px-3 py-2">
                        <InlineEditNumber
                          value={p.priority}
                          min={0}
                          onChange={(n) =>
                            onEdit(p.id, { priority: n })
                          }
                        />
                      </td>
                      <td className="px-3 py-2">
                        <div className="space-y-1">
                          <InlineEditMoney
                            valueCents={p.fundedCents}
                            onChange={(cents) =>
                              onEdit(p.id, {
                                fundedCents: Math.max(
                                  0,
                                  Math.min(cents, p.totalCents),
                                ),
                              })
                            }
                          />
                          <div className="row text-xs muted">
                            <span>{pctFunded}% funded</span>
                          </div>
                        </div>
                      </td>
                      <td className="px-3 py-2">
                        <div className="space-y-1">
                          <InlineEditMoney
                            valueCents={p.totalCents}
                            onChange={(cents) =>
                              onEdit(p.id, {
                                totalCents: Math.max(cents, 0),
                                fundedCents: Math.min(
                                  p.fundedCents,
                                  cents,
                                ),
                              })
                            }
                          />
                          <FundingBar
                            pct={pctFunded}
                          />
                        </div>
                      </td>
                      <td className="px-3 py-2">
                        <Money cents={remaining} />
                      </td>
                      <td className="px-3 py-2">
                        <DueBadge dueISO={p.dueOn} userTimezone={userTimezone} />
                      </td>
                      <td className="px-3 py-2">
                        <div className="flex items-center space-x-2">
                          <span className={`text-xs px-2 py-1 rounded ${
                            p.autoPayEnabled 
                              ? 'bg-green-100 text-green-800' 
                              : 'bg-gray-100 text-gray-600'
                          }`}>
                            {p.autoPayEnabled ? 'Enabled' : 'Disabled'}
                          </span>
                          {p.autoPayEnabled && p.paymentSchedule && (
                            <span className="text-xs text-gray-500">
                              {p.paymentSchedule.frequency === 'custom' 
                                ? `Every ${p.paymentSchedule.customDays} days`
                                : p.paymentSchedule.frequency.charAt(0).toUpperCase() + p.paymentSchedule.frequency.slice(1)
                              }
                            </span>
                          )}
                        </div>
                      </td>
                      <td className="rounded-r-[--radius-xl] px-3 py-2">
                        <button
                          className="btn"
                          type="button"
                          onClick={() => onDelete(p.id)}
                          disabled={deleteM.isPending}
                        >
                          Delete
                        </button>
                      </td>
                    </tr>
                  );
                })}
            </tbody>
          </table>
        )}
      </section>
    </div>
  );
}

/* --- Small presentational helpers --- */

function KpiCard({
  label,
  children,
}: {
  label: string;
  children: ReactNode;
}) {
  return (
    <div className="card kpi">
      <h3>{label}</h3>
      <div className="val">{children}</div>
    </div>
  );
}

function FundingBar({ pct }: { pct: number }) {
  const clamped = Math.min(100, Math.max(0, pct));
  return (
    <div className="h-1.5 w-full rounded-full bg-[--color-panel] overflow-hidden">
      <div
        className="h-full bg-[--color-accent]"
        style={{ width: `${clamped}%` }}
      />
    </div>
  );
}

/* --- Inline editors (same behavior, slightly nicer UX) --- */

function InlineEditText({
  value,
  onChange,
}: {
  value: string;
  onChange: (v: string) => void;
}) {
  const [editing, setEditing] = useState(false);
  const [v, setV] = useState(value);
  useEffect(() => setV(value), [value]);
  const commit = () => {
    const t = v.trim();
    if (t && t !== value) onChange(t);
    setEditing(false);
  };
  return editing ? (
    <input
      className="input"
      value={v}
      onChange={(e) => setV(e.target.value)}
      onBlur={commit}
      onKeyDown={(e) => e.key === "Enter" && commit()}
      autoFocus
    />
  ) : (
    <button
      type="button"
      className="link inline-flex items-center gap-1"
      onClick={() => setEditing(true)}
    >
      <span>{value}</span>
      <span className="text-[10px] opacity-60">Edit</span>
    </button>
  );
}

function InlineEditNumber({
  value,
  onChange,
  min = 0,
  max = Number.MAX_SAFE_INTEGER,
}: {
  value: number;
  onChange: (v: number) => void;
  min?: number;
  max?: number;
}) {
  const [editing, setEditing] = useState(false);
  const [v, setV] = useState(String(value));
  useEffect(() => setV(String(value)), [value]);
  const commit = () => {
    const n = Math.max(
      min,
      Math.min(max, Math.floor(Number(v) || 0)),
    );
    if (n !== value) onChange(n);
    setEditing(false);
  };
  return editing ? (
    <input
      className="input w-24 text-right"
      value={v}
      onChange={(e) => setV(e.target.value)}
      onBlur={commit}
      onKeyDown={(e) => e.key === "Enter" && commit()}
      autoFocus
    />
  ) : (
    <button
      type="button"
      className="link"
      onClick={() => setEditing(true)}
    >
      {value}
    </button>
  );
}

function InlineEditMoney({
  valueCents,
  onChange,
}: {
  valueCents: number;
  onChange: (cents: number) => void;
}) {
  const [editing, setEditing] = useState(false);
  const [v, setV] = useState((valueCents / 100).toFixed(2));
  useEffect(
    () => setV((valueCents / 100).toFixed(2)),
    [valueCents],
  );
  const commit = () => {
    const cents = Math.max(
      0,
      Math.round((parseFloat(v || "0")) * 100),
    );
    if (cents !== valueCents) onChange(cents);
    setEditing(false);
  };
  return editing ? (
    <input
      className="input w-28 text-right font-mono"
      type="number"
      step="0.01"
      min={0}
      value={v}
      onChange={(e) => setV(e.target.value)}
      onBlur={commit}
      onKeyDown={(e) => e.key === "Enter" && commit()}
      autoFocus
    />
  ) : (
    <button
      type="button"
      className="link font-mono"
      onClick={() => setEditing(true)}
    >
      {(valueCents / 100).toFixed(2)}
    </button>
  );
}

function InlineEditDate({
  value,
  onChange,
  timezone,
}: {
  value: string;
  onChange: (iso: string) => void;
  timezone: string;
}) {
  const [editing, setEditing] = useState(false);
  const [v, setV] = useState(
    isoToDateString(value, timezone),
  );
  useEffect(
    () =>
      setV(
        isoToDateString(value, timezone),
      ),
    [value, timezone],
  );
  const commit = () => {
    const iso = dateStringToUTCMidnight(v, timezone);
    if (iso !== value) onChange(iso);
    setEditing(false);
  };
  return editing ? (
    <input
      className="input w-40"
      type="date"
      value={v}
      onChange={(e) => setV(e.target.value)}
      onBlur={commit}
      onKeyDown={(e) => e.key === "Enter" && commit()}
      autoFocus
    />
  ) : (
    <button
      type="button"
      className="link"
      onClick={() => setEditing(true)}
    >
      {formatDateInTimezone(value, timezone)}
    </button>
  );
}
