import { useState, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import {
  fetchSharedTask,
  fetchSharedTaskComments,
  fetchSharedFiles,
  fetchSharedFileContent,
  fetchSharedSubtaskActivities,
  getSharedFileRawUrl,
} from '../api';
import { StatusBadge } from '../components/shared/StatusBadge';
import { FilePreview } from '../components/files/FilePreview';
import { FileBrowser } from '../components/files/FileBrowser';
import { SubtasksPanel } from '../components/detail/tabs/SubtasksPanel';
import {
  TaskDataSourceProvider,
  createSharedTaskDataSource,
} from '../components/detail/task-data-source';
import { PUBLIC_SHARED_TABS, type SharedTabId } from './sharedTabs';
import { POLLING } from '../lib/constants';
import { ChatMessage } from '../components/chat/ChatMessage';
import { groupCommentsByMovement, MovementGroupExpanded } from '../components/chat/MovementGroup';
import { isThinkingComment, hasTrailingThinking } from '../components/chat/thinkingUtils';
import { sharedImageBaseUrl, sharedRawUrlFor } from '../lib/sharedView';

interface SharedViewProps {
  token: string;
}

type TabId = SharedTabId;

// ---- Shared file browser (本体 FileBrowser を read-only 再利用、output 区分のみ) ----

interface SharedFileBrowserProps {
  token: string;
  onPreview: (path: string, name: string) => void;
}

function SharedFileBrowser({ token, onPreview }: SharedFileBrowserProps) {
  const [currentPath, setCurrentPath] = useState('');

  const filesQuery = useQuery({
    queryKey: ['shared', 'files', token, currentPath],
    queryFn: () => fetchSharedFiles(token, currentPath),
    retry: false,
  });

  const entries = filesQuery.data?.entries ?? [];
  const pathSegments = currentPath ? currentPath.split('/').filter(Boolean) : [];
  const rawUrlFor = useMemo(() => sharedRawUrlFor(token), [token]);

  return (
    <div className="bg-canvas border border-hairline rounded-md p-3.5">
      <FileBrowser
        section="output"
        currentPath={currentPath}
        entries={entries}
        pathSegments={pathSegments}
        onSectionChange={() => { /* 共有は output 固定 */ }}
        onNavigate={setCurrentPath}
        onPreview={onPreview}
        onRefresh={() => filesQuery.refetch()}
        isRefreshing={filesQuery.isFetching}
        rawUrlFor={rawUrlFor}
        hideSections
      />
    </div>
  );
}

// ---- Main SharedView ----

/**
 * 共有タスクページ（公開・認証なし・read-only）。
 *
 * TaskDataSourceProvider に shared 実装を注入することで、本体の SubtasksPanel を
 * そのまま read-only 再利用する（個別サブタスクの activity/files 取得が
 * `/api/shared/:token/...` 経由になり、本体の `/api/local/...` には触れない）。
 * これにより共有ページのドリフトを防ぐ。
 */
export function SharedView({ token }: SharedViewProps) {
  // トークン単位でメモ化し、context value の identity を安定させる
  // （毎レンダーで新オブジェクトを渡すと consumer が無駄に再描画される）。
  const dataSource = useMemo(() => createSharedTaskDataSource(token), [token]);
  return (
    <TaskDataSourceProvider value={dataSource}>
      <SharedViewInner token={token} />
    </TaskDataSourceProvider>
  );
}

function SharedViewInner({ token }: SharedViewProps) {
  const { t } = useTranslation('shared');
  const [activeTab, setActiveTab] = useState<TabId>('overview');

  // Preview state
  const [previewState, setPreviewState] = useState<{
    name: string;
    content: string;
    imageSrc: string;
    markdownImageBaseUrl?: string;
  } | null>(null);

  const taskQuery = useQuery({
    queryKey: ['shared', 'task', token],
    queryFn: () => fetchSharedTask(token),
    refetchInterval: POLLING.FAST,
    retry: false,
  });

  const commentsQuery = useQuery({
    queryKey: ['shared', 'comments', token],
    queryFn: () => fetchSharedTaskComments(token),
    refetchInterval: POLLING.FAST,
    retry: false,
  });

  const task = taskQuery.data ?? null;
  const comments = commentsQuery.data ?? [];

  const hasSubtasks = (task?.subtasks?.length ?? 0) > 0;

  const subtaskActivitiesQuery = useQuery({
    queryKey: ['shared', 'subtaskActivities', token],
    queryFn: () => fetchSharedSubtaskActivities(token),
    refetchInterval: POLLING.FAST,
    enabled: hasSubtasks,
    retry: false,
  });

  const handlePreview = useCallback(
    async (filePath: string, name: string) => {
      const rawUrl = getSharedFileRawUrl(token, filePath);
      const isImage = /\.(png|jpe?g|gif|webp|svg|bmp|ico)$/i.test(name);
      const isPdf = /\.pdf$/i.test(name);
      const isHtml = /\.html?$/i.test(name);

      if (isImage || isPdf || isHtml) {
        setPreviewState({
          name,
          content: '',
          imageSrc: rawUrl,
          markdownImageBaseUrl: sharedImageBaseUrl(token),
        });
        return;
      }

      try {
        const content = await fetchSharedFileContent(token, filePath);
        setPreviewState({
          name,
          content,
          imageSrc: '',
          markdownImageBaseUrl: sharedImageBaseUrl(token),
        });
      } catch {
        // ignore
      }
    },
    [token],
  );

  if (taskQuery.isLoading) {
    return (
      <div className="h-dvh flex items-center justify-center bg-surface">
        <div className="w-7 h-7 border-2 border-accent border-t-transparent rounded-full animate-spin" />
      </div>
    );
  }

  if (taskQuery.isError || !task) {
    return (
      <div className="h-dvh flex items-center justify-center bg-surface px-6">
        <div className="text-center max-w-sm">
          <div className="text-4xl mb-3" aria-hidden="true">🔒</div>
          <div className="text-sm font-bold text-slate-900 mb-1.5">{t('notFoundTitle')}</div>
          <div className="text-[13px] text-slate-500 leading-relaxed">{t('notFoundBody')}</div>
        </div>
      </div>
    );
  }

  const status = task.latestJob?.status ?? task.state ?? 'unknown';
  const resultComments = comments.filter(c => c.kind === 'result' || c.kind === 'progress' || c.kind === 'ask' || c.kind === 'request' || c.kind === 'comment' || c.kind === 'handoff');
  const imageBaseUrl = sharedImageBaseUrl(token);
  const isRunning = status === 'running' || status === 'dispatching';
  const animatingIdx = isRunning && hasTrailingThinking(resultComments) ? resultComments.length - 1 : -1;
  // 本体チャットと同じく movement 単位でグルーピングし、折り畳み表示する。
  const groupedItems = groupCommentsByMovement(resultComments);

  return (
    <div className="min-h-dvh bg-surface text-slate-900 flex flex-col">
      <header className="bg-canvas border-b border-hairline px-4 py-3 sm:py-4">
        <div className="max-w-4xl mx-auto">
          <div className="flex items-start gap-3">
            <div className="flex-1 min-w-0">
              <div className="flex items-center gap-1.5 text-[10px] text-slate-400 font-mono uppercase tracking-wider mb-1">
                <svg className="w-3 h-3" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <path d="M6.5 9.5L4 12a2.5 2.5 0 11-3.5-3.5L3 6M9.5 6.5L12 4a2.5 2.5 0 113.5 3.5L13 10M6 10l4-4" />
                </svg>
                {t('viewBadge')}
              </div>
              <h1 className="text-sm sm:text-base font-bold text-slate-900 leading-snug break-words">
                {task.title || task.body.split('\n')[0]?.slice(0, 100)}
              </h1>
              <div className="flex items-center gap-2 mt-1.5 flex-wrap">
                <StatusBadge status={status} />
                {task.pieceName && (
                  <span className="text-[10px] text-slate-500 bg-surface-2 border border-hairline px-1.5 py-0.5 rounded font-mono">
                    {task.pieceName}
                  </span>
                )}
                <span className="text-[10px] text-slate-400 font-mono">
                  {new Date(task.createdAt).toLocaleString()}
                </span>
              </div>
            </div>
          </div>
        </div>
      </header>

      <div className="bg-canvas border-b border-hairline px-4">
        <div className="max-w-4xl mx-auto flex gap-0">
          {PUBLIC_SHARED_TABS.map(tab => (
            <button
              key={tab}
              onClick={() => setActiveTab(tab)}
              className={`px-3 py-2.5 text-xs border-b-2 transition-colors ${
                activeTab === tab
                  ? 'text-slate-900 border-accent font-semibold'
                  : 'text-slate-500 border-transparent hover:text-slate-800 font-medium'
              }`}
            >
              {tab === 'overview' ? t('tabOverview') : t('tabFiles')}
            </button>
          ))}
        </div>
      </div>

      <main className="flex-1 px-3 sm:px-4 py-4 sm:py-6">
        <div className="max-w-4xl mx-auto flex flex-col gap-3">
          {activeTab === 'overview' && (
            <>
              {resultComments.length > 0 && (
                <div className="flex flex-col gap-3">
                  {(() => {
                    let commentIdx = 0;
                    return groupedItems.map((item, gi) => {
                      if (item.type === 'movement') {
                        const startIdx = commentIdx;
                        commentIdx += item.inner.length;
                        return (
                          <MovementGroupExpanded
                            key={`mg-${gi}`}
                            item={item}
                            taskId={task.id}
                            isLast={gi === groupedItems.length - 1}
                            isRunning={isRunning}
                            animatingIdx={animatingIdx}
                            startIdx={startIdx}
                            imageBaseUrl={imageBaseUrl}
                            hideAttachments
                          />
                        );
                      }
                      const idx = commentIdx;
                      commentIdx++;
                      return (
                        <ChatMessage
                          key={item.comment.id}
                          comment={item.comment}
                          taskId={task.id}
                          imageBaseUrl={imageBaseUrl}
                          hideAttachments
                          isStaleThinking={isThinkingComment(item.comment) && idx !== animatingIdx}
                        />
                      );
                    });
                  })()}
                </div>
              )}

              {resultComments.length === 0 && (
                <div className="bg-canvas border border-hairline rounded-md p-6 text-center text-slate-500 text-[13px]">
                  {t('noResults')}
                </div>
              )}

              {hasSubtasks && task.subtasks && (
                <SubtasksPanel
                  taskId={task.id}
                  subtasks={task.subtasks}
                  subtaskCount={task.subtaskCount ?? task.subtasks.length}
                  subtaskCompleted={task.subtaskCompleted ?? 0}
                  subtaskActivities={subtaskActivitiesQuery.data}
                />
              )}
            </>
          )}

          {activeTab === 'files' && (
            <SharedFileBrowser token={token} onPreview={handlePreview} />
          )}
        </div>
      </main>

      {previewState && (
        <FilePreview
          name={previewState.name}
          content={previewState.content}
          imageSrc={previewState.imageSrc}
          markdownImageBaseUrl={previewState.markdownImageBaseUrl}
          onClose={() => setPreviewState(null)}
        />
      )}
    </div>
  );
}
