'use client';

import { Suspense, useEffect, useMemo, useState } from 'react';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import Link from 'next/link';
import { JobCard, JobListingSkeleton } from '@/components/jobs/JobCard';
import {
  countActiveJobsBrowseFilters,
  defaultJobsBrowseFilters,
  JobsBrowseFilterButton,
  JobsBrowseFilterModal,
  type JobsBrowseFilters,
  type JobsBrowseSort,
} from '@/components/jobs/JobsBrowseFilterModal';
import { Button } from '@/components/ui/button';
import { BrowsePageHero } from '@/components/layout/BrowsePageHero';
import { Search, Briefcase, MapPin, PlusCircle } from 'lucide-react';
import { api } from '@/lib/api';
import { BROWSE_PAGE_SIZE, formatBrowseCount, type PaginationMeta } from '@/lib/pagination';
import { useInfiniteScroll } from '@/hooks/useInfiniteScroll';
import { useAuth } from '@/contexts/AuthContext';
import { appendAreaQuery, regionLabel, regionPath, resolveBrowseRegionSlug } from '@/lib/region';
import { buildPostJobAuthUrl } from '@/lib/createJob';
import { useRegion } from '@/contexts/RegionContext';

type CategoryOption = { id: string; name: string; slug: string; icon?: string };

function sortJobs(jobs: Record<string, unknown>[], sort: JobsBrowseSort) {
  const copy = [...jobs];
  if (sort === 'budget-high') {
    return copy.sort((a, b) => Number(b.budget ?? 0) - Number(a.budget ?? 0));
  }
  if (sort === 'budget-low') {
    return copy.sort((a, b) => Number(a.budget ?? 0) - Number(b.budget ?? 0));
  }
  return copy.sort(
    (a, b) => new Date(b.createdAt as string).getTime() - new Date(a.createdAt as string).getTime()
  );
}

function JobsContent({
  regionSlug: regionSlugFromPath,
  postJobHref = buildPostJobAuthUrl(),
}: {
  regionSlug?: string;
  postJobHref?: string;
}) {
  const searchParams = useSearchParams();
  const pathname = usePathname();
  const router = useRouter();
  const { slug: contextSlug, regionReady } = useRegion();
  const regionSlug = resolveBrowseRegionSlug(regionSlugFromPath, contextSlug);
  const { user } = useAuth();
  const [categories, setCategories] = useState<CategoryOption[]>([]);
  const [jobs, setJobs] = useState<Record<string, unknown>[]>([]);
  const [search, setSearch] = useState(searchParams.get('search') || '');
  const [filters, setFilters] = useState<JobsBrowseFilters>(() => ({
    categorySlug: searchParams.get('category') || '',
    sort: (searchParams.get('sort') as JobsBrowseSort) || 'newest',
  }));
  const [filterOpen, setFilterOpen] = useState(false);
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [page, setPage] = useState(1);
  const [meta, setMeta] = useState<PaginationMeta | null>(null);

  const { categorySlug, sort } = filters;
  const label = regionLabel(regionSlug);
  const selectedCategory = categories.find((c) => c.slug === categorySlug);
  const activeFilterCount = useMemo(() => countActiveJobsBrowseFilters(filters), [filters]);

  const jobHref = (id: string) =>
    user?.role === 'WORKER' ? `/worker/jobs/${id}` : `/jobs/${id}`;

  const syncBrowseParams = (next: JobsBrowseFilters) => {
    const params = new URLSearchParams(searchParams.toString());
    if (next.categorySlug) params.set('category', next.categorySlug);
    else params.delete('category');
    if (next.sort && next.sort !== 'newest') params.set('sort', next.sort);
    else params.delete('sort');
    const query = params.toString();
    router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false });
  };

  const handleFiltersChange = (next: JobsBrowseFilters) => {
    setFilters(next);
    syncBrowseParams(next);
  };

  const clearAllFilters = () => {
    setSearch('');
    handleFiltersChange(defaultJobsBrowseFilters);
    fetchJobs({ search: '', categorySlug: '' });
  };

  const fetchJobs = (
    pageNum = 1,
    append = false,
    overrides?: { search?: string; categorySlug?: string }
  ) => {
    if (pageNum === 1) setLoading(true);
    else setLoadingMore(true);

    const params = new URLSearchParams({
      status: 'OPEN',
      limit: String(BROWSE_PAGE_SIZE),
      page: String(pageNum),
    });
    const q = overrides?.search !== undefined ? overrides.search : search;
    const cat = overrides?.categorySlug !== undefined ? overrides.categorySlug : categorySlug;
    if (q) params.set('search', q);
    if (cat) params.set('categorySlug', cat);
    appendAreaQuery(params, regionSlug);

    api<{ data: Record<string, unknown>[]; meta?: PaginationMeta }>(`/jobs?${params}`)
      .then((res) => {
        setJobs((prev) => (append ? [...prev, ...res.data] : res.data));
        setMeta(res.meta ?? null);
        setPage(pageNum);
      })
      .catch(console.error)
      .finally(() => {
        setLoading(false);
        setLoadingMore(false);
      });
  };

  const hasMore = meta != null && page < meta.totalPages;

  const loadMore = () => {
    if (loading || loadingMore || !hasMore) return;
    fetchJobs(page + 1, true);
  };

  const loadMoreRef = useInfiniteScroll(loadMore, { enabled: hasMore && !loading });

  useEffect(() => {
    api<{ data: CategoryOption[] }>('/categories?limit=50')
      .then((res) => setCategories(res.data))
      .catch(console.error);
  }, []);

  useEffect(() => {
    if (!regionReady) return;
    fetchJobs(1, false);
  }, [regionSlug, categorySlug, regionReady]);

  const sortedJobs = useMemo(() => sortJobs(jobs, sort), [jobs, sort]);

  return (
    <>
      <div className="mb-4 space-y-3">
        <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
          <div className="relative min-w-0 flex-1">
            <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400" />
            <input
              type="text"
              placeholder="Job title, skill, or keyword..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              onKeyDown={(e) => e.key === 'Enter' && fetchJobs()}
              className="search-input-icon h-11"
            />
          </div>
          <div className="flex shrink-0 items-center gap-2">
            <Button onClick={() => fetchJobs()} size="sm" className="h-9 px-4">
              Search
            </Button>
            <JobsBrowseFilterButton
              activeCount={activeFilterCount}
              onClick={() => setFilterOpen(true)}
            />
          </div>
        </div>

        {!loading && (
          <p className="text-sm text-muted">
            <Briefcase className="mr-1 inline h-4 w-4 -mt-0.5 text-accent" />
            <span className="font-semibold text-slate-900">
              {formatBrowseCount(sortedJobs.length, meta?.total)}
            </span>{' '}
            open job
            {meta?.total === 1 || (meta == null && sortedJobs.length === 1) ? '' : 's'}
            {selectedCategory ? ` · ${selectedCategory.name}` : ''} in {label}
            {activeFilterCount > 0 ? ' · filtered' : ''}
          </p>
        )}
      </div>

      <JobsBrowseFilterModal
        open={filterOpen}
        onClose={() => setFilterOpen(false)}
        filters={filters}
        onChange={handleFiltersChange}
        categories={categories}
        resultCount={meta?.total ?? sortedJobs.length}
      />

      {loading ? (
        <JobListingSkeleton />
      ) : sortedJobs.length > 0 ? (
        <div className="space-y-3">
          {sortedJobs.map((job) => (
            <JobCard
              key={job.id as string}
              variant="listing"
              job={job as Parameters<typeof JobCard>[0]['job']}
              href={jobHref(job.id as string)}
            />
          ))}
          {hasMore && (
            <div ref={loadMoreRef} className="py-4 text-center text-sm text-muted">
              {loadingMore ? 'Loading more jobs…' : 'Scroll for more'}
            </div>
          )}
        </div>
      ) : (
        <div className="rounded-xl border border-dashed border-border bg-surface py-16 px-6 text-center">
          <div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-slate-100">
            <Briefcase className="h-7 w-7 text-muted" />
          </div>
          <h3 className="font-bold text-slate-900 text-lg">No jobs found</h3>
          <p className="text-sm text-muted mt-2 max-w-sm mx-auto">
            {search
              ? `No results for "${search}". Try a different keyword or browse all open jobs.`
              : selectedCategory
                ? `No open ${selectedCategory.name.toLowerCase()} jobs in ${label} right now.`
                : `No open jobs in ${label} right now. Be the first to post one!`}
          </p>
          <div className="flex flex-col sm:flex-row gap-2 justify-center mt-6">
            {(search || activeFilterCount > 0) && (
              <Button variant="outline" onClick={clearAllFilters}>
                Clear filters
              </Button>
            )}
            <Link href={postJobHref}>
              <Button variant="accent" className="gap-2 w-full sm:w-auto">
                <PlusCircle className="h-4 w-4" />
                Post a Job
              </Button>
            </Link>
          </div>
        </div>
      )}
    </>
  );
}

export function JobsPageView({ regionSlug: regionSlugFromPath }: { regionSlug?: string }) {
  const { slug: contextSlug } = useRegion();
  const regionSlug = resolveBrowseRegionSlug(regionSlugFromPath, contextSlug);
  const label = regionLabel(regionSlug);
  const mapHref = regionSlug ? regionPath(regionSlug, '/map?filter=jobs') : '/map?filter=jobs';

  return (
    <div>
      <BrowsePageHero
        eyebrow={`Job board · ${label}`}
        title="Find Jobs"
        description={`Browse open jobs from customers in ${label} — carpentry, plumbing, electrical, and more.`}
        actions={[
          { href: mapHref, label: 'Map view', icon: MapPin, variant: 'heroOutline' },
          { href: buildPostJobAuthUrl(), label: 'Post a job', icon: PlusCircle, variant: 'accent' },
        ]}
      />

      <div className="page-container max-w-4xl">
        <Suspense fallback={<JobListingSkeleton />}>
          <JobsContent regionSlug={regionSlug} />
        </Suspense>
      </div>
    </div>
  );
}
