'use client';

import type { ReactNode } from 'react';
import Link from 'next/link';
import {
  Banknote,
  Briefcase,
  MapPin,
  MessageSquare,
  Sparkles,
  UserRound,
} from 'lucide-react';
import type { JobReactionSummary, JobReactionType } from '@ehandyhire/shared';
import { JobFeedReactions } from '@/components/jobs/JobFeedReactions';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { UserAvatar } from '@/components/ui/UserAvatar';
import { getUploadUrl } from '@/lib/api';
import { isRegionFilterActive, jobMatchesRegion } from '@/lib/region';
import { cn, formatCurrency, formatRelativeTime } from '@/lib/utils';

export interface FeedJob {
  id: string;
  title: string;
  description: string;
  budget?: number | string | null;
  location: string;
  status: string;
  createdAt: string;
  isGuest?: boolean;
  guestName?: string | null;
  invitedWorkerId?: string | null;
  category?: { name: string; slug: string; icon?: string };
  customer?: {
    firstName: string;
    lastName: string;
    avatarUrl?: string | null;
  } | null;
  images?: { id: string; url: string }[];
  _count?: { quotations: number };
  reactions?: JobReactionSummary;
}

export type JobFeedMode = 'discovery' | 'owned' | 'assigned';

const statusVariant: Record<string, 'default' | 'secondary' | 'success' | 'warning' | 'destructive'> = {
  OPEN: 'success',
  QUOTED: 'warning',
  ACCEPTED: 'default',
  IN_PROGRESS: 'warning',
  COMPLETED: 'secondary',
  CANCELLED: 'destructive',
};

function isRecentJob(createdAt: string) {
  const days = (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);
  return days <= 3;
}

function getCustomerLabel(job: FeedJob) {
  if (job.customer) return `${job.customer.firstName} ${job.customer.lastName}`;
  if (job.guestName?.trim()) return job.guestName.trim();
  return 'A customer';
}

function formatStatus(status: string) {
  return status.replace(/_/g, ' ');
}

export function JobFeedCard({
  job,
  href,
  mode = 'discovery',
  viewerUser,
  onReact,
  reactionsDisabled = false,
}: {
  job: FeedJob;
  href: string;
  mode?: JobFeedMode;
  viewerUser?: { firstName: string; lastName: string; avatarUrl?: string | null };
  onReact?: (jobId: string, type: JobReactionType) => void;
  reactionsDisabled?: boolean;
}) {
  const isRecent = mode === 'discovery' && isRecentJob(job.createdAt);
  const quoteCount = job._count?.quotations ?? 0;
  const coverImage = job.images?.[0]?.url ? getUploadUrl(job.images[0].url) : null;

  let headerName: string;
  let headerLine: ReactNode;
  let avatarFirstName: string | undefined;
  let avatarLastName: string | undefined;
  let avatarUrl: string | null | undefined;
  let avatarFallback: ReactNode | undefined;

  if (mode === 'owned' && viewerUser) {
    headerName = 'You';
    avatarFirstName = viewerUser.firstName;
    avatarLastName = viewerUser.lastName;
    avatarUrl = viewerUser.avatarUrl;
    headerLine = (
      <>
        <span className="font-semibold">You</span>
        <span className="text-muted"> posted a job</span>
        {job.category ? (
          <span className="text-muted">
            {' '}
            in <span className="font-medium text-slate-700">{job.category.name}</span>
          </span>
        ) : null}
      </>
    );
  } else if (mode === 'assigned') {
    const customer = getCustomerLabel(job);
    headerName = customer;
    avatarFirstName = job.customer?.firstName;
    avatarLastName = job.customer?.lastName;
    avatarUrl = job.customer?.avatarUrl;
    if (!job.customer) {
      avatarFallback = <Briefcase className="h-5 w-5" />;
    }
    headerLine = (
      <>
        <span className="font-semibold">{customer}</span>
        <span className="text-muted"> · active job with you</span>
      </>
    );
  } else {
    headerName = getCustomerLabel(job);
    avatarFirstName = job.customer?.firstName ?? headerName;
    avatarLastName = job.customer?.lastName ?? '';
    avatarUrl = job.customer?.avatarUrl;
    headerLine = (
      <>
        <span className="font-semibold">{headerName}</span>
        <span className="text-muted"> posted a job</span>
        {job.category ? (
          <span className="text-muted">
            {' '}
            in <span className="font-medium text-slate-700">{job.category.name}</span>
          </span>
        ) : null}
      </>
    );
  }

  return (
    <article className="overflow-hidden rounded-xl border border-border bg-surface shadow-sm">
      <div className="flex items-start gap-3 p-4 pb-3">
        <UserAvatar
          firstName={avatarFirstName}
          lastName={avatarLastName}
          avatarUrl={avatarUrl}
          size="feed"
          ringClassName="ring-2 ring-slate-100"
          fallback={avatarFallback}
        />
        <div className="min-w-0 flex-1 pt-0.5">
          <p className="text-sm leading-snug text-slate-900">{headerLine}</p>
          <p className="mt-0.5 text-xs text-muted">{formatRelativeTime(job.createdAt)}</p>
        </div>
        <div className="flex shrink-0 flex-wrap justify-end gap-1">
          {(mode === 'owned' || mode === 'assigned') && (
            <Badge variant={statusVariant[job.status] || 'secondary'} className="normal-case tracking-normal">
              {formatStatus(job.status)}
            </Badge>
          )}
          {isRecent && (
            <Badge className="normal-case tracking-normal bg-primary/10 text-primary border-0">
              New
            </Badge>
          )}
        </div>
      </div>

      <Link href={href} className="block px-4 pb-3 group">
        <h2 className="text-lg font-bold text-slate-900 leading-snug group-hover:text-primary transition-colors">
          {job.title}
        </h2>
        <p className="mt-2 text-sm text-slate-600 leading-relaxed line-clamp-4 whitespace-pre-line">
          {job.description}
        </p>
      </Link>

      {coverImage ? (
        <Link href={href} className="block border-y border-border bg-slate-50">
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img src={coverImage} alt="" className="max-h-72 w-full object-cover" />
        </Link>
      ) : null}

      <div className="space-y-3 p-4 pt-3">
        <div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted">
          <span className="inline-flex items-center gap-1.5">
            <MapPin className="h-4 w-4 shrink-0 text-slate-400" />
            {job.location}
          </span>
          {job.budget ? (
            <span className="inline-flex items-center gap-1.5 font-semibold text-accent">
              <Banknote className="h-4 w-4 shrink-0" />
              {formatCurrency(Number(job.budget))}
            </span>
          ) : (
            <span className="text-xs">Budget negotiable</span>
          )}
          {quoteCount > 0 && (
            <span className="inline-flex items-center gap-1.5 text-primary">
              <MessageSquare className="h-4 w-4 shrink-0" />
              {quoteCount} quote{quoteCount > 1 ? 's' : ''}
            </span>
          )}
        </div>

        {mode === 'discovery' && onReact ? (
          <JobFeedReactions job={job} onReact={onReact} disabled={reactionsDisabled} />
        ) : null}

        <div className="flex items-center gap-2 border-t border-border pt-3">
          <Link href={href} className="flex-1">
            <Button variant="outline" size="sm" className="w-full">
              View details
            </Button>
          </Link>
          {mode === 'discovery' && (
            <Link href={href} className="flex-1">
              <Button size="sm" className="w-full gap-1.5">
                <Sparkles className="h-4 w-4" />
                Submit application
              </Button>
            </Link>
          )}
          {mode === 'owned' && quoteCount > 0 && (
            <Link href={href} className="flex-1">
              <Button size="sm" className="w-full gap-1.5">
                <MessageSquare className="h-4 w-4" />
                View quotes
              </Button>
            </Link>
          )}
        </div>
      </div>
    </article>
  );
}

export function JobFeedList({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) {
  return <div className={cn('space-y-4', className)}>{children}</div>;
}

export function JobFeedSkeleton({ count = 3 }: { count?: number }) {
  return (
    <JobFeedList>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} className="rounded-xl border border-border bg-surface p-4 animate-pulse">
          <div className="flex gap-3">
            <div className="h-11 w-11 rounded-full bg-slate-200 shrink-0" />
            <div className="flex-1 space-y-2">
              <div className="h-4 w-2/3 rounded bg-slate-200" />
              <div className="h-3 w-20 rounded bg-slate-100" />
            </div>
          </div>
          <div className="mt-4 space-y-2">
            <div className="h-5 w-4/5 rounded bg-slate-200" />
            <div className="h-4 w-full rounded bg-slate-100" />
            <div className="h-4 w-full rounded bg-slate-100" />
          </div>
          <div className="mt-4 h-9 rounded bg-slate-100" />
        </div>
      ))}
    </JobFeedList>
  );
}

export type JobFeedFilter = 'all' | 'new';

export type WorkerJobFeedSort = 'newest' | 'budget-high' | 'budget-low';

export interface WorkerJobFeedFilters {
  feed: JobFeedFilter;
  categorySlug: string;
  regionSlug: string;
  sort: WorkerJobFeedSort;
  hasBudget: 'all' | 'yes' | 'no';
  status: 'all' | 'OPEN' | 'QUOTED';
}

export const defaultWorkerJobFeedFilters: WorkerJobFeedFilters = {
  feed: 'all',
  categorySlug: '',
  regionSlug: '',
  sort: 'newest',
  hasBudget: 'all',
  status: 'all',
};

export function countActiveWorkerJobFeedFilters(filters: WorkerJobFeedFilters) {
  let count = 0;
  if (filters.feed !== 'all') count += 1;
  if (filters.categorySlug) count += 1;
  if (isRegionFilterActive(filters.regionSlug)) count += 1;
  if (filters.sort !== 'newest') count += 1;
  if (filters.hasBudget !== 'all') count += 1;
  if (filters.status !== 'all') count += 1;
  return count;
}

export function applyWorkerJobFeedFilters(
  jobs: FeedJob[],
  filters: WorkerJobFeedFilters
) {
  let result = filterDiscoveryFeedJobs(jobs, filters.feed);

  if (filters.categorySlug) {
    result = result.filter((j) => j.category?.slug === filters.categorySlug);
  }

  if (isRegionFilterActive(filters.regionSlug)) {
    result = result.filter((j) => jobMatchesRegion(j.location, filters.regionSlug));
  }

  if (filters.status !== 'all') {
    result = result.filter((j) => j.status === filters.status);
  }

  if (filters.hasBudget === 'yes') {
    result = result.filter((j) => j.budget != null && Number(j.budget) > 0);
  } else if (filters.hasBudget === 'no') {
    result = result.filter((j) => !j.budget || Number(j.budget) <= 0);
  }

  const copy = [...result];
  if (filters.sort === 'budget-high') {
    return copy.sort((a, b) => Number(b.budget ?? 0) - Number(a.budget ?? 0));
  }
  if (filters.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).getTime() - new Date(a.createdAt).getTime()
  );
}

export function filterDiscoveryFeedJobs(
  jobs: FeedJob[],
  filter: JobFeedFilter
) {
  if (filter === 'new') {
    return jobs.filter((j) => isRecentJob(j.createdAt));
  }
  return jobs;
}

export type CustomerJobFeedFilter = 'all' | 'open' | 'active' | 'completed';

export type CustomerJobListSort = 'newest' | 'budget-high' | 'budget-low';

export interface CustomerJobListFilters {
  feed: CustomerJobFeedFilter;
  sort: CustomerJobListSort;
}

export const defaultCustomerJobListFilters: CustomerJobListFilters = {
  feed: 'all',
  sort: 'newest',
};

export function countActiveCustomerJobListFilters(filters: CustomerJobListFilters) {
  let count = 0;
  if (filters.feed !== 'all') count += 1;
  if (filters.sort !== 'newest') count += 1;
  return count;
}

export function applyCustomerJobListFilters(jobs: FeedJob[], filters: CustomerJobListFilters) {
  const result = filterCustomerFeedJobs(jobs, filters.feed);

  const copy = [...result];
  if (filters.sort === 'budget-high') {
    return copy.sort((a, b) => Number(b.budget ?? 0) - Number(a.budget ?? 0));
  }
  if (filters.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).getTime() - new Date(a.createdAt).getTime()
  );
}

export function filterCustomerFeedJobs(jobs: FeedJob[], filter: CustomerJobFeedFilter) {
  if (filter === 'open') return jobs.filter((j) => j.status === 'OPEN');
  if (filter === 'active') {
    return jobs.filter((j) => ['QUOTED', 'ACCEPTED', 'IN_PROGRESS'].includes(j.status));
  }
  if (filter === 'completed') {
    return jobs.filter((j) => j.status === 'COMPLETED');
  }
  return jobs;
}

function FeedFilterChips<T extends string>({
  tabs,
  value,
  onChange,
}: {
  tabs: { key: T; label: string; count: number }[];
  value: T;
  onChange: (value: T) => void;
}) {
  return (
    <div className="flex gap-2 overflow-x-auto pb-1 -mx-1 px-1 scrollbar-none">
      {tabs.map((tab) => (
        <button
          key={tab.key}
          type="button"
          onClick={() => onChange(tab.key)}
          className={cn(
            'shrink-0 rounded-full px-4 py-2 text-sm font-semibold transition-colors',
            value === tab.key
              ? 'bg-primary text-white shadow-sm'
              : 'bg-slate-100 text-slate-600 hover:bg-slate-200'
          )}
        >
          {tab.label}
          <span
            className={cn(
              'ml-1.5 tabular-nums',
              value === tab.key ? 'text-white/80' : 'text-muted'
            )}
          >
            {tab.count}
          </span>
        </button>
      ))}
    </div>
  );
}

export function DiscoveryJobFeedFilters({
  value,
  onChange,
  counts,
}: {
  value: JobFeedFilter;
  onChange: (filter: JobFeedFilter) => void;
  counts: { all: number; new: number };
}) {
  return (
    <FeedFilterChips
      value={value}
      onChange={onChange}
      tabs={[
        { key: 'all', label: 'All', count: counts.all },
        { key: 'new', label: 'New', count: counts.new },
      ]}
    />
  );
}

export function CustomerJobFeedFilters({
  value,
  onChange,
  counts,
}: {
  value: CustomerJobFeedFilter;
  onChange: (filter: CustomerJobFeedFilter) => void;
  counts: { all: number; open: number; active: number; completed: number };
}) {
  return (
    <FeedFilterChips
      value={value}
      onChange={onChange}
      tabs={[
        { key: 'all', label: 'All', count: counts.all },
        { key: 'open', label: 'Open', count: counts.open },
        { key: 'active', label: 'Active', count: counts.active },
        { key: 'completed', label: 'Completed', count: counts.completed },
      ]}
    />
  );
}

export function JobFeedEmpty({
  title,
  body,
}: {
  title: string;
  body: string;
}) {
  return (
    <div className="rounded-xl border border-dashed border-border bg-slate-50 px-6 py-12 text-center">
      <div className="mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-full bg-slate-200 text-slate-500">
        <UserRound className="h-6 w-6" />
      </div>
      <p className="font-semibold text-slate-900">{title}</p>
      <p className="mt-1 text-sm text-muted max-w-sm mx-auto">{body}</p>
    </div>
  );
}

// Backward-compatible aliases
export type WorkerFeedJob = FeedJob;
export const WorkerJobFeedCard = (props: Parameters<typeof JobFeedCard>[0]) => (
  <JobFeedCard {...props} mode="discovery" />
);
export const WorkerJobFeedSkeleton = JobFeedSkeleton;
export const JobFeedFilters = DiscoveryJobFeedFilters;
export const filterFeedJobs = filterDiscoveryFeedJobs;
export function WorkerJobFeedEmpty({ filter }: { filter: JobFeedFilter }) {
  const messages: Record<JobFeedFilter, { title: string; body: string }> = {
    all: {
      title: 'No jobs in your feed yet',
      body: 'New customer posts will show up here. Check back soon or update your skills and service areas.',
    },
    new: {
      title: 'No new posts',
      body: 'Jobs posted in the last few days will show up in this tab.',
    },
  };
  const msg = messages[filter];
  return <JobFeedEmpty title={msg.title} body={msg.body} />;
}
