'use client';

import { LayoutGrid, List, SlidersHorizontal, X, Search } from 'lucide-react';
import { useRouter, useSearchParams, usePathname } from 'next/navigation';
import * as React from 'react';
import {
  DataTable,
  DensityToggle,
  PriceDelta,
  useDensity,
  DENSITY_ROW_HEIGHT,
  type DataTableColumn,
} from '@/components/design-system';
import { ListingPreviewPanel } from '@/components/listings/listing-preview-panel';
import { Sparkline } from '@/components/listings/sparkline';
import { PropertyCard } from '@/components/search/property-card';
import { Button } from '@/components/ui/button';
import { formatPrice, formatPricePerM2 } from '@/lib/currency';
import { useListingsSearch } from '@/lib/hooks/use-listings';
import type { ListingDetail, PropertyType, TransactionType } from '@/lib/listings-api';
import { PROPERTY_TYPES, TRANSACTION_TYPES } from '@/lib/validations/listings';
import { HCM_DISTRICTS } from '@/lib/vietnam-geo';

// ---------------------------------------------------------------------------
// Hằng số
// ---------------------------------------------------------------------------

const DISTRICTS = HCM_DISTRICTS;

const PRICE_RANGES = [
  { label: 'Dưới 1 tỷ', min: '', max: '1000000000' },
  { label: '1 – 3 tỷ', min: '1000000000', max: '3000000000' },
  { label: '3 – 7 tỷ', min: '3000000000', max: '7000000000' },
  { label: '7 – 15 tỷ', min: '7000000000', max: '15000000000' },
  { label: 'Trên 15 tỷ', min: '15000000000', max: '' },
];

const AREA_RANGES = [
  { label: 'Dưới 30 m²', min: 0, max: 30 },
  { label: '30 – 50 m²', min: 30, max: 50 },
  { label: '50 – 80 m²', min: 50, max: 80 },
  { label: '80 – 150 m²', min: 80, max: 150 },
  { label: 'Trên 150 m²', min: 150, max: 0 },
];

const BEDROOM_OPTIONS = [
  { label: '1 PN', value: 1 },
  { label: '2 PN', value: 2 },
  { label: '3 PN', value: 3 },
  { label: '4+ PN', value: 4 },
];

const PAGE_SIZE = 50;

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function shortId(id: string): string {
  return `GG-${id.slice(0, 5).toUpperCase()}`;
}

function getDelta30d(listing: ListingDetail): number | null {
  const raw = (listing as ListingDetail & { priceDelta30d?: number | null }).priceDelta30d;
  return raw ?? null;
}

function formatPublishedAt(dateStr: string | null): string {
  if (!dateStr) return '—';
  const d = new Date(dateStr);
  return d.toLocaleDateString('vi-VN', { day: '2-digit', month: '2-digit', year: '2-digit' });
}

// ---------------------------------------------------------------------------
// URL param sync helpers
// ---------------------------------------------------------------------------

interface Filters {
  transactionType: TransactionType | '';
  propertyType: PropertyType | '';
  district: string;
  priceRange: string;
  areaRange: string;
  bedrooms: string;
  q: string;
}

const defaultFilters: Filters = {
  transactionType: '',
  propertyType: '',
  district: '',
  priceRange: '',
  areaRange: '',
  bedrooms: '',
  q: '',
};

function filtersFromSearchParams(sp: URLSearchParams): Filters {
  return {
    transactionType: (sp.get('transactionType') ?? '') as TransactionType | '',
    propertyType: (sp.get('propertyType') ?? '') as PropertyType | '',
    district: sp.get('district') ?? '',
    priceRange: sp.get('priceRange') ?? '',
    areaRange: sp.get('areaRange') ?? '',
    bedrooms: sp.get('bedrooms') ?? '',
    q: sp.get('q') ?? '',
  };
}

function filtersToSearchParams(
  filters: Filters,
  page: number,
  sortBy: string,
  order: 'asc' | 'desc',
): URLSearchParams {
  const sp = new URLSearchParams();
  if (filters.transactionType) sp.set('transactionType', filters.transactionType);
  if (filters.propertyType) sp.set('propertyType', filters.propertyType);
  if (filters.district) sp.set('district', filters.district);
  if (filters.priceRange) sp.set('priceRange', filters.priceRange);
  if (filters.areaRange) sp.set('areaRange', filters.areaRange);
  if (filters.bedrooms) sp.set('bedrooms', filters.bedrooms);
  if (filters.q) sp.set('q', filters.q);
  if (page > 1) sp.set('page', String(page));
  if (sortBy) sp.set('sortBy', sortBy);
  if (order !== 'desc') sp.set('order', order);
  return sp;
}

// ---------------------------------------------------------------------------
// Columns
// ---------------------------------------------------------------------------

function buildColumns(): DataTableColumn<ListingDetail>[] {
  return [
    {
      id: 'index',
      header: '#',
      cell: (_row, index) => (
        <span className="text-foreground-dim text-[11px] tabular-nums">{index + 1}</span>
      ),
      width: '36px',
    },
    {
      id: 'code',
      header: 'Mã',
      cell: (row) => (
        <span className="font-mono text-[12px] text-primary">{shortId(row.id)}</span>
      ),
      width: '76px',
    },
    {
      id: 'title',
      header: 'Tiêu đề',
      cell: (row) => (
        <span className="text-foreground text-[13px] truncate block max-w-[200px]">
          {row.property.title}
        </span>
      ),
      sortable: true,
      sortValue: (row) => row.property.title,
      width: '200px',
    },
    {
      id: 'district',
      header: 'Quận/Phường',
      cell: (row) => (
        <div className="text-[12px]">
          <span className="text-foreground">{row.property.district}</span>
          {row.property.ward && (
            <span className="text-foreground-dim"> · {row.property.ward}</span>
          )}
        </div>
      ),
      sortable: true,
      sortValue: (row) => row.property.district,
      width: '150px',
    },
    {
      id: 'area',
      header: 'DT m²',
      cell: (row) => (
        <span className="font-mono text-[12px] tabular-nums text-foreground-muted">
          {row.property.areaM2}
        </span>
      ),
      align: 'right',
      numeric: true,
      sortable: true,
      sortValue: (row) => row.property.areaM2,
      width: '70px',
    },
    {
      id: 'price',
      header: 'Giá',
      cell: (row) => (
        <span className="font-mono text-[13px] font-medium text-foreground tabular-nums">
          {formatPrice(row.priceVND)}
        </span>
      ),
      align: 'right',
      numeric: true,
      sortable: true,
      sortValue: (row) => Number(row.priceVND),
      width: '100px',
    },
    {
      id: 'pricePerM2',
      header: 'Giá/m²',
      cell: (row) => (
        <span className="font-mono text-[11px] tabular-nums text-foreground-muted">
          {row.pricePerM2 ? formatPricePerM2(row.pricePerM2) : '—'}
        </span>
      ),
      align: 'right',
      numeric: true,
      sortable: true,
      sortValue: (row) => row.pricePerM2 ?? 0,
      width: '90px',
    },
    {
      id: 'bedrooms',
      header: 'PN',
      cell: (row) => (
        <span className="text-[12px] tabular-nums text-foreground-muted">
          {row.property.bedrooms ?? '—'}
        </span>
      ),
      align: 'right',
      numeric: true,
      sortable: true,
      sortValue: (row) => row.property.bedrooms ?? 0,
      width: '50px',
    },
    {
      id: 'publishedAt',
      header: 'Ngày đăng',
      cell: (row) => (
        <span className="text-[11px] tabular-nums text-foreground-dim">
          {formatPublishedAt(row.publishedAt)}
        </span>
      ),
      sortable: true,
      sortValue: (row) => row.publishedAt ?? '',
      width: '80px',
    },
    {
      id: 'sparkline',
      header: '30d',
      cell: (row) => <Sparkline listingId={row.id} width={56} height={18} />,
      align: 'center',
      width: '72px',
    },
    {
      id: 'delta30d',
      header: 'Δ30d',
      cell: (row) => {
        const delta = getDelta30d(row);
        if (delta === null) {
          return <span className="text-foreground-dim text-[12px]">—</span>;
        }
        return <PriceDelta value={delta} size="sm" />;
      },
      align: 'right',
      numeric: true,
      sortable: true,
      sortValue: (row) => getDelta30d(row) ?? -Infinity,
      width: '70px',
    },
    {
      id: 'agent',
      header: 'Môi giới',
      cell: (row) => (
        <span className="text-[11px] text-foreground-dim truncate block max-w-[80px]">
          {row.agent?.agency ?? '—'}
        </span>
      ),
      width: '80px',
    },
  ];
}

// ---------------------------------------------------------------------------
// Filter sidebar
// ---------------------------------------------------------------------------

function FilterSelect({
  label,
  value,
  onChange,
  children,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  children: React.ReactNode;
}) {
  return (
    <div className="space-y-1">
      <label className="block text-[11px] font-medium uppercase tracking-wide text-foreground-muted">
        {label}
      </label>
      <select
        aria-label={label}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="w-full rounded-md border border-border bg-background-surface px-2.5 py-1.5 text-[13px] text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
      >
        {children}
      </select>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Component chính
// ---------------------------------------------------------------------------

type ViewMode = 'table' | 'card';

export default function ListingsPage() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  // State from URL
  const [filters, setFilters] = React.useState<Filters>(() =>
    filtersFromSearchParams(searchParams),
  );
  const [page, setPage] = React.useState(() => Number(searchParams.get('page') || '1'));
  const [sortBy, _setSortBy] = React.useState(() => searchParams.get('sortBy') || 'publishedAt');
  const [order, _setOrder] = React.useState<'asc' | 'desc'>(
    () => (searchParams.get('order') as 'asc' | 'desc') || 'desc',
  );
  const [viewMode, setViewMode] = React.useState<ViewMode>('table');
  const [hoveredListing, setHoveredListing] = React.useState<ListingDetail | null>(null);
  const [searchInput, setSearchInput] = React.useState(filters.q);
  const { density } = useDensity();

  // Sync URL when state changes
  const syncUrl = React.useCallback(
    (f: Filters, p: number, sb: string, o: 'asc' | 'desc') => {
      const sp = filtersToSearchParams(f, p, sb, o);
      const qs = sp.toString();
      router.replace(`${pathname}${qs ? `?${qs}` : ''}`, { scroll: false });
    },
    [router, pathname],
  );

  // Build API params from filters
  const apiParams = React.useMemo(() => {
    const params: Record<string, string | number | undefined> = {
      page,
      limit: PAGE_SIZE,
      status: 'ACTIVE' as const,
      sortBy,
      order,
    };

    if (filters.transactionType) params['transactionType'] = filters.transactionType;
    if (filters.propertyType) params['propertyType'] = filters.propertyType;
    if (filters.district) params['district'] = filters.district;
    if (filters.q) params['q'] = filters.q;
    if (filters.bedrooms) params['bedrooms'] = Number(filters.bedrooms);

    if (filters.priceRange) {
      const [min, max] = filters.priceRange.split(':');
      if (min) params['minPrice'] = min;
      if (max) params['maxPrice'] = max;
    }

    if (filters.areaRange) {
      const [min, max] = filters.areaRange.split(':');
      if (min && min !== '0') params['minArea'] = Number(min);
      if (max && max !== '0') params['maxArea'] = Number(max);
    }

    return params;
  }, [filters, page, sortBy, order]);

  const { data, isLoading, isError, refetch } = useListingsSearch(apiParams);

  const handleFilterChange = (key: keyof Filters, value: string) => {
    const next = { ...filters, [key]: value };
    setFilters(next);
    setPage(1);
    syncUrl(next, 1, sortBy, order);
  };

  const clearFilters = () => {
    setFilters(defaultFilters);
    setSearchInput('');
    setPage(1);
    syncUrl(defaultFilters, 1, sortBy, order);
  };

  const handlePageChange = (p: number) => {
    setPage(p);
    syncUrl(filters, p, sortBy, order);
  };

  const handleSearchSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    handleFilterChange('q', searchInput);
  };

  const handleRowClick = React.useCallback(
    (listing: ListingDetail) => {
      router.push(`/listings/${listing.id}`);
    },
    [router],
  );

  const columns = React.useMemo(() => buildColumns(), []);

  const hasFilters = Object.values(filters).some(Boolean);

  const listings = data?.data ?? [];
  const total = data?.total ?? 0;
  const totalPages = data?.totalPages ?? 0;

  return (
    <div className="mx-auto max-w-[1600px] px-4 py-5">
      {/* Header */}
      <div className="mb-4 flex items-baseline justify-between">
        <div>
          <h1 className="text-display-md font-semibold text-foreground">Thị Trường BĐS</h1>
          {!isLoading && (
            <p className="mt-0.5 text-body-sm text-foreground-muted">
              {total.toLocaleString('vi-VN')} bất động sản đang niêm yết
            </p>
          )}
        </div>

        <div className="flex items-center gap-3">
          {/* Density toggle */}
          <DensityToggle />

          {/* View toggle */}
          <div className="flex items-center gap-1 rounded-md border border-border p-0.5">
            <button
              aria-label="Chế độ bảng"
              aria-pressed={viewMode === 'table'}
              onClick={() => setViewMode('table')}
              className={`rounded p-1.5 transition-colors ${
                viewMode === 'table'
                  ? 'bg-background-surface text-foreground'
                  : 'text-foreground-dim hover:text-foreground-muted'
              }`}
            >
              <List className="h-4 w-4" />
            </button>
            <button
              aria-label="Chế độ thẻ"
              aria-pressed={viewMode === 'card'}
              onClick={() => setViewMode('card')}
              className={`rounded p-1.5 transition-colors ${
                viewMode === 'card'
                  ? 'bg-background-surface text-foreground'
                  : 'text-foreground-dim hover:text-foreground-muted'
              }`}
            >
              <LayoutGrid className="h-4 w-4" />
            </button>
          </div>
        </div>
      </div>

      {/* Layout: sidebar + table + preview */}
      <div className="flex gap-4">
        {/* ── Left sidebar filters ── */}
        <aside className="hidden w-[220px] shrink-0 lg:block">
          <div className="sticky top-20 space-y-3 rounded-md border border-border bg-background-elevated p-3">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-1.5 text-[12px] font-medium text-foreground-muted">
                <SlidersHorizontal className="h-3.5 w-3.5" />
                Bộ lọc
              </div>
              {hasFilters && (
                <button
                  onClick={clearFilters}
                  className="flex items-center gap-0.5 text-[11px] text-primary hover:underline"
                >
                  <X className="h-3 w-3" />
                  Xóa
                </button>
              )}
            </div>

            {/* Search */}
            <form onSubmit={handleSearchSubmit} className="relative">
              <Search className="absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-foreground-dim" />
              <input
                type="text"
                value={searchInput}
                onChange={(e) => setSearchInput(e.target.value)}
                placeholder="Tìm kiếm..."
                className="w-full rounded-md border border-border bg-background-surface py-1.5 pl-7 pr-2 text-[13px] text-foreground placeholder:text-foreground-dim focus:outline-none focus:ring-1 focus:ring-primary"
              />
            </form>

            <FilterSelect
              label="Loại giao dịch"
              value={filters.transactionType}
              onChange={(v) => handleFilterChange('transactionType', v)}
            >
              <option value="">Tất cả</option>
              {TRANSACTION_TYPES.map((t) => (
                <option key={t.value} value={t.value}>{t.label}</option>
              ))}
            </FilterSelect>

            <FilterSelect
              label="Loại BĐS"
              value={filters.propertyType}
              onChange={(v) => handleFilterChange('propertyType', v)}
            >
              <option value="">Tất cả</option>
              {PROPERTY_TYPES.map((t) => (
                <option key={t.value} value={t.value}>{t.label}</option>
              ))}
            </FilterSelect>

            <FilterSelect
              label="Quận/Huyện"
              value={filters.district}
              onChange={(v) => handleFilterChange('district', v)}
            >
              <option value="">Tất cả</option>
              {DISTRICTS.map((d) => (
                <option key={d} value={d}>{d}</option>
              ))}
            </FilterSelect>

            <FilterSelect
              label="Khoảng giá"
              value={filters.priceRange}
              onChange={(v) => handleFilterChange('priceRange', v)}
            >
              <option value="">Tất cả</option>
              {PRICE_RANGES.map((r) => (
                <option key={r.label} value={`${r.min}:${r.max}`}>{r.label}</option>
              ))}
            </FilterSelect>

            <FilterSelect
              label="Diện tích"
              value={filters.areaRange}
              onChange={(v) => handleFilterChange('areaRange', v)}
            >
              <option value="">Tất cả</option>
              {AREA_RANGES.map((r) => (
                <option key={r.label} value={`${r.min}:${r.max}`}>{r.label}</option>
              ))}
            </FilterSelect>

            <FilterSelect
              label="Phòng ngủ"
              value={filters.bedrooms}
              onChange={(v) => handleFilterChange('bedrooms', v)}
            >
              <option value="">Tất cả</option>
              {BEDROOM_OPTIONS.map((b) => (
                <option key={b.value} value={String(b.value)}>{b.label}</option>
              ))}
            </FilterSelect>
          </div>
        </aside>

        {/* ── Main content ── */}
        <div className="min-w-0 flex-1">
          {isError ? (
            <div className="flex min-h-[400px] flex-col items-center justify-center gap-3 text-foreground-muted">
              <p className="text-body font-medium">Không thể tải danh sách bất động sản</p>
              <Button variant="outline" size="sm" onClick={() => refetch()}>
                Thử lại
              </Button>
            </div>
          ) : viewMode === 'table' ? (
            <DataTable<ListingDetail>
              columns={columns}
              data={listings}
              getRowId={(row) => row.id}
              onRowClick={handleRowClick}
              onRowHover={setHoveredListing}
              loading={isLoading}
              stickyHeader
              dense={density === 'compact'}
              defaultSortId={sortBy}
              defaultSortDir={order}
              emptyText="Không tìm thấy bất động sản phù hợp"
              className={DENSITY_ROW_HEIGHT[density]}
            />
          ) : (
            isLoading ? (
              <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
                {Array.from({ length: 12 }).map((_, i) => (
                  <div key={i} className="h-64 animate-pulse rounded-lg bg-background-surface" />
                ))}
              </div>
            ) : (
              <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
                {listings.map((listing) => (
                  <PropertyCard key={listing.id} listing={listing} />
                ))}
              </div>
            )
          )}

          {/* Pagination */}
          {totalPages > 1 && !isLoading && (
            <div className="mt-4 flex items-center justify-between">
              <p className="text-body-sm text-foreground-muted">
                Trang {page} / {totalPages} · {total.toLocaleString('vi-VN')} kết quả
              </p>
              <div className="flex items-center gap-1">
                <Button
                  variant="outline"
                  size="sm"
                  disabled={page <= 1}
                  onClick={() => handlePageChange(page - 1)}
                  className="h-8"
                >
                  ◀
                </Button>
                {Array.from({ length: Math.min(5, totalPages) }).map((_, i) => {
                  const half = 2;
                  const start = Math.max(1, Math.min(page - half, totalPages - 4));
                  const p = start + i;
                  return (
                    <Button
                      key={p}
                      variant={p === page ? 'default' : 'outline'}
                      size="sm"
                      onClick={() => handlePageChange(p)}
                      className="h-8 w-8 p-0 text-[12px] tabular-nums"
                    >
                      {p}
                    </Button>
                  );
                })}
                <Button
                  variant="outline"
                  size="sm"
                  disabled={page >= totalPages}
                  onClick={() => handlePageChange(page + 1)}
                  className="h-8"
                >
                  ▶
                </Button>
              </div>
            </div>
          )}
        </div>

        {/* ── Right preview panel (table mode only) ── */}
        {viewMode === 'table' && (
          <aside className="hidden w-[280px] shrink-0 xl:block">
            <div className="sticky top-20 h-[calc(100vh-120px)] rounded-md border border-border bg-background-elevated">
              <ListingPreviewPanel listing={hoveredListing} />
            </div>
          </aside>
        )}
      </div>
    </div>
  );
}
