'use client';

import { useState } from 'react';
import Link from 'next/link';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { formatPrice } from '@alqove/shared';
import { useSelectedStoreId } from '@/lib/stores/store-context';
import { useStoreStatements } from '@/lib/queries/use-statements';
import { api } from '@/lib/api';
import type { LedgerEntry } from '@alqove/api-client';

const PER_PAGE = 20;

// SSR-safe: pin locale + UTC so server and client render the same string.
const DATE_FORMATTER = new Intl.DateTimeFormat('en-US', {
  month: 'short',
  day: 'numeric',
  year: 'numeric',
  timeZone: 'UTC',
});

function formatDate(iso: string): string {
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return '';
  return DATE_FORMATTER.format(date);
}

function labelForType(entry: LedgerEntry): string {
  // Map the underlying enum to something readable. Falling back to the raw
  // value keeps the column meaningful even if the API adds new entry types.
  switch (entry.entry_type) {
    case 'order_earned':
      return 'Order earned';
    case 'order_refunded':
      return 'Refund';
    case 'label_cost_debit':
      return 'Shipping label';
    case 'payout_settled':
      return 'Payout';
    case 'adjustment_credit':
      return 'Adjustment (credit)';
    case 'adjustment_debit':
      return 'Adjustment (debit)';
    default:
      return entry.entry_type;
  }
}

function signedAmount(entry: LedgerEntry): { value: string; positive: boolean } {
  const positive = entry.direction === 'credit';
  const sign = positive ? '+' : '−';
  return { value: `${sign}${formatPrice(entry.amount_cents)}`, positive };
}

interface RunningBalanceCellProps {
  entry: LedgerEntry;
}

function RunningBalanceCell({ entry }: RunningBalanceCellProps) {
  // The API does not return a per-row running balance today; show the
  // available_at date as a proxy so sellers can correlate to the cycle.
  return (
    <span className="text-xs text-ink/60">{formatDate(entry.available_at)}</span>
  );
}

function buildFilename(from: string | null, to: string | null): string {
  const range =
    from && to ? `${from}_to_${to}` : from ? `from_${from}` : to ? `to_${to}` : 'all';
  return `alqove-statement-${range}.csv`;
}

export function SellerStatementsClient() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const storeId = useSelectedStoreId();

  const from = searchParams.get('from');
  const to = searchParams.get('to');
  const page = Math.max(1, Number(searchParams.get('page') ?? '1'));

  const [draftFrom, setDraftFrom] = useState(from ?? '');
  const [draftTo, setDraftTo] = useState(to ?? '');
  const [downloadError, setDownloadError] = useState<string | null>(null);
  const [downloading, setDownloading] = useState(false);

  const writeParams = (mut: (p: URLSearchParams) => void) => {
    const params = new URLSearchParams(searchParams.toString());
    mut(params);
    const qs = params.toString();
    router.replace(qs ? `${pathname}?${qs}` : pathname);
  };

  const applyRange = () => {
    writeParams((p) => {
      if (draftFrom) p.set('from', draftFrom);
      else p.delete('from');
      if (draftTo) p.set('to', draftTo);
      else p.delete('to');
      p.delete('page');
    });
  };

  const setPage = (next: number) => {
    writeParams((p) => {
      if (next <= 1) p.delete('page');
      else p.set('page', String(next));
    });
  };

  const queryParams = {
    page,
    per_page: PER_PAGE,
    ...(from ? { from } : {}),
    ...(to ? { to } : {}),
  };

  const { data, isLoading, isError } = useStoreStatements(storeId, queryParams);
  const entries = data?.data ?? [];
  const meta = data?.meta;

  const downloadCsv = async () => {
    if (!storeId) return;
    setDownloadError(null);
    setDownloading(true);
    try {
      const blob = await api.statements.downloadCsv(storeId, {
        ...(from ? { from } : {}),
        ...(to ? { to } : {}),
      });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = buildFilename(from, to);
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch (e) {
      setDownloadError((e as Error).message ?? 'Failed to download CSV.');
    } finally {
      setDownloading(false);
    }
  };

  return (
    <div>
      <div className="flex items-start justify-between gap-4">
        <div>
          <h1 className="text-2xl font-bold text-ink">Statements</h1>
          <p className="mt-1 text-sm text-ink/60">
            Every credit and debit against your store balance.
          </p>
        </div>
        <button
          type="button"
          onClick={downloadCsv}
          disabled={!storeId || downloading}
          data-testid="statements-download-csv"
          className="rounded-md border border-forest/30 bg-white px-3 py-2 text-sm font-medium text-ink hover:bg-bone disabled:cursor-not-allowed disabled:opacity-50"
        >
          {downloading ? 'Preparing…' : 'Download CSV'}
        </button>
      </div>

      {downloadError && (
        <p
          className="mt-3 rounded bg-terracotta/10 p-3 text-sm text-terracotta"
          data-testid="statements-download-error"
        >
          {downloadError}
        </p>
      )}

      <div className="mt-4 flex flex-wrap items-end gap-3 rounded-md border border-forest/10 bg-white p-3">
        <label className="flex flex-col text-xs text-ink/60">
          <span className="mb-1 font-medium uppercase tracking-wide">From</span>
          <input
            type="date"
            value={draftFrom}
            onChange={(e) => setDraftFrom(e.target.value)}
            data-testid="statements-from"
            className="rounded-md border border-forest/30 px-2 py-1 text-sm text-ink"
          />
        </label>
        <label className="flex flex-col text-xs text-ink/60">
          <span className="mb-1 font-medium uppercase tracking-wide">To</span>
          <input
            type="date"
            value={draftTo}
            onChange={(e) => setDraftTo(e.target.value)}
            data-testid="statements-to"
            className="rounded-md border border-forest/30 px-2 py-1 text-sm text-ink"
          />
        </label>
        <button
          type="button"
          onClick={applyRange}
          data-testid="statements-apply-range"
          className="rounded-md bg-forest px-3 py-1.5 text-sm font-medium text-white hover:bg-forest/90"
        >
          Apply
        </button>
      </div>

      <div className="mt-4 overflow-hidden rounded-md border border-forest/20 bg-white">
        {isLoading && (
          <div
            className="p-8 text-center text-sm text-ink/60"
            data-testid="statements-loading"
          >
            Loading statement…
          </div>
        )}

        {isError && (
          <div
            className="p-8 text-center text-sm text-terracotta"
            data-testid="statements-error"
          >
            Failed to load statement.
          </div>
        )}

        {!isLoading && !isError && entries.length === 0 && (
          <div
            className="p-8 text-center text-sm text-ink/60"
            data-testid="statements-empty"
          >
            No ledger entries in this range yet.
          </div>
        )}

        {!isLoading && !isError && entries.length > 0 && (
          <table className="w-full text-sm">
            <thead className="bg-bone/60">
              <tr>
                <Th>Date</Th>
                <Th>Description</Th>
                <Th>Type</Th>
                <Th className="text-right">Amount</Th>
                <Th>Payout</Th>
                <Th>Available</Th>
              </tr>
            </thead>
            <tbody>
              {entries.map((entry) => {
                const signed = signedAmount(entry);
                return (
                  <tr
                    key={entry.id}
                    data-testid={`statements-row-${entry.id}`}
                    className="border-t border-forest/10"
                  >
                    <td className="px-4 py-3 text-ink">
                      {formatDate(entry.created_at)}
                    </td>
                    <td className="px-4 py-3 text-ink">
                      {entry.description ?? <span className="text-ink/40">—</span>}
                    </td>
                    <td className="px-4 py-3 text-xs text-ink/70">
                      {labelForType(entry)}
                    </td>
                    <td
                      className={`px-4 py-3 text-right font-mono ${
                        signed.positive ? 'text-forest-700' : 'text-rose-700'
                      }`}
                      data-testid={`statements-amount-${entry.id}`}
                    >
                      {signed.value}
                    </td>
                    <td className="px-4 py-3 text-xs">
                      {entry.payout_id ? (
                        <Link
                          href={`/seller/payouts?highlight=${entry.payout_id}`}
                          className="font-mono text-terracotta hover:underline"
                          data-testid={`statements-payout-link-${entry.id}`}
                        >
                          {entry.payout_id.slice(0, 8)}
                        </Link>
                      ) : (
                        <span className="text-ink/40">—</span>
                      )}
                    </td>
                    <td className="px-4 py-3">
                      <RunningBalanceCell entry={entry} />
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      {meta && meta.last_page > 1 && (
        <div className="mt-4 flex items-center justify-between text-xs text-ink/60">
          <span>
            Page {meta.current_page} of {meta.last_page} · {meta.total} total
          </span>
          <div className="flex gap-2">
            <button
              type="button"
              onClick={() => setPage(page - 1)}
              disabled={page <= 1}
              className="rounded border border-forest/30 px-3 py-1 disabled:cursor-not-allowed disabled:opacity-50 hover:bg-bone/50"
            >
              Previous
            </button>
            <button
              type="button"
              onClick={() => setPage(page + 1)}
              disabled={page >= meta.last_page}
              className="rounded border border-forest/30 px-3 py-1 disabled:cursor-not-allowed disabled:opacity-50 hover:bg-bone/50"
            >
              Next
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

function Th({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <th
      scope="col"
      className={`px-4 py-2 text-left text-xs font-semibold uppercase tracking-wide text-ink/60 ${
        className ?? ''
      }`}
    >
      {children}
    </th>
  );
}
