'use client';

import { useEffect, useRef, type ReactNode, type RefObject } from 'react';
import { useTranslations } from 'next-intl';
import { Mic, Square, Trash2 } from 'lucide-react';
import { Button } from '@/components/ui/shared/Button';
import { Dropdown } from '@/components/ui/shared/Dropdown';
import { formatDetailChipLabel } from '@/components/treatment/detailChipLabel';
import { autosaveStatusClass, labBlockedBannerClass } from '@/components/treatment/treatmentStatusStyles';
import { TreatmentDetailAttachmentsStrip } from '@/components/ui/treatment/TreatmentDetailAttachmentsStrip';
import { VoiceRecordingBar } from '@/components/ui/treatment/VoiceRecordingBar';
import type { VoiceCaptureState } from '@/lib/voice/useVoiceCapture';
import type { TreatmentDetailDraft } from '@/types/treatment';
import type { TreatmentCatalogEntry } from '@/types/treatment-catalog';
import { treatmentTypeColor, treatmentTypeOptionStyle } from '@/components/shared/treatmentTypeDisplay';
import {
  isDetailTypeSelected,
  isLabDependentDetailMissingTeeth,
} from '@/components/treatment/treatmentDetailRules';

const WORKSPACE_ACTION_BTN_HEIGHT = 'h-[2.875rem] sm:h-9';
const WORKSPACE_ACTION_BTN_CLASS = `${WORKSPACE_ACTION_BTN_HEIGHT} shrink-0 px-3 text-sm`;

interface TreatmentDetailsEditorProps {
  details: TreatmentDetailDraft[];
  activeDetailId: string;
  onActiveDetailChange: (id: string) => void;
  onDetailsChange: (details: TreatmentDetailDraft[]) => void;
  isDetailLocked: (detail: TreatmentDetailDraft) => boolean;
  labDependentCodes: Set<string>;
  treatmentCatalog: TreatmentCatalogEntry[];
  disabled: boolean;
  canEdit: boolean;
  saveStatus: 'idle' | 'dirty' | 'saving' | 'saved' | 'error';
  uploadBusy: boolean;
  onAddDetail: () => void;
  onRemoveDetail?: (detailClientId: string) => void;
  onUploadFiles: (files: File[], onProgress: (percent: number) => void) => Promise<void>;
  onRemoveAttachment?: (attachmentId: string) => void;
  /** Detail chips + Add detail (default true). */
  showChrome?: boolean;
  /** Type / notes / attachments fields (default true). */
  showFields?: boolean;
  /** FDI chart (or other) rendered beside notes on wide screens. */
  chart?: ReactNode;
  /**
   * Voice entry. Omit when unavailable — the Add button then renders unsplit, exactly as
   * before this feature existed. Presence *is* the availability flag, so the two cannot
   * disagree.
   */
  voice?: VoiceCaptureState;
  /** Dim the chart until a treatment type is chosen. */
  chartLocked?: boolean;
  chartLockMessage?: string;
  /** Owned by TreatmentWorkspace so lab drafts can be wiped when leaving prosthesis. */
  onTreatmentTypeChange?: (nextType: string) => void;
  /** Arch-level jobs count as work for the missing-teeth lab banner. */
  hasArchJobs?: boolean;
  showLabDispatchToggle?: boolean;
  labWorkspaceView?: 'chart' | 'dispatch';
  onLabWorkspaceViewChange?: (view: 'chart' | 'dispatch') => void;
}

export function TreatmentDetailsEditor({
  details,
  activeDetailId,
  onActiveDetailChange,
  onDetailsChange,
  isDetailLocked,
  labDependentCodes,
  treatmentCatalog,
  disabled,
  canEdit,
  saveStatus,
  uploadBusy,
  onAddDetail,
  onRemoveDetail,
  onUploadFiles,
  onRemoveAttachment,
  showChrome = true,
  showFields = true,
  voice,
  chart,
  chartLocked = false,
  chartLockMessage,
  onTreatmentTypeChange,
  hasArchJobs = false,
  showLabDispatchToggle = false,
  labWorkspaceView = 'chart',
  onLabWorkspaceViewChange,
}: TreatmentDetailsEditorProps) {
  const t = useTranslations('treatment');
  const tCommon = useTranslations('common');
  const notesRef = useRef<HTMLTextAreaElement>(null);
  const activeDetail = details.find((d) => d.clientId === activeDetailId) ?? details[0];

  const locked = Boolean(activeDetail && isDetailLocked(activeDetail));
  const readOnly = !activeDetail || disabled || locked;
  const showMissingTeethLabBlock = Boolean(
    activeDetail &&
      isLabDependentDetailMissingTeeth(activeDetail, labDependentCodes, hasArchJobs),
  );

  if (!showChrome && !showFields) return null;

  const treatmentTypeTextColor =
    activeDetail && isDetailTypeSelected(activeDetail)
      ? treatmentTypeColor(
          activeDetail.treatmentType,
          treatmentCatalog.findIndex((e) => e.code === activeDetail.treatmentType),
        )
      : undefined;

  function setActiveType(nextType: string) {
    onDetailsChange(
      details.map((d) =>
        d.clientId === activeDetailId ? { ...d, treatmentType: nextType } : d,
      ),
    );
  }

  const actionWidthLabels = [t('showLabDispatch'), t('showChart'), t('addDetail')];

  return (
    <div className="surface-card p-3 sm:p-4 space-y-4">
      {showChrome ? (
        <>
          <div className="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between">
            <div>
              <h3 className="text-sm font-semibold text-text-primary">{t('detailsTitle')}</h3>
            </div>
            {voice ? (
              <AddDetailWithVoice
                addLabel={t('addDetail')}
                widthLabels={actionWidthLabels}
                startLabel={t('voiceStart')}
                stopLabel={t('voiceStop')}
                disabled={!canEdit || disabled}
                onAddDetail={onAddDetail}
                voice={voice}
              />
            ) : (
              <Button
                type="button"
                variant="primary"
                size="sm"
                disabled={!canEdit || disabled}
                onClick={onAddDetail}
                className={WORKSPACE_ACTION_BTN_CLASS}
              >
                <WorkspaceActionLabel label={t('addDetail')} widthLabels={actionWidthLabels} />
              </Button>
            )}
          </div>

          {voice ? <VoiceRecordingBar voice={voice} /> : null}

          <div className="flex flex-wrap gap-2">
            {details.map((d, idx) => {
              const detailLocked = isDetailLocked(d);
              const isActive = d.clientId === activeDetailId;
              const showRemoveAction = Boolean(onRemoveDetail);
              const removeDisabled = !canEdit || disabled || detailLocked || uploadBusy;
              const chipLabel = formatDetailChipLabel(
                d,
                treatmentCatalog,
                t('detailLabel', { n: idx + 1 }),
              );
              const showLabStatus =
                isDetailTypeSelected(d) && labDependentCodes.has(d.treatmentType);
              return (
                <div
                  key={d.clientId}
                  className={`
                    inline-flex items-stretch overflow-hidden rounded-[var(--radius-md)] border max-w-full
                    ${
                      isActive
                        ? 'border-primary bg-primary-soft'
                        : 'border-border/70 hover:border-border hover:bg-background-card/50'
                    }
                  `}
                >
                  <button
                    type="button"
                    onClick={() => onActiveDetailChange(d.clientId)}
                    title={chipLabel}
                    className={`
                      inline-flex max-w-[20rem] items-center gap-1.5 px-3 py-1.5 text-sm transition-colors
                      focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/45
                      ${isActive ? 'font-medium text-text-primary' : 'text-text-secondary'}
                    `}
                  >
                    <span className="truncate">{chipLabel}</span>
                    {showLabStatus ? (
                      <span
                        className={`shrink-0 ${
                          detailLocked
                            ? 'text-emerald-600 dark:text-emerald-400'
                            : 'text-amber-600 dark:text-amber-400'
                        }`}
                      >
                        · {detailLocked ? t('detailSentBadge') : t('detailUnsentBadge')}
                      </span>
                    ) : null}
                  </button>
                  {showRemoveAction ? (
                    <button
                      type="button"
                      onClick={(e) => {
                        e.stopPropagation();
                        if (removeDisabled) return;
                        onRemoveDetail?.(d.clientId);
                      }}
                      disabled={removeDisabled}
                      title={tCommon('delete')}
                      aria-label={t('removeDetailAria', { n: idx + 1 })}
                      className={`
                        inline-flex items-center justify-center border-s px-1.5 transition-colors
                        focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-red-500/40
                        disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-inherit
                        ${
                          isActive
                            ? 'border-primary/30 text-text-muted hover:bg-red-500/15 hover:text-red-600'
                            : 'border-border/60 text-text-muted hover:bg-red-500/15 hover:text-red-600'
                        }
                      `}
                    >
                      <Trash2 className="h-3.5 w-3.5" aria-hidden />
                    </button>
                  ) : null}
                </div>
              );
            })}
          </div>
        </>
      ) : null}

      {activeDetail && showMissingTeethLabBlock ? (
        <p className={labBlockedBannerClass}>{t('labShipmentBlockedBody')}</p>
      ) : null}

      {showFields && activeDetail ? (
        <div className="space-y-3">
          <div className="grid grid-cols-1 gap-3 sm:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] sm:items-end">
            <Dropdown
              label={t('treatmentType')}
              value={activeDetail.treatmentType}
              onChange={(e) =>
                (onTreatmentTypeChange ?? setActiveType)(e.target.value)
              }
              disabled={readOnly}
              style={{ color: treatmentTypeTextColor }}
            >
              <option value="">{t('treatmentTypePlaceholder')}</option>
              {treatmentCatalog.map((entry, index) => (
                <option key={entry.code} value={entry.code} style={treatmentTypeOptionStyle(entry.code, index)}>
                  {entry.label}
                </option>
              ))}
            </Dropdown>
            <TreatmentDetailAttachmentsStrip
              attachments={activeDetail.attachmentMetas}
              disabled={readOnly}
              uploadBusy={uploadBusy}
              onUploadFiles={onUploadFiles}
              onRemoveAttachment={readOnly ? undefined : onRemoveAttachment}
            />
            {showLabDispatchToggle ? (
              <Button
                type="button"
                variant={labWorkspaceView === 'dispatch' ? 'outline' : 'primary'}
                size="sm"
                className={`${WORKSPACE_ACTION_BTN_CLASS} ${
                  labWorkspaceView === 'dispatch' ? 'bg-background-secondary' : ''
                }`}
                onClick={() =>
                  onLabWorkspaceViewChange?.(
                    labWorkspaceView === 'dispatch' ? 'chart' : 'dispatch',
                  )
                }
              >
                <WorkspaceActionLabel
                  label={labWorkspaceView === 'dispatch' ? t('showChart') : t('showLabDispatch')}
                  widthLabels={actionWidthLabels}
                />
              </Button>
            ) : null}
          </div>

          {chart ? (
            <div className="relative min-w-0 w-full">
              {chartLocked ? (
                <div className="absolute inset-0 z-10 flex items-center justify-center rounded-[var(--radius-md)] bg-background-card/70 px-4">
                  <p className="text-sm text-text-secondary text-center">{chartLockMessage}</p>
                </div>
              ) : null}
              <div className={chartLocked ? 'pointer-events-none opacity-40' : undefined}>{chart}</div>
            </div>
          ) : null}

          <NotesField
            textareaRef={notesRef}
            value={activeDetail.comment}
            disabled={readOnly}
            label={t('comments')}
            placeholder={t('commentsPlaceholder')}
            onChange={(v) => {
              onDetailsChange(
                details.map((d) => (d.clientId === activeDetailId ? { ...d, comment: v } : d)),
              );
            }}
          />

          {canEdit && saveStatus !== 'idle' && (
            <p className={`text-xs ${autosaveStatusClass(saveStatus)}`} role="status" aria-live="polite">
              {saveStatus === 'dirty' && t('unsavedChanges')}
              {saveStatus === 'saving' && t('saveStatusSaving')}
              {saveStatus === 'saved' && t('saveStatusSaved')}
              {saveStatus === 'error' && t('saveStatusError')}
            </p>
          )}
        </div>
      ) : showFields && !activeDetail ? (
        <p className="text-sm text-text-muted">{t('noDetails')}</p>
      ) : null}
    </div>
  );
}

function WorkspaceActionLabel({
  label,
  widthLabels,
}: {
  label: string;
  widthLabels: string[];
}) {
  return (
    <span className="inline-grid justify-items-center">
      {widthLabels.map((text, index) => (
        <span
          key={`${index}-${text}`}
          className="invisible col-start-1 row-start-1 whitespace-nowrap"
          aria-hidden
        >
          {text}
        </span>
      ))}
      <span className="col-start-1 row-start-1 whitespace-nowrap">{label}</span>
    </span>
  );
}

function NotesField({
  textareaRef,
  value,
  disabled,
  label,
  placeholder,
  onChange,
}: {
  textareaRef: RefObject<HTMLTextAreaElement | null>;
  value: string;
  disabled: boolean;
  label: string;
  placeholder: string;
  onChange: (value: string) => void;
}) {
  useEffect(() => {
    const el = textareaRef.current;
    if (!el) return;
    el.style.height = '0px';
    el.style.height = `${el.scrollHeight}px`;
  }, [textareaRef, value]);

  return (
    <label className="block text-xs font-medium text-text-secondary min-w-0">
      {label}
      <textarea
        ref={textareaRef}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        rows={1}
        disabled={disabled}
        className="mt-1.5 w-full min-h-[2.875rem] sm:min-h-9 resize-none overflow-hidden rounded-[var(--radius-md)] border border-border bg-background-secondary/90 px-3 py-2.5 sm:py-2 text-base sm:text-sm leading-tight text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-primary/35"
      />
    </label>
  );
}

/**
 * "Add detail", split into two segments with the microphone at the logical end.
 *
 * Built like the detail chip's trash affordance in this same file — a wrapper holding two
 * raw `<button>`s divided by `border-s` — rather than two shared `Button`s, which hardcode
 * their own rounding and would fight a segmented control. `border-s` puts the microphone
 * visually right in en/nl and left in fa, on the same side as the chip's trash in both.
 *
 * Add keeps its exact existing behaviour; the microphone is an independent action.
 */
function AddDetailWithVoice({
  addLabel,
  widthLabels,
  startLabel,
  stopLabel,
  disabled,
  onAddDetail,
  voice,
}: {
  addLabel: string;
  widthLabels: string[];
  startLabel: string;
  stopLabel: string;
  disabled: boolean;
  onAddDetail: () => void;
  voice: VoiceCaptureState;
}) {
  const isRecording = voice.phase === 'recording';
  const isBusy = voice.phase !== 'idle';
  const micLabel = isRecording ? stopLabel : startLabel;

  return (
    <div
      className={`
        inline-flex items-stretch overflow-hidden rounded-[var(--radius-md)]
        bg-primary text-white shrink-0 ${WORKSPACE_ACTION_BTN_HEIGHT}
        ${disabled ? 'opacity-60' : ''}
      `}
    >
      <button
        type="button"
        onClick={onAddDetail}
        disabled={disabled || isBusy}
        className="
          px-3 text-sm font-medium transition-all duration-200
          hover:opacity-90 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset
          focus-visible:ring-white/60
          disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:opacity-60
        "
      >
        <WorkspaceActionLabel label={addLabel} widthLabels={widthLabels} />
      </button>
      <button
        type="button"
        onClick={isRecording ? voice.onStop : voice.onStart}
        disabled={disabled || voice.phase === 'processing'}
        title={micLabel}
        aria-label={micLabel}
        className={`
          inline-flex items-center justify-center border-s border-white/25 px-3
          transition-all duration-200 focus:outline-none focus-visible:ring-2
          focus-visible:ring-inset focus-visible:ring-white/60
          disabled:cursor-not-allowed disabled:opacity-60
          ${isRecording ? 'bg-red-600 hover:bg-red-700' : 'hover:opacity-90'}
        `}
      >
        {isRecording ? (
          <Square className="h-4 w-4 fill-current" aria-hidden />
        ) : (
          <Mic className="h-4 w-4" aria-hidden />
        )}
      </button>
    </div>
  );
}
