import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { DetailTabId } from '../../lib/urlState';
import { shareTask, unshareTask } from '../../api';

interface Tab { id: DetailTabId; labelKey: string; }

interface DetailHeaderProps {
  title: string;
  subtitle: string;
  tabs: Tab[];
  activeTab: DetailTabId;
  /** True while the deferred content tab is still catching up to activeTab.
   * Used to render a subtle pulse on the active tab so the user knows the
   * click was registered even if the content takes a frame or two to paint. */
  tabTransitionPending?: boolean;
  onTabChange: (tab: DetailTabId) => void;
  onClose: () => void;
  detailWidth?: 'normal' | 'focused';
  onWidthToggle?: () => void;
  // 共有機能
  taskId?: number;
  shareToken?: string | null;
  onShareChange?: () => void;
  /** Status of the latest job for this task. The Continue button is shown
   * when latestJobStatus is provided and enabled only on terminal states. */
  latestJobStatus?: string | null;
  /** Click handler for the Continue button. When undefined, the button is
   * hidden entirely (e.g., shared/read-only views). */
  onContinue?: () => void;
}

function ShareButton({ taskId, shareToken, onShareChange }: { taskId: number; shareToken: string | null; onShareChange?: () => void }) {
  const { t } = useTranslation('detail');
  const [copied, setCopied] = useState(false);
  const qc = useQueryClient();

  const shareMutation = useMutation({
    mutationFn: () => shareTask(taskId),
    onSuccess: (data) => {
      const url = `${window.location.origin}${data.shareUrl}`;
      navigator.clipboard.writeText(url);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
      qc.invalidateQueries({ queryKey: ['localTaskDetail', taskId] });
      qc.invalidateQueries({ queryKey: ['localTasks'] });
      onShareChange?.();
    },
  });

  const unshareMutation = useMutation({
    mutationFn: () => unshareTask(taskId),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['localTaskDetail', taskId] });
      qc.invalidateQueries({ queryKey: ['localTasks'] });
      onShareChange?.();
    },
  });

  // Refero refresh: collapse share UI from text-button rows into compact
  // icon-only buttons. The title row was getting eaten by long Japanese
  // labels ("リンクコピー" / "共有停止") on narrow viewports; with icons
  // we get the same affordance in ~32px instead of ~80px each.
  const iconBtnBase =
    'inline-flex items-center justify-center w-7 h-7 border rounded-md transition-colors disabled:opacity-50';

  if (!shareToken) {
    return (
      <button
        onClick={() => shareMutation.mutate()}
        disabled={shareMutation.isPending}
        title={shareMutation.isPending ? t('share.sharing') : t('share.publish')}
        aria-label={t('share.publish')}
        className={`${iconBtnBase} border-hairline bg-canvas text-slate-600 hover:text-slate-900 hover:bg-surface`}
      >
        {shareMutation.isPending ? (
          <svg className="w-3.5 h-3.5 animate-spin" viewBox="0 0 24 24" fill="none">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" />
          </svg>
        ) : (
          <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <circle cx="4" cy="8" r="2" />
            <circle cx="12" cy="4" r="2" />
            <circle cx="12" cy="12" r="2" />
            <path d="M5.7 7l4.6-2M5.7 9l4.6 2" />
          </svg>
        )}
      </button>
    );
  }

  const handleCopy = () => {
    const url = `${window.location.origin}/ui/shared/${shareToken}`;
    navigator.clipboard.writeText(url);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div className="flex items-center gap-1">
      <button
        onClick={handleCopy}
        title={copied ? t('share.copied') : t('share.copy')}
        aria-label={t('share.copy')}
        className={`${iconBtnBase} ${copied ? 'border-emerald-200 dark:border-emerald-500/30 bg-emerald-50 dark:bg-emerald-500/15 text-emerald-700 dark:text-emerald-300' : 'border-hairline bg-canvas text-slate-600 hover:text-slate-900 hover:bg-surface'}`}
      >
        {copied ? (
          <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M3 8.5l3 3 7-7" />
          </svg>
        ) : (
          <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <rect x="5" y="5" width="9" height="9" rx="1.5" />
            <path d="M11 5V3.5A1.5 1.5 0 009.5 2h-6A1.5 1.5 0 002 3.5v6A1.5 1.5 0 003.5 11H5" />
          </svg>
        )}
      </button>
      <button
        onClick={() => unshareMutation.mutate()}
        disabled={unshareMutation.isPending}
        title={t('share.stop')}
        aria-label={t('share.stop')}
        className={`${iconBtnBase} border-hairline bg-canvas text-slate-500 hover:text-red-700 dark:hover:text-red-300 hover:border-red-200 hover:bg-red-50 dark:hover:bg-red-500/15`}
      >
        {unshareMutation.isPending ? (
          <svg className="w-3.5 h-3.5 animate-spin" viewBox="0 0 24 24" fill="none">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" />
          </svg>
        ) : (
          <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M5 5l6 6M11 5l-6 6" />
          </svg>
        )}
      </button>
    </div>
  );
}

function ContinueButton({ latestJobStatus, onClick }: { latestJobStatus: string | null; onClick: () => void }) {
  const { t } = useTranslation('detail');
  // Mirror the spec/backend TERMINAL list (worker maps abort outcomes to
  // 'failed', so 'aborted' is intentionally absent).
  const TERMINAL = ['succeeded', 'failed', 'waiting_human', 'cancelled'];
  const enabled = latestJobStatus != null && TERMINAL.includes(latestJobStatus);
  const iconBtnBase =
    'inline-flex items-center justify-center w-7 h-7 border rounded-md transition-colors disabled:opacity-40 disabled:cursor-not-allowed';
  return (
    <button
      onClick={onClick}
      disabled={!enabled}
      title={enabled ? t('continue.label') : t('continue.disabled')}
      aria-label={t('continue.label')}
      className={`${iconBtnBase} border-hairline bg-canvas text-slate-600 hover:text-slate-900 hover:bg-surface`}
    >
      {/* arrow → divider: 「次のフェーズへ進む」cue。FileBrowser の refresh
          (循環矢印) と区別するためフラットな skip-forward 形状を採用 */}
      <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
        <path d="M2 8h9" />
        <path d="M8 5l3 3-3 3" />
        <path d="M13.5 4v8" />
      </svg>
    </button>
  );
}

export function DetailHeader({ title, subtitle, tabs, activeTab, tabTransitionPending, onTabChange, onClose, detailWidth, onWidthToggle, taskId, shareToken, onShareChange, latestJobStatus, onContinue }: DetailHeaderProps) {
  const { t } = useTranslation('detail');
  // Mobile (< sm) hides the close button and tab bar because App.tsx
  // renders its own mobile-level top tab bar with the same controls.
  // Two close buttons / two tab bars on iPhone was visually redundant.
  return (
    <div className="flex-shrink-0 border-b border-hairline bg-canvas px-4 pt-3 pb-3 sm:pb-0" id="detail-panel-title">
      <div className="flex items-start justify-between gap-2 mb-0 sm:mb-3">
        <div className="min-w-0 flex-1">
          <div className="text-[10px] font-mono uppercase tracking-wider text-slate-400">{subtitle}</div>
          <div className="font-semibold text-lg text-slate-900 mt-0.5 break-words leading-tight">{title}</div>
        </div>
        {/* Inline action cluster: width toggle + share + close. Share is
            now icon-only (32px) so it fits next to the title instead of
            occupying its own row. */}
        <div className="flex items-center gap-1 flex-shrink-0">
          {onContinue && taskId != null && (
            <ContinueButton
              latestJobStatus={latestJobStatus ?? null}
              onClick={onContinue}
            />
          )}
          {taskId != null && (
            <ShareButton
              taskId={taskId}
              shareToken={shareToken ?? null}
              onShareChange={onShareChange}
            />
          )}
          {onWidthToggle && detailWidth && (
            <button
              onClick={onWidthToggle}
              title={detailWidth === 'focused' ? t('focus.toStandard') : t('focus.toFocused')}
              aria-label={detailWidth === 'focused' ? t('focus.toStandard') : t('focus.toFocusedShort')}
              aria-pressed={detailWidth === 'focused'}
              className="hidden sm:inline-flex items-center justify-center w-7 h-7 rounded-md text-slate-500 hover:text-slate-700 hover:bg-surface-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring"
            >
              {detailWidth === 'focused' ? (
                // exit-fullscreen 様: 4 つの内向き角矢印
                <svg className="w-4 h-4" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M6 2v4H2M10 2v4h4M6 14v-4H2M10 14v-4h4" />
                </svg>
              ) : (
                // enter-fullscreen 様: 4 つの外向き角矢印
                <svg className="w-4 h-4" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M2 6V2h4M14 6V2h-4M2 10v4h4M14 10v4h-4" />
                </svg>
              )}
            </button>
          )}
          <button
            onClick={onClose}
            aria-label={t('panel.close')}
            className="hidden sm:inline-flex items-center justify-center w-7 h-7 rounded-md text-slate-400 hover:text-slate-700 hover:bg-surface-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring"
          >
            <svg className="w-4 h-4" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round">
              <path d="M4 4l8 8M12 4l-8 8"/>
            </svg>
          </button>
        </div>
      </div>
      <div role="tablist" aria-label={t('panel.tabsLabel')} className="hidden sm:flex gap-4 -mb-px">
        {tabs.map(tab => {
          const active = activeTab === tab.id;
          const pending = active && tabTransitionPending;
          return (
            <button
              key={tab.id}
              role="tab"
              aria-selected={active}
              onClick={() => onTabChange(tab.id)}
              className={`pb-2.5 text-xs border-b-2 active:scale-[0.97] transition-[transform,color,border-color] duration-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring inline-flex items-center gap-1.5 ${
                active
                  ? 'border-accent text-slate-900 font-semibold'
                  : 'border-transparent text-slate-500 font-medium hover:text-slate-800'
              }`}
            >
              {t(tab.labelKey)}
              {pending && (
                <span
                  aria-hidden="true"
                  className="inline-block w-2.5 h-2.5 border-2 border-accent border-t-transparent rounded-full animate-spin"
                />
              )}
            </button>
          );
        })}
      </div>
    </div>
  );
}
