'use client';

import { useState, useEffect, useRef } from 'react';
import { CheckCircle2, Clock, Loader2, Wrench, BarChart2, ClipboardList } from 'lucide-react';
import Link from 'next/link';
import { useTranslations } from 'next-intl';
import { trpc } from '@/lib/trpc/client';
import type { RouterOutputs } from '@/lib/trpc/server';
import { LanguageSwitcher } from '../language-switcher';

type Status = 'OPEN' | 'CLAIMED' | 'RESOLVED';
type QueueItem = RouterOutputs['maintenanceRequest']['queue']['items'][number];

// ── Helpers ────────────────────────────────────────────────────────────────

type TFn = (key: string, values?: Record<string, string | number>) => string;

function timeAgo(date: Date | string, t: TFn): string {
  const diffMs = Date.now() - new Date(date).getTime();
  const mins = Math.floor(diffMs / 60_000);
  if (mins < 1) return t('timeAgo.now');
  if (mins < 60) return t('timeAgo.minutesAgo', { mins });
  const hours = Math.floor(mins / 60);
  if (hours < 24) return t('timeAgo.hoursAgo', { hours });
  return t('timeAgo.daysAgo', { days: Math.floor(hours / 24) });
}

function playBeep() {
  try {
    const ctx = new AudioContext();
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.connect(gain);
    gain.connect(ctx.destination);
    osc.type = 'sine';
    osc.frequency.value = 880;
    gain.gain.setValueAtTime(0.2, ctx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.4);
    osc.start(ctx.currentTime);
    osc.stop(ctx.currentTime + 0.4);
  } catch {
    // AudioContext may be blocked before user interaction — ignore.
  }
}

const STATUS_CLASS: Record<Status, string> = {
  OPEN: 'bg-orange-100 text-orange-700',
  CLAIMED: 'bg-blue-100 text-blue-700',
  RESOLVED: 'bg-green-100 text-green-700',
};

// ── Thumbnail ───────────────────────────────────────────────────────────────

function Thumbnail({ photoKey, alt }: { photoKey: string | null; alt: string }) {
  const { data } = trpc.storage.signPhotoDownload.useQuery(
    { photoKey: photoKey! },
    { enabled: !!photoKey, staleTime: 50_000 },
  );
  if (!photoKey) {
    return <div className="h-16 w-16 shrink-0 rounded-lg bg-muted" />;
  }
  if (!data?.url) {
    return <div className="h-16 w-16 shrink-0 animate-pulse rounded-lg bg-muted" />;
  }
  return (
    // eslint-disable-next-line @next/next/no-img-element
    <img src={data.url} alt={alt} className="h-16 w-16 shrink-0 rounded-lg object-cover" />
  );
}

// ── Request card ────────────────────────────────────────────────────────────

function RequestCard({
  item,
  onClaim,
  onResolve,
  claiming,
  t,
  tc,
}: {
  item: QueueItem;
  onClaim: () => void;
  onResolve: () => void;
  claiming: boolean;
  t: ReturnType<typeof useTranslations<'maintenance'>>;
  tc: ReturnType<typeof useTranslations<'common'>>;
}) {
  return (
    <div data-testid="request-card" className="flex flex-col gap-3 rounded-xl border border-border bg-card p-4 shadow-sm">
      {/* Top row: thumbnail + main info */}
      <div className="flex gap-3">
        <Thumbnail photoKey={item.photoKey} alt={t('photo')} />
        <div className="min-w-0 flex-1">
          <p className="font-medium">
            {item.workstation.code} — {item.workstation.name}{' '}
            <span className="text-xs text-muted-foreground">· {item.workstation.area}</span>
          </p>
          <p className="mt-0.5 line-clamp-2 text-sm text-muted-foreground">{item.description}</p>
          <p className="mt-1 text-xs text-muted-foreground">
            {t('reportedBy', { email: item.reportedBy.email, time: timeAgo(item.createdAt, tc) })}
          </p>
        </div>
      </div>

      {/* Footer: badge + actions */}
      <div className="flex items-center justify-between gap-3">
        <span className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${STATUS_CLASS[item.status as Status]}`}>
          {tc(`status.${item.status.toLowerCase() as 'open' | 'claimed' | 'resolved'}`)}
        </span>

        {item.status === 'OPEN' && (
          <button
            onClick={onClaim}
            disabled={claiming}
            className="flex items-center gap-1.5 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50"
          >
            {claiming ? <Loader2 className="h-4 w-4 animate-spin" /> : <Wrench className="h-4 w-4" />}
            {t('accept')}
          </button>
        )}

        {item.status === 'CLAIMED' && (
          <div className="flex items-center gap-3">
            <p className="text-xs text-muted-foreground">
              {t('claimedBy', { email: item.claimedBy?.email ?? '?', time: timeAgo(item.claimedAt!, tc) })}
            </p>
            <button
              onClick={onResolve}
              className="flex items-center gap-1.5 rounded-lg bg-green-600 px-4 py-2 text-sm font-medium text-white hover:opacity-90"
            >
              <CheckCircle2 className="h-4 w-4" />
              {t('markResolved')}
            </button>
          </div>
        )}

        {item.status === 'RESOLVED' && (
          <p className="text-xs text-muted-foreground">
            {t('resolvedBy', { email: item.resolvedBy?.email ?? '?', time: timeAgo(item.resolvedAt!, tc) })}
          </p>
        )}
      </div>
    </div>
  );
}

// ── Resolve dialog ──────────────────────────────────────────────────────────

function ResolveDialog({
  onConfirm,
  onCancel,
  note,
  onNoteChange,
  resolving,
  t,
  tc,
}: {
  onConfirm: () => void;
  onCancel: () => void;
  note: string;
  onNoteChange: (v: string) => void;
  resolving: boolean;
  t: ReturnType<typeof useTranslations<'maintenance'>>;
  tc: ReturnType<typeof useTranslations<'common'>>;
}) {
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
      <div className="w-full max-w-md rounded-2xl bg-card p-6 shadow-xl">
        <h2 className="mb-4 text-lg font-semibold">{t('resolveDialogTitle')}</h2>
        <label className="mb-1 block text-sm font-medium">
          {t('resolveNoteLabel')}
        </label>
        <textarea
          value={note}
          onChange={(e) => onNoteChange(e.target.value)}
          rows={3}
          placeholder={t('resolveNotePlaceholder')}
          className="mb-4 w-full resize-none rounded-lg border border-border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
        />
        <div className="flex justify-end gap-3">
          <button onClick={onCancel} className="rounded-lg px-4 py-2 text-sm hover:bg-accent">
            {tc('cancel')}
          </button>
          <button
            onClick={onConfirm}
            disabled={resolving}
            className="flex items-center gap-1.5 rounded-lg bg-green-600 px-4 py-2 text-sm font-medium text-white hover:opacity-90 disabled:opacity-50"
          >
            {resolving && <Loader2 className="h-4 w-4 animate-spin" />}
            {tc('confirm')}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Main queue component ────────────────────────────────────────────────────

export function MaintenanceQueue() {
  const t = useTranslations('maintenance');
  const tc = useTranslations('common');

  const [statuses, setStatuses] = useState<Status[]>(['OPEN', 'CLAIMED']);
  const [area, setArea] = useState('');
  const [resolveId, setResolveId] = useState<string | null>(null);
  const [resolutionNote, setResolutionNote] = useState('');
  const [soundEnabled, setSoundEnabled] = useState(false);

  const { data, refetch } = trpc.maintenanceRequest.queue.useQuery(
    {
      statuses: statuses.length > 0 ? statuses : undefined,
      area: area || undefined,
    },
    { refetchInterval: 5000, refetchIntervalInBackground: false },
  );

  const items = data?.items ?? [];
  const openCount = items.filter((i) => i.status === 'OPEN').length;

  // Document title badge
  useEffect(() => {
    document.title =
      openCount > 0
        ? t('documentTitleWithCount', { count: openCount })
        : t('documentTitle');
  }, [openCount, t]);

  // Audio notification for new OPEN requests
  const prevOpenIds = useRef(new Set<string>());
  useEffect(() => {
    const currentIds = new Set(items.filter((i) => i.status === 'OPEN').map((i) => i.id));
    const hasNew = [...currentIds].some((id) => !prevOpenIds.current.has(id));
    if (hasNew && prevOpenIds.current.size > 0 && soundEnabled) {
      playBeep();
    }
    prevOpenIds.current = currentIds;
  }, [items, soundEnabled]);

  const claimMutation = trpc.maintenanceRequest.claim.useMutation({
    onSuccess: () => refetch(),
  });
  const resolveMutation = trpc.maintenanceRequest.resolve.useMutation({
    onSuccess: () => {
      setResolveId(null);
      refetch();
    },
  });

  const areas = [...new Set(items.map((i) => i.workstation.area))].sort();

  function toggleStatus(s: Status) {
    setStatuses((prev) =>
      prev.includes(s) ? prev.filter((x) => x !== s) : [...prev, s],
    );
  }

  return (
    <div className="min-h-screen bg-background">
      {/* Header */}
      <header className="sticky top-0 z-10 border-b border-border bg-card px-4 py-3">
        <div className="mx-auto flex max-w-4xl items-center justify-between gap-4">
          <div className="flex items-center gap-3">
            <h1 className="text-lg font-bold">
              {openCount > 0 ? (
                <span>
                  <span className="mr-1.5 inline-flex h-6 w-6 items-center justify-center rounded-full bg-orange-500 text-xs text-white">
                    {openCount}
                  </span>
                  {t('openRequestsTitle', { count: openCount })}
                </span>
              ) : (
                t('queueTitle')
              )}
            </h1>
          </div>
          <div className="flex items-center gap-2 text-sm">
            <Link
              href="/quality"
              className="flex items-center gap-1.5 rounded-full bg-muted px-3 py-1 text-xs font-medium text-muted-foreground hover:bg-accent"
            >
              <ClipboardList className="h-3 w-3" />
              {t('qualityLink')}
            </Link>
            <Link
              href="/maintenance/report"
              className="flex items-center gap-1.5 rounded-full bg-muted px-3 py-1 text-xs font-medium text-muted-foreground hover:bg-accent"
            >
              <BarChart2 className="h-3 w-3" />
              {t('reportLink')}
            </Link>
            <button
              onClick={() => setSoundEnabled((v) => !v)}
              className={`rounded-full px-3 py-1 text-xs font-medium transition-colors ${
                soundEnabled
                  ? 'bg-primary text-primary-foreground'
                  : 'bg-muted text-muted-foreground'
              }`}
            >
              {soundEnabled ? t('soundOn') : t('soundOff')}
            </button>
            <LanguageSwitcher />
          </div>
        </div>

        {/* Filters */}
        <div className="mx-auto mt-2 flex max-w-4xl flex-wrap items-center gap-3">
          <span className="text-xs text-muted-foreground">{t('filterStatus')}</span>
          {(['OPEN', 'CLAIMED', 'RESOLVED'] as Status[]).map((s) => (
            <label key={s} className="flex cursor-pointer items-center gap-1.5 text-sm">
              <input
                type="checkbox"
                checked={statuses.includes(s)}
                onChange={() => toggleStatus(s)}
                className="rounded"
              />
              {tc(`status.${s.toLowerCase() as 'open' | 'claimed' | 'resolved'}`)}
            </label>
          ))}

          {areas.length > 0 && (
            <>
              <span className="text-xs text-muted-foreground">{t('filterArea')}</span>
              <select
                value={area}
                onChange={(e) => setArea(e.target.value)}
                className="rounded-lg border border-border bg-card px-2 py-1 text-sm"
              >
                <option value="">{tc('allAreas')}</option>
                {areas.map((a) => (
                  <option key={a} value={a}>
                    {a}
                  </option>
                ))}
              </select>
            </>
          )}

          <div className="ml-auto flex items-center gap-1 text-xs text-muted-foreground">
            <Clock className="h-3 w-3" />
            {t('updatesEvery')}
          </div>
        </div>
      </header>

      {/* Cards */}
      <main className="mx-auto max-w-4xl p-4">
        {items.length === 0 ? (
          <div className="py-16 text-center text-muted-foreground">
            <Wrench className="mx-auto mb-3 h-10 w-10 opacity-30" />
            <p>{t('emptyQueue')}</p>
          </div>
        ) : (
          <div className="grid gap-3 sm:grid-cols-2">
            {items.map((item) => (
              <RequestCard
                key={item.id}
                item={item}
                t={t}
                tc={tc}
                onClaim={() => claimMutation.mutate({ id: item.id })}
                onResolve={() => {
                  setResolveId(item.id);
                  setResolutionNote('');
                }}
                claiming={
                  claimMutation.isPending &&
                  claimMutation.variables?.id === item.id
                }
              />
            ))}
          </div>
        )}
      </main>

      {/* Resolve dialog */}
      {resolveId && (
        <ResolveDialog
          note={resolutionNote}
          onNoteChange={setResolutionNote}
          t={t}
          tc={tc}
          onConfirm={() =>
            resolveMutation.mutate({
              id: resolveId,
              resolutionNote: resolutionNote.trim() || undefined,
            })
          }
          onCancel={() => setResolveId(null)}
          resolving={resolveMutation.isPending}
        />
      )}
    </div>
  );
}
