'use client';

import { useEffect, useRef, useState, type ReactNode } from 'react';
import { useTranslations } from 'next-intl';
import { FileText, Paperclip } from 'lucide-react';
import { Button } from '@/components/ui/shared/Button';
import { DialogCloseButton } from '@/components/ui/shared/DialogCloseButton';
import {
  ResponsiveDialogOverlay,
  ResponsiveDialogPanel,
} from '@/components/ui/shared/ResponsiveDialog';
import { treatmentsApi } from '@/lib/api/treatments';
import type { TreatmentAttachmentMeta } from '@/types/treatment';

/** Match Dropdown control height (`py-2.5 sm:py-2` + text-base/sm + border). */
const CONTROL_H = 'h-[2.875rem] sm:h-9';
const THUMB_CLASS =
  'relative aspect-square h-full shrink-0 overflow-hidden rounded-[var(--radius-sm)] bg-background-secondary';

type AttachmentKind = 'image' | 'pdf' | 'file';

const ATTACHMENT_KIND_ORDER: AttachmentKind[] = ['image', 'pdf', 'file'];

function attachmentKind(mimeType: string): AttachmentKind {
  if (mimeType.startsWith('image/')) return 'image';
  if (mimeType === 'application/pdf') return 'pdf';
  return 'file';
}

function groupAttachmentsByKind(attachments: TreatmentAttachmentMeta[]) {
  const byKind: Record<AttachmentKind, TreatmentAttachmentMeta[]> = {
    image: [],
    pdf: [],
    file: [],
  };
  for (const item of attachments) {
    byKind[attachmentKind(item.mimeType)].push(item);
  }
  return ATTACHMENT_KIND_ORDER.filter((kind) => byKind[kind].length > 0).map((kind) => ({
    kind,
    items: byKind[kind],
  }));
}

function AttachmentGroup({ children }: { children: ReactNode }) {
  return (
    <div className="flex shrink-0 items-stretch gap-2 border-s border-border/60 px-2">
      {children}
    </div>
  );
}

type TreatmentDetailAttachmentsStripProps = {
  attachments: TreatmentAttachmentMeta[];
  disabled: boolean;
  uploadBusy: boolean;
  onUploadFiles: (files: File[], onProgress: (percent: number) => void) => Promise<void>;
  onRemoveAttachment?: (attachmentId: string) => void;
};

export function TreatmentDetailAttachmentsStrip({
  attachments,
  disabled,
  uploadBusy,
  onUploadFiles,
  onRemoveAttachment,
}: TreatmentDetailAttachmentsStripProps) {
  const t = useTranslations('treatment');
  const tCommon = useTranslations('common');
  const inputRef = useRef<HTMLInputElement>(null);
  const [uploadPercent, setUploadPercent] = useState<number | null>(null);
  const [previewId, setPreviewId] = useState<string | null>(null);

  const preview = attachments.find((item) => item.id === previewId) ?? null;
  const attachmentGroups = groupAttachmentsByKind(attachments);

  async function handleFiles(list: FileList | null) {
    if (!list?.length || disabled || uploadBusy) return;
    setUploadPercent(0);
    try {
      await onUploadFiles(Array.from(list), (percent) => setUploadPercent(percent));
    } finally {
      setUploadPercent(null);
      if (inputRef.current) inputRef.current.value = '';
    }
  }

  return (
    <div className="min-w-0">
      <p className="block text-sm font-medium text-text-secondary mb-1">{t('attachments')}</p>
      <div
        className={`
          flex min-w-0 items-stretch overflow-hidden rounded-[var(--radius-md)] border border-border
          bg-background-card ${CONTROL_H}
          ${disabled ? 'opacity-50' : ''}
        `}
      >
        <input
          ref={inputRef}
          type="file"
          multiple
          disabled={disabled || uploadBusy}
          onChange={(e) => void handleFiles(e.target.files)}
          className="sr-only"
          aria-label={t('attachFiles')}
        />
        <button
          type="button"
          disabled={disabled || uploadBusy}
          onClick={() => inputRef.current?.click()}
          title={t('chooseFiles')}
          aria-label={t('chooseFiles')}
          className={`
            inline-flex aspect-square h-full shrink-0 items-center justify-center
            text-text-secondary hover:bg-background-card/80 hover:text-text-primary
            focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/35
            disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-inherit
          `}
        >
          <Paperclip className="h-4 w-4" aria-hidden />
        </button>
        <div className="flex min-w-0 flex-1 items-stretch overflow-x-auto py-1 pe-0.5">
          {uploadBusy ? (
            <AttachmentGroup>
              <div
                className={THUMB_CLASS}
                role="progressbar"
                aria-valuemin={0}
                aria-valuemax={100}
                aria-valuenow={uploadPercent ?? 0}
                aria-label={t('saveStatusSaving')}
              >
                <div className="absolute inset-0 flex items-center justify-center p-1.5">
                  <div className="h-1.5 w-full overflow-hidden rounded-full bg-border">
                    <div
                      className={`h-full rounded-full bg-primary ${uploadPercent ? 'transition-[width]' : 'animate-pulse'}`}
                      style={{ width: `${Math.max(uploadPercent ?? 8, 8)}%` }}
                    />
                  </div>
                </div>
              </div>
            </AttachmentGroup>
          ) : null}
          {attachmentGroups.map((group) => (
            <AttachmentGroup key={group.kind}>
              {group.items.map((file) => (
                <button
                  key={file.id}
                  type="button"
                  title={file.fileName}
                  onClick={() => setPreviewId(file.id)}
                  className={`${THUMB_CLASS} focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/35`}
                >
                  <AttachmentThumb attachment={file} />
                </button>
              ))}
            </AttachmentGroup>
          ))}
        </div>
      </div>

      {preview ? (
        <ResponsiveDialogOverlay onBackdropClick={() => setPreviewId(null)}>
          <ResponsiveDialogPanel
            role="dialog"
            aria-modal="true"
            aria-labelledby="treatment-attachment-preview-title"
            maxWidthClass="sm:max-w-lg"
          >
            <div className="mb-3 flex items-start justify-between gap-2">
              <h4
                id="treatment-attachment-preview-title"
                className="min-w-0 truncate text-sm font-semibold text-text-primary pe-2"
                title={preview.fileName}
              >
                {preview.fileName}
              </h4>
              <DialogCloseButton onClick={() => setPreviewId(null)} />
            </div>
            <AttachmentPreviewBody attachment={preview} />
            <div className="mt-4 flex flex-wrap justify-end gap-2">
              {onRemoveAttachment && !disabled ? (
                <Button
                  type="button"
                  variant="danger"
                  onClick={() => {
                    onRemoveAttachment(preview.id);
                    setPreviewId(null);
                  }}
                >
                  {tCommon('delete')}
                </Button>
              ) : null}
              <Button type="button" variant="outline" onClick={() => setPreviewId(null)}>
                {tCommon('close')}
              </Button>
            </div>
          </ResponsiveDialogPanel>
        </ResponsiveDialogOverlay>
      ) : null}
    </div>
  );
}

function AttachmentThumb({ attachment }: { attachment: TreatmentAttachmentMeta }) {
  const { url, failed } = useAttachmentUrl(attachment.id);
  if (url && attachment.mimeType.startsWith('image/') && !failed) {
    return <img src={url} alt="" className="h-full w-full object-cover" />;
  }
  return (
    <span className="flex h-full w-full items-center justify-center text-text-muted">
      <FileText className="h-4 w-4" aria-hidden />
    </span>
  );
}

function AttachmentPreviewBody({ attachment }: { attachment: TreatmentAttachmentMeta }) {
  const t = useTranslations('treatment');
  const { url, failed } = useAttachmentUrl(attachment.id);
  if (failed || !url) {
    return <p className="text-sm text-text-muted">{t('attachmentPreviewUnavailable')}</p>;
  }
  if (attachment.mimeType.startsWith('image/')) {
    return (
      <img
        src={url}
        alt={attachment.fileName}
        className="max-h-[min(24rem,60vh)] w-full rounded-[var(--radius-md)] object-contain bg-background-secondary"
      />
    );
  }
  if (attachment.mimeType === 'application/pdf') {
    return (
      <iframe
        src={url}
        title={attachment.fileName}
        className="h-[min(24rem,60vh)] w-full rounded-[var(--radius-md)] border-0 bg-background-secondary"
      />
    );
  }
  return <p className="text-sm text-text-muted">{attachment.fileName}</p>;
}

function useAttachmentUrl(attachmentId: string) {
  const [url, setUrl] = useState<string | null>(null);
  const [failed, setFailed] = useState(false);

  useEffect(() => {
    let cancelled = false;
    let objectUrl: string | null = null;
    void (async () => {
      try {
        const blob = await treatmentsApi.getAttachmentFileBlob(attachmentId);
        if (cancelled) return;
        objectUrl = URL.createObjectURL(blob);
        setUrl(objectUrl);
        setFailed(false);
      } catch {
        if (!cancelled) setFailed(true);
      }
    })();
    return () => {
      cancelled = true;
      if (objectUrl) URL.revokeObjectURL(objectUrl);
    };
  }, [attachmentId]);

  return { url, failed };
}
