'use client';

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

type Defect = RouterOutputs['qualityDefect']['queue'][number];
type DefectStatus = 'OPEN' | 'ACKNOWLEDGED' | 'CORRECTED';
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('now');
  if (mins < 60) return t('minutesAgo', { mins });
  const hours = Math.floor(mins / 60);
  if (hours < 24) return t('hoursAgo', { hours });
  return t('daysAgo', { days: Math.floor(hours / 24) });
}

function compressImage(file: File): Promise<Blob> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      URL.revokeObjectURL(url);
      const MAX = 1600;
      let { width, height } = img;
      if (width > MAX || height > MAX) {
        if (width >= height) {
          height = Math.round((height * MAX) / width);
          width = MAX;
        } else {
          width = Math.round((width * MAX) / height);
          height = MAX;
        }
      }
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      const ctx = canvas.getContext('2d');
      if (!ctx) return reject(new Error('Canvas context unavailable'));
      ctx.drawImage(img, 0, 0, width, height);
      canvas.toBlob(
        (blob) => (blob ? resolve(blob) : reject(new Error('Canvas toBlob failed'))),
        'image/jpeg',
        0.8,
      );
    };
    img.onerror = () => reject(new Error('Image load failed'));
    img.src = url;
  });
}

const STATUS_CLASS: Record<DefectStatus, string> = {
  OPEN: 'bg-orange-100 text-orange-700',
  ACKNOWLEDGED: 'bg-blue-100 text-blue-700',
  CORRECTED: 'bg-green-100 text-green-700',
};

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 null;
  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" />
  );
}

// ── New-defect form ───────────────────────────────────────────────────────────

function NewDefectForm({
  onCreated,
  t,
}: {
  onCreated: () => void;
  t: ReturnType<typeof useTranslations<'quality'>>;
}) {
  const fileRef = useRef<HTMLInputElement>(null);
  const [workstationId, setWorkstationId] = useState('');
  const [defectType, setDefectType] = useState('');
  const [location, setLocation] = useState('');
  const [rfsCode, setRfsCode] = useState('');
  const [description, setDescription] = useState('');
  const [photoBlob, setPhotoBlob] = useState<Blob | null>(null);
  const [photoPreview, setPhotoPreview] = useState<string | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const { data: workstations = [] } = trpc.workstation.list.useQuery(undefined, {
    staleTime: 60 * 60 * 1000,
  });
  const signUpload = trpc.storage.signPhotoUpload.useMutation();
  const create = trpc.qualityDefect.create.useMutation();

  async function handlePhotoChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;
    try {
      const compressed = await compressImage(file);
      if (photoPreview) URL.revokeObjectURL(photoPreview);
      setPhotoBlob(compressed);
      setPhotoPreview(URL.createObjectURL(compressed));
    } catch {
      setError(t('form.photoError'));
    }
  }

  function removePhoto() {
    if (photoPreview) URL.revokeObjectURL(photoPreview);
    setPhotoBlob(null);
    setPhotoPreview(null);
    if (fileRef.current) fileRef.current.value = '';
  }

  function reset() {
    setWorkstationId('');
    setDefectType('');
    setLocation('');
    setRfsCode('');
    setDescription('');
    removePhoto();
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!workstationId || defectType.trim().length < 1 || description.trim().length < 3) return;
    setSubmitting(true);
    setError(null);
    try {
      let photoKey: string | undefined;
      if (photoBlob) {
        const signed = await signUpload.mutateAsync({
          contentType: 'image/jpeg',
          byteSize: photoBlob.size,
          category: 'quality',
        });
        const res = await fetch(signed.uploadUrl, {
          method: 'PUT',
          body: photoBlob,
          headers: { 'Content-Type': 'image/jpeg' },
        });
        if (!res.ok) throw new Error(`Photo PUT ${res.status}`);
        photoKey = signed.photoKey;
      }
      await create.mutateAsync({
        workstationId,
        defectType: defectType.trim(),
        location: location.trim() || undefined,
        rfsCode: rfsCode.trim() || undefined,
        description: description.trim(),
        photoKey,
      });
      reset();
      onCreated();
    } catch {
      setError(t('form.submitError'));
    } finally {
      setSubmitting(false);
    }
  }

  const canSubmit =
    workstationId !== '' &&
    defectType.trim().length >= 1 &&
    description.trim().length >= 3 &&
    !submitting;

  return (
    <form
      onSubmit={handleSubmit}
      className="flex flex-col gap-3 rounded-xl border border-border bg-card p-4 shadow-sm"
    >
      <h2 className="text-sm font-semibold">{t('newDefect')}</h2>

      <div className="grid gap-3 sm:grid-cols-2">
        <label className="flex flex-col gap-1 text-sm">
          <span className="font-medium">{t('form.workstation')}</span>
          <select
            value={workstationId}
            onChange={(e) => setWorkstationId(e.target.value)}
            required
            className="rounded-lg border border-border bg-background px-3 py-2 text-sm"
          >
            <option value="">{t('form.workstationPlaceholder')}</option>
            {workstations.map((ws) => (
              <option key={ws.id} value={ws.id}>
                {ws.code} — {ws.name} · {ws.area}
              </option>
            ))}
          </select>
        </label>

        <label className="flex flex-col gap-1 text-sm">
          <span className="font-medium">{t('form.defectType')}</span>
          <input
            type="text"
            value={defectType}
            onChange={(e) => setDefectType(e.target.value)}
            required
            maxLength={100}
            placeholder={t('form.defectTypePlaceholder')}
            className="rounded-lg border border-border bg-background px-3 py-2 text-sm"
          />
        </label>

        <label className="flex flex-col gap-1 text-sm">
          <span className="font-medium">{t('form.location')}</span>
          <input
            type="text"
            value={location}
            onChange={(e) => setLocation(e.target.value)}
            maxLength={200}
            placeholder={t('form.locationPlaceholder')}
            className="rounded-lg border border-border bg-background px-3 py-2 text-sm"
          />
        </label>

        <label className="flex flex-col gap-1 text-sm">
          <span className="font-medium">{t('form.rfs')}</span>
          <input
            type="text"
            value={rfsCode}
            onChange={(e) => setRfsCode(e.target.value)}
            maxLength={100}
            placeholder={t('form.rfsPlaceholder')}
            className="rounded-lg border border-border bg-background px-3 py-2 text-sm"
          />
        </label>
      </div>

      <label className="flex flex-col gap-1 text-sm">
        <span className="font-medium">{t('form.description')}</span>
        <textarea
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          required
          minLength={3}
          maxLength={1000}
          rows={2}
          placeholder={t('form.descriptionPlaceholder')}
          className="resize-none rounded-lg border border-border bg-background px-3 py-2 text-sm"
        />
      </label>

      {/* Photo */}
      <div className="flex items-center gap-3">
        {photoPreview ? (
          <div className="relative">
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src={photoPreview} alt="" className="h-16 w-16 rounded-lg object-cover" />
            <button
              type="button"
              onClick={removePhoto}
              className="absolute -right-2 -top-2 rounded-full bg-black/60 p-1 text-white hover:bg-black/80"
            >
              <X className="h-3 w-3" />
            </button>
          </div>
        ) : (
          <button
            type="button"
            onClick={() => fileRef.current?.click()}
            className="flex items-center gap-2 rounded-lg border border-dashed border-border px-3 py-2 text-sm text-muted-foreground hover:bg-accent"
          >
            <Camera className="h-4 w-4" />
            {t('form.photoButton')}
          </button>
        )}
        <input
          ref={fileRef}
          type="file"
          accept="image/*"
          className="hidden"
          onChange={handlePhotoChange}
        />

        <button
          type="submit"
          disabled={!canSubmit}
          className="ml-auto flex items-center gap-1.5 rounded-lg bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground hover:opacity-90 disabled:opacity-40"
        >
          {submitting ? <Loader2 className="h-4 w-4 animate-spin" /> : <AlertTriangle className="h-4 w-4" />}
          {submitting ? t('form.submitting') : t('form.submit')}
        </button>
      </div>

      {error && (
        <p className="rounded-lg bg-destructive/10 px-3 py-2 text-sm text-destructive">{error}</p>
      )}
    </form>
  );
}

// ── Defect card ───────────────────────────────────────────────────────────────

function DefectCard({
  defect,
  t,
  tTime,
}: {
  defect: Defect;
  t: ReturnType<typeof useTranslations<'quality'>>;
  tTime: TFn;
}) {
  const status = defect.status as DefectStatus;
  return (
    <div className="flex flex-col gap-3 rounded-xl border border-border bg-card p-4 shadow-sm">
      <div className="flex gap-3">
        <Thumbnail photoKey={defect.photoKey} alt={t('photoAlt')} />
        <div className="min-w-0 flex-1">
          <div className="flex items-start justify-between gap-2">
            <p className="font-medium">
              {defect.defectType}
              <span className="ml-1 text-xs text-muted-foreground">
                · {defect.workstation.code}
              </span>
            </p>
            <span className={`shrink-0 rounded-full px-2.5 py-0.5 text-xs font-medium ${STATUS_CLASS[status]}`}>
              {t(`status.${status.toLowerCase() as 'open' | 'acknowledged' | 'corrected'}`)}
            </span>
          </div>
          {defect.location && (
            <p className="mt-0.5 text-xs text-muted-foreground">
              {t('location')}: {defect.location}
            </p>
          )}
          <p className="mt-1 line-clamp-2 text-sm text-muted-foreground">{defect.description}</p>
          <div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-muted-foreground">
            {defect.rfsCode && (
              <span className="rounded bg-muted px-1.5 py-0.5 font-mono">
                {t('rfs')} {defect.rfsCode}
              </span>
            )}
            <span>{t('createdBy', { email: defect.createdBy.email, time: timeAgo(defect.createdAt, tTime) })}</span>
          </div>
          {defect.acknowledgedBy && defect.acknowledgedAt && (
            <p className="mt-0.5 text-xs text-blue-700">
              {t('acknowledgedBy', { email: defect.acknowledgedBy.email, time: timeAgo(defect.acknowledgedAt, tTime) })}
            </p>
          )}
          {defect.correctedBy && defect.correctedAt && (
            <p className="mt-0.5 text-xs text-green-700">
              {t('correctedBy', { email: defect.correctedBy.email, time: timeAgo(defect.correctedAt, tTime) })}
            </p>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Console ───────────────────────────────────────────────────────────────────

export function QualityConsole({ canCreate }: { canCreate: boolean }) {
  const t = useTranslations('quality');
  const tTime = useTranslations('common.timeAgo');

  const [statuses, setStatuses] = useState<DefectStatus[]>(['OPEN', 'ACKNOWLEDGED']);

  const { data: defects = [], refetch } = trpc.qualityDefect.queue.useQuery(
    { statuses: statuses.length > 0 ? statuses : undefined },
    { refetchInterval: 5000, refetchIntervalInBackground: false },
  );

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

  return (
    <div className="min-h-screen bg-background">
      <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">
          <h1 className="flex items-center gap-2 text-lg font-bold">
            <ClipboardList className="h-5 w-5" />
            {t('consoleTitle')}
          </h1>
          <div className="flex items-center gap-2 text-sm">
            <Link
              href="/maintenance"
              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"
            >
              <Wrench className="h-3 w-3" />
              {t('backToMaintenance')}
            </Link>
            <LanguageSwitcher />
          </div>
        </div>
      </header>

      <main className="mx-auto flex max-w-4xl flex-col gap-4 p-4">
        {canCreate && <NewDefectForm onCreated={() => refetch()} t={t} />}

        {/* Filters */}
        <div className="flex flex-wrap items-center gap-3">
          <span className="text-xs text-muted-foreground">{t('filterStatus')}</span>
          {(['OPEN', 'ACKNOWLEDGED', 'CORRECTED'] as DefectStatus[]).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"
              />
              {t(`status.${s.toLowerCase() as 'open' | 'acknowledged' | 'corrected'}`)}
            </label>
          ))}
          <span className="ml-auto text-xs text-muted-foreground">{t('updatesEvery')}</span>
        </div>

        {/* Queue */}
        <section>
          <h2 className="mb-3 text-sm font-medium text-muted-foreground">{t('queueTitle')}</h2>
          {defects.length === 0 ? (
            <div className="py-12 text-center text-muted-foreground">
              <ClipboardList className="mx-auto mb-3 h-10 w-10 opacity-30" />
              <p>{t('empty')}</p>
            </div>
          ) : (
            <div className="grid gap-3 sm:grid-cols-2">
              {defects.map((defect) => (
                <DefectCard key={defect.id} defect={defect} t={t} tTime={tTime} />
              ))}
            </div>
          )}
        </section>
      </main>
    </div>
  );
}
