import { useState, useEffect, useCallback, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import {
  fetchSharedTask,
  fetchSharedTaskComments,
  fetchSharedFiles,
  fetchSharedFileContent,
  fetchSharedSubtaskActivities,
  getSharedFileRawUrl,
  type LocalFileEntry,
} from '../api';
import { StatusBadge } from '../components/shared/StatusBadge';
import { FilePreview } from '../components/files/FilePreview';
import { SubtasksPanel } from '../components/detail/tabs/SubtasksPanel';
import { POLLING } from '../lib/constants';
import { ChatMessage } from '../components/chat/ChatMessage';
import { isThinkingComment, hasTrailingThinking } from '../components/chat/thinkingUtils';
import { isPreviewable, formatFileDate } from '../lib/utils';

interface SharedViewProps {
  token: string;
}

type TabId = 'overview' | 'files';
type FileSort = 'name' | 'newest';

const ICON_BTN =
  'w-8 h-8 flex items-center justify-center rounded-md border border-hairline bg-white text-slate-500 hover:text-slate-900 hover:bg-surface transition-colors';

function sortEntries(entries: LocalFileEntry[], mode: FileSort): LocalFileEntry[] {
  const dirs = entries.filter(e => e.kind === 'directory');
  const files = entries.filter(e => e.kind !== 'directory');
  const sortFn = mode === 'newest'
    ? (a: LocalFileEntry, b: LocalFileEntry) => {
      const at = a.modifiedAt ? new Date(a.modifiedAt).getTime() : 0;
      const bt = b.modifiedAt ? new Date(b.modifiedAt).getTime() : 0;
      if (at !== bt) return bt - at;
      return a.name.localeCompare(b.name);
    }
    : (a: LocalFileEntry, b: LocalFileEntry) => a.name.localeCompare(b.name);
  return [...dirs.sort(sortFn), ...files.sort(sortFn)];
}

// ---- Shared file browser (output section only) ----

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

function SharedFileBrowser({ token, onPreview }: SharedFileBrowserProps) {
  const [currentPath, setCurrentPath] = useState('');
  const [entries, setEntries] = useState<LocalFileEntry[]>([]);
  const [loading, setLoading] = useState(false);
  const [sort, setSort] = useState<FileSort>('name');

  const loadEntries = useCallback(
    async (path: string) => {
      setLoading(true);
      try {
        const r = await fetchSharedFiles(token, path);
        setEntries(r.entries);
      } catch {
        setEntries([]);
      } finally {
        setLoading(false);
      }
    },
    [token],
  );

  useEffect(() => {
    loadEntries(currentPath);
  }, [currentPath, loadEntries]);

  const sortedEntries = useMemo(() => sortEntries(entries, sort), [entries, sort]);
  const pathSegments = currentPath ? currentPath.split('/').filter(Boolean) : [];

  return (
    <div className="bg-white border border-hairline rounded-md p-3.5">
      <div className="flex flex-col gap-3">
        <div className="flex items-center justify-between gap-2">
          <div className="text-2xs text-slate-500 font-mono break-all min-w-0 flex-1">
            /output{currentPath ? `/${currentPath}` : ''}
          </div>
          <select
            value={sort}
            onChange={e => setSort(e.target.value as FileSort)}
            className="flex-shrink-0 px-2 h-7 text-2xs rounded-md border border-hairline bg-white text-slate-700 hover:bg-surface focus:outline-none focus:ring-2 focus:ring-accent-ring"
            aria-label="並び順"
          >
            <option value="name">名前順</option>
            <option value="newest">新しい順</option>
          </select>
        </div>

        {pathSegments.length > 0 && (
          <button
            onClick={() => setCurrentPath(pathSegments.slice(0, -1).join('/'))}
            className="self-start inline-flex items-center gap-1 px-2 h-7 rounded-md border border-hairline bg-white text-2xs text-slate-600 hover:bg-surface transition-colors"
          >
            <svg className="w-3 h-3" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M10 4l-4 4 4 4M6 8h6" />
            </svg>
            Up
          </button>
        )}

        {loading && (
          <div className="text-xs text-slate-400">読み込み中...</div>
        )}

        <div className="flex flex-col gap-1">
          {sortedEntries.map(entry => (
            <div
              key={`${entry.kind}:${entry.path}`}
              className="flex items-center gap-2 px-2.5 py-1.5 rounded-md bg-white border border-hairline hover:bg-surface transition-colors"
            >
              <span className="text-slate-400 flex-shrink-0" aria-hidden="true">
                {entry.kind === 'directory' ? (
                  <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 4.5A1.5 1.5 0 013.5 3h3l1.5 2h4.5A1.5 1.5 0 0114 6.5v5A1.5 1.5 0 0112.5 13h-9A1.5 1.5 0 012 11.5v-7z" />
                  </svg>
                ) : (
                  <svg className="w-4 h-4" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M9 2H4a1.5 1.5 0 00-1.5 1.5v9A1.5 1.5 0 004 14h8a1.5 1.5 0 001.5-1.5V6.5L9 2z" />
                    <path d="M9 2v4.5h4.5" />
                  </svg>
                )}
              </span>
              <div className="min-w-0 flex-1">
                <div className="text-[13px] text-slate-800 truncate" title={entry.name}>{entry.name}</div>
                {entry.kind === 'file' && entry.modifiedAt && (
                  <div className="text-[10px] text-slate-400 font-mono leading-tight">{formatFileDate(entry.modifiedAt)}</div>
                )}
              </div>
              <div className="flex items-center gap-1 flex-shrink-0">
                {entry.kind === 'directory' ? (
                  <button
                    onClick={() => setCurrentPath(entry.path)}
                    className={ICON_BTN}
                    title="Open folder"
                    aria-label="Open folder"
                  >
                    <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M6 4l4 4-4 4" />
                    </svg>
                  </button>
                ) : (
                  <>
                    {isPreviewable(entry.name) && (
                      <button
                        onClick={() => onPreview(entry.path, entry.name)}
                        className={ICON_BTN}
                        title="Preview"
                        aria-label="Preview"
                      >
                        <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="M1.5 8s2.5-5 6.5-5 6.5 5 6.5 5-2.5 5-6.5 5-6.5-5-6.5-5z" />
                          <circle cx="8" cy="8" r="2" />
                        </svg>
                      </button>
                    )}
                    <a
                      href={getSharedFileRawUrl(token, entry.path)}
                      download={entry.name}
                      className={ICON_BTN}
                      title="Download"
                      aria-label="Download"
                    >
                      <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="M8 2v8M4.5 6.5L8 10l3.5-3.5M2.5 13h11" />
                      </svg>
                    </a>
                  </>
                )}
              </div>
            </div>
          ))}
          {!loading && entries.length === 0 && (
            <div className="text-xs text-slate-500 px-1 py-2">ファイルなし</div>
          )}
        </div>
      </div>
    </div>
  );
}

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

export function SharedView({ token }: SharedViewProps) {
  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: `/api/shared/${token}/files/raw?path=`,
        });
        return;
      }

      try {
        const content = await fetchSharedFileContent(token, filePath);
        setPreviewState({
          name,
          content,
          imageSrc: '',
          markdownImageBaseUrl: `/api/shared/${token}/files/raw?path=`,
        });
      } 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">共有リンクが見つかりません</div>
          <div className="text-[13px] text-slate-500 leading-relaxed">このリンクは無効か、共有が解除されています。</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 = `/api/shared/${token}/files/raw?path=`;
  const isRunning = status === 'running' || status === 'dispatching';
  const animatingIdx = isRunning && hasTrailingThinking(resultComments) ? resultComments.length - 1 : -1;

  return (
    <div className="min-h-dvh bg-surface text-slate-900 flex flex-col">
      <header className="bg-white 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>
                Shared View
              </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-white border-b border-hairline px-4">
        <div className="max-w-4xl mx-auto flex gap-0">
          {(['overview', 'files'] as const).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' ? '概要' : 'ファイル'}
            </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">
                  {resultComments.map((comment, i) => (
                    <ChatMessage
                      key={comment.id}
                      comment={comment}
                      taskId={task.id}
                      imageBaseUrl={imageBaseUrl}
                      isStaleThinking={isThinkingComment(comment) && i !== animatingIdx}
                    />
                  ))}
                </div>
              )}

              {resultComments.length === 0 && (
                <div className="bg-white border border-hairline rounded-md p-6 text-center text-slate-500 text-[13px]">
                  まだ結果がありません
                </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>
  );
}
