import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { api, WRITER_ROLES, type EntityType } from "../api";
import { useAuth } from "../context/AuthContext";
import { formatMoney, formatGainLoss } from "../format";

interface EntityRow {
  id: number;
  name: string;
  type: string;
  vintage_year: number | null;
  fund_size_cents: number | null;
  status: string;
  committedCents: number;
  investedCents: number;
  lastValueCents: number;
}

const TYPE_LABELS: Record<string, string> = {
  fund: "Fund",
  spv: "SPV",
  gp: "GP",
  mgmt_co: "Mgmt Co",
  carry: "Carry Vehicle",
};

export default function EntitiesList() {
  const { user } = useAuth();
  const [entities, setEntities] = useState<EntityRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [showForm, setShowForm] = useState(false);

  const isWriter = user && WRITER_ROLES.includes(user.role);

  useEffect(() => {
    loadData();
  }, []);

  async function loadData() {
    setLoading(true);
    try {
      const rollup = await api.listEntityRollup();
      setEntities(
        rollup.map((r) => ({
          id: r.id,
          name: r.name,
          type: r.type,
          vintage_year: r.vintage_year,
          fund_size_cents: r.fund_size_cents,
          status: r.status,
          committedCents: r.committed_cents,
          investedCents: r.invested_cents,
          lastValueCents: r.last_signed_value_cents,
        })),
      );
    } finally {
      setLoading(false);
    }
  }

  if (loading) {
    return <div className="text-gray-500 text-sm">Loading...</div>;
  }

  const funds = entities.filter((e) => e.type === "fund" || e.type === "spv");
  const gps = entities.filter(
    (e) => e.type === "gp" || e.type === "mgmt_co" || e.type === "carry",
  );

  return (
    <div className="space-y-8">
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-semibold text-gray-900">Entities</h1>
        {isWriter && (
          <button
            onClick={() => setShowForm(true)}
            className="px-4 py-2 bg-brand-900 text-white text-sm rounded hover:bg-brand-800"
          >
            Add Entity
          </button>
        )}
      </div>

      {showForm && (
        <AddEntityForm
          onClose={() => setShowForm(false)}
          onCreated={() => {
            setShowForm(false);
            loadData();
          }}
        />
      )}

      <EntityTable title="Funds and SPVs" rows={funds} />
      <EntityTable title="Management Entities" rows={gps} />
    </div>
  );
}

function AddEntityForm({
  onClose,
  onCreated,
}: {
  onClose: () => void;
  onCreated: () => void;
}) {
  const [name, setName] = useState("");
  const [type, setType] = useState<EntityType>("fund");
  const [vintageYear, setVintageYear] = useState("");
  const [fundSizeDollars, setFundSizeDollars] = useState("");
  const [error, setError] = useState("");
  const [saving, setSaving] = useState(false);

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!name.trim()) {
      setError("Name is required.");
      return;
    }
    setError("");
    setSaving(true);
    try {
      const data: any = { name: name.trim(), type };
      if (vintageYear) {
        const vy = parseInt(vintageYear);
        if (isNaN(vy)) {
          setError("Vintage year must be a number.");
          setSaving(false);
          return;
        }
        data.vintage_year = vy;
      }
      if (fundSizeDollars) {
        const dollars = parseFloat(fundSizeDollars.replace(/[,$]/g, ""));
        if (isNaN(dollars)) {
          setError("Fund size must be a number.");
          setSaving(false);
          return;
        }
        data.fund_size_cents = Math.round(dollars * 100);
      }
      await api.createEntity(data);
      onCreated();
    } catch (err: any) {
      setError(err.message || "Failed to create entity");
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="bg-white border border-gray-200 rounded-lg p-6 max-w-lg">
      <h3 className="text-sm font-medium text-gray-900 mb-4">New Entity</h3>
      <form onSubmit={handleSubmit} className="space-y-3">
        <div>
          <label className="block text-sm text-gray-700 mb-1">Name</label>
          <input
            type="text"
            value={name}
            onChange={(e) => setName(e.target.value)}
            className="w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-accent-500 focus:border-transparent"
            placeholder="Low Time Preference Fund I, LLC"
            required
          />
        </div>
        <div>
          <label className="block text-sm text-gray-700 mb-1">Type</label>
          <select
            value={type}
            onChange={(e) => setType(e.target.value as EntityType)}
            className="w-full px-3 py-2 border border-gray-300 rounded text-sm"
          >
            <option value="fund">Fund</option>
            <option value="spv">SPV</option>
            <option value="gp">GP</option>
            <option value="mgmt_co">Mgmt Co</option>
            <option value="carry">Carry Vehicle</option>
          </select>
        </div>
        <div className="flex gap-3">
          <div className="flex-1">
            <label className="block text-sm text-gray-700 mb-1">Vintage Year</label>
            <input
              type="text"
              value={vintageYear}
              onChange={(e) => setVintageYear(e.target.value)}
              className="w-full px-3 py-2 border border-gray-300 rounded text-sm"
              placeholder="2021"
            />
          </div>
          <div className="flex-1">
            <label className="block text-sm text-gray-700 mb-1">Fund Size ($)</label>
            <input
              type="text"
              value={fundSizeDollars}
              onChange={(e) => setFundSizeDollars(e.target.value)}
              className="w-full px-3 py-2 border border-gray-300 rounded text-sm"
              placeholder="3,300,000"
            />
          </div>
        </div>
        {error && (
          <p className="text-sm text-red-600">{error}</p>
        )}
        <div className="flex gap-2 pt-1">
          <button
            type="submit"
            disabled={saving}
            className="px-4 py-2 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
          >
            {saving ? "Creating..." : "Create"}
          </button>
          <button
            type="button"
            onClick={onClose}
            className="px-4 py-2 border border-gray-300 text-sm rounded hover:bg-gray-50"
          >
            Cancel
          </button>
        </div>
      </form>
    </div>
  );
}

type SortKey = "name" | "type" | "vintage" | "committed" | "invested" | "value" | "gain";

function EntityTable({ title, rows }: { title: string; rows: EntityRow[] }) {
  const [sortKey, setSortKey] = useState<SortKey>("name");
  const [dir, setDir] = useState<1 | -1>(1);

  const totalCommitted = rows.reduce((s, r) => s + r.committedCents, 0);
  const totalInvested = rows.reduce((s, r) => s + r.investedCents, 0);
  const totalValue = rows.reduce((s, r) => s + r.lastValueCents, 0);
  const totalGain = totalValue - totalInvested;

  const sorted = useMemo(() => {
    const val = (r: EntityRow): string | number => {
      switch (sortKey) {
        case "name": return r.name.toLowerCase();
        case "type": return r.type;
        case "vintage": return r.vintage_year ?? -Infinity;
        case "committed": return r.committedCents;
        case "invested": return r.investedCents;
        case "value": return r.lastValueCents;
        case "gain": return r.lastValueCents - r.investedCents;
      }
    };
    return [...rows].sort((a, b) => {
      const av = val(a), bv = val(b);
      if (av < bv) return -1 * dir;
      if (av > bv) return 1 * dir;
      return 0;
    });
  }, [rows, sortKey, dir]);

  const sortBy = (key: SortKey) => {
    if (key === sortKey) setDir((d) => (d === 1 ? -1 : 1));
    else { setSortKey(key); setDir(1); }
  };

  const arrow = (key: SortKey) => (sortKey === key ? (dir === 1 ? " ↑" : " ↓") : "");
  const Th = ({ k, label, align = "left" }: { k: SortKey; label: string; align?: "left" | "right" }) => {
    const a = align === "right" ? "text-right" : "text-left";
    return (
      <th className={`px-4 py-3 font-medium text-gray-600 select-none ${a}`}>
        <button onClick={() => sortBy(k)} className={`w-full hover:text-gray-900 ${a}`}>
          {label}<span className="text-accent-500">{arrow(k)}</span>
        </button>
      </th>
    );
  };

  return (
    <div>
      <h2 className="text-lg font-semibold text-gray-900 mb-3">{title}</h2>

      {/* Mobile: stacked cards (a wide financial table doesn't fit a phone) */}
      <div className="md:hidden space-y-3">
        {sorted.map((row) => {
          const gl = formatGainLoss(row.lastValueCents, row.investedCents);
          return (
            <Link
              key={row.id}
              to={`/entities/${row.id}`}
              className="block bg-white border border-gray-200 rounded-lg p-4 active:bg-gray-50"
            >
              <div className="flex items-start justify-between gap-2">
                <span className="font-medium text-gray-900">{row.name}</span>
                <span className="shrink-0 inline-block px-2 py-0.5 bg-gray-100 text-gray-600 text-xs rounded">
                  {TYPE_LABELS[row.type] || row.type}
                </span>
              </div>
              {row.vintage_year && (
                <div className="mt-0.5 text-xs text-gray-400">Vintage {row.vintage_year}</div>
              )}
              <div className="grid grid-cols-2 gap-x-4 gap-y-2 mt-3">
                <CardMetric label="Committed" value={formatMoney(row.committedCents)} />
                <CardMetric label="Invested" value={formatMoney(row.investedCents)} />
                <CardMetric label="Last value" value={formatMoney(row.lastValueCents)} />
                <CardMetric
                  label="Gain/Loss"
                  value={`${gl.positive ? "+" : "-"}${gl.text}`}
                  valueClass={gl.positive ? "text-green-600" : "text-red-600"}
                />
              </div>
            </Link>
          );
        })}
        {rows.length > 0 && (
          <div className="bg-gray-50 border border-gray-200 rounded-lg p-4">
            <div className="text-xs font-medium text-gray-500 uppercase mb-2">Total</div>
            <div className="grid grid-cols-2 gap-x-4 gap-y-2">
              <CardMetric label="Committed" value={formatMoney(totalCommitted)} />
              <CardMetric label="Invested" value={formatMoney(totalInvested)} />
              <CardMetric label="Last value" value={formatMoney(totalValue)} />
              <CardMetric
                label="Gain/Loss"
                value={`${totalGain >= 0 ? "+" : "-"}${formatMoney(Math.abs(totalGain))}`}
                valueClass={totalGain >= 0 ? "text-green-600" : "text-red-600"}
              />
            </div>
          </div>
        )}
        {rows.length === 0 && (
          <p className="text-sm text-gray-400 px-1">No entities yet.</p>
        )}
      </div>

      {/* Desktop: full sortable table */}
      <div className="hidden md:block bg-white border border-gray-200 rounded-lg overflow-x-auto">
        <table className="w-full min-w-[46rem] text-sm">
          <thead>
            <tr className="bg-gray-50 border-b border-gray-200">
              <Th k="name" label="Name" />
              <Th k="type" label="Type" />
              <Th k="vintage" label="Vintage" />
              <Th k="committed" label="Committed" align="right" />
              <Th k="invested" label="Invested" align="right" />
              <Th k="value" label="Last Signed Value" align="right" />
              <Th k="gain" label="Gain/Loss" align="right" />
            </tr>
          </thead>
          <tbody>
            {sorted.map((row) => {
              const gl = formatGainLoss(row.lastValueCents, row.investedCents);
              return (
                <tr key={row.id} className="border-b border-gray-100 hover:bg-gray-50">
                  <td className="px-4 py-3">
                    <Link
                      to={`/entities/${row.id}`}
                      className="text-gray-900 font-medium hover:text-accent-600"
                    >
                      {row.name}
                    </Link>
                  </td>
                  <td className="px-4 py-3">
                    <span className="inline-block px-2 py-0.5 bg-gray-100 text-gray-600 text-xs rounded">
                      {TYPE_LABELS[row.type] || row.type}
                    </span>
                  </td>
                  <td className="px-4 py-3 text-gray-600">{row.vintage_year || "—"}</td>
                  <td className="px-4 py-3 text-right text-gray-900">{formatMoney(row.committedCents)}</td>
                  <td className="px-4 py-3 text-right text-gray-900">{formatMoney(row.investedCents)}</td>
                  <td className="px-4 py-3 text-right text-gray-900">{formatMoney(row.lastValueCents)}</td>
                  <td className={`px-4 py-3 text-right font-medium ${gl.positive ? "text-green-600" : "text-red-600"}`}>
                    {gl.positive ? "+" : "-"}{gl.text}
                  </td>
                </tr>
              );
            })}
            {rows.length > 0 && (
              <tr className="bg-gray-50 font-medium">
                <td className="px-4 py-3 text-gray-900" colSpan={3}>
                  Total
                </td>
                <td className="px-4 py-3 text-right text-gray-900">{formatMoney(totalCommitted)}</td>
                <td className="px-4 py-3 text-right text-gray-900">{formatMoney(totalInvested)}</td>
                <td className="px-4 py-3 text-right text-gray-900">{formatMoney(totalValue)}</td>
                <td className={`px-4 py-3 text-right ${totalGain >= 0 ? "text-green-600" : "text-red-600"}`}>
                  {totalGain >= 0 ? "+" : "-"}{formatMoney(Math.abs(totalGain))}
                </td>
              </tr>
            )}
            {rows.length === 0 && (
              <tr>
                <td className="px-4 py-6 text-center text-gray-400" colSpan={7}>
                  No entities yet.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function CardMetric({
  label,
  value,
  valueClass = "text-gray-900",
}: {
  label: string;
  value: string;
  valueClass?: string;
}) {
  return (
    <div>
      <div className="text-xs text-gray-400 uppercase">{label}</div>
      <div className={`text-sm font-medium ${valueClass}`}>{value}</div>
    </div>
  );
}
