import { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import * as Dialog from '@radix-ui/react-dialog';
import { useQuery } from '@tanstack/react-query';
import { CreateLocalTaskInput, fetchMyOrgs, Visibility, listBrowserSessionProfiles } from '../../api';
import { AttachmentDropzone } from './AttachmentDropzone';
import { PromptCoachPanel } from './PromptCoachPanel';
import { ScheduleFields } from './ScheduleFields';
import { usePieceList } from '../../hooks/usePieces';
import { useSpaces } from '../../hooks/useSpaces';
import { sortSpacesForRail } from '../../lib/spaceSort';
import { resolvePieceOptions } from '../../lib/splitPieces';
import { useAuthState } from '../../App';

interface CreateTaskDialogProps {
  onClose: () => void;
  onSubmit: (input: CreateLocalTaskInput, attachments: Array<{ name: string; contentBase64: string }>) => Promise<void>;
  /**
   * Optional preselected piece. When set, the piece is locked (not overridden
   * by the auto-classifier) and a placeholder hint explains the assistant.
   * Used by the Help Center "AI に聞く" button to land users in the help piece.
   */
  initialPiece?: string;
  initialBody?: string;
  placeholder?: string;
  /**
   * Spaces foundation: スペース詳細から開いた場合に紐付けるスペース。
   * 指定時はそのスペースに固定（ピッカー非表示・名称のみ表示）。
   * 未指定（グローバルのタスク一覧から開いた）時は個人スペースが既定。
   */
  initialSpaceId?: string;
}

export function CreateTaskDialog({ onClose, onSubmit, initialPiece, initialBody, placeholder, initialSpaceId }: CreateTaskDialogProps) {
  const { t } = useTranslation('create');
  const { data: pieces } = usePieceList();
  const { data: spacesData } = useSpaces();
  const { data: orgs = [] } = useQuery({ queryKey: ['my-orgs'], queryFn: fetchMyOrgs, staleTime: 5 * 60 * 1000 });
  const { data: sessionProfiles = [] } = useQuery({
    queryKey: ['browser-session-profiles'],
    // ラップ必須: react-query は queryFn に QueryFunctionContext を渡すため、直接渡すと
    // spaceId 引数にオブジェクトが入り ?spaceId=[object Object] になる(WS2 回帰)。
    queryFn: () => listBrowserSessionProfiles(),
    staleTime: 60 * 1000,
  });
  const activeSessionProfiles = sessionProfiles.filter(p => p.status === 'active');
  interface ConnectionRow { serverId: string; serverName: string; connected: boolean }
  const { data: connections } = useQuery({
    queryKey: ['mcp-connections'],
    queryFn: async (): Promise<ConnectionRow[]> => {
      const res = await fetch('/api/mcp/connections', { credentials: 'include' });
      if (!res.ok) return [];
      const data = await res.json();
      return (data.connections ?? []) as ConnectionRow[];
    },
    staleTime: 30_000,
  });
  const authState = useAuthState();
  const defaultVis = (authState.mode === 'authenticated' ? authState.user?.defaultVisibility : undefined) ?? 'private';
  const savedOrgId = (authState.mode === 'authenticated' ? authState.user?.defaultVisibilityOrgId : undefined) ?? null;
  const [visibility, setVisibility] = useState<Visibility>(defaultVis);
  const [visibilityScopeOrgId, setVisibilityScopeOrgId] = useState<string | null>(savedOrgId);

  // Backfill the scope when orgs finish loading: useQuery starts with orgs=[]
  // so without this the initial render freezes scopeId=null for users without
  // a saved default, and picking 'Organization' would submit an unscoped task.
  useEffect(() => {
    if (visibilityScopeOrgId !== null) return;
    if (orgs.length === 0) return;
    setVisibilityScopeOrgId(orgs[0].orgId);
  }, [orgs, visibilityScopeOrgId]);
  const [form, setForm] = useState<CreateLocalTaskInput>({
    body: initialBody ?? '',
    piece: initialPiece ?? 'auto',
    profile: 'auto',
    outputFormat: 'markdown',
    askPolicy: 'low',
    priority: 'medium',
    workspaceMode: 'persistent',
  });
  // スペース起点で開いた場合は固定。それ以外はユーザーが任意で選択（既定=個人）。
  const [selectedSpaceId, setSelectedSpaceId] = useState<string | undefined>(initialSpaceId);
  const sortedSpaces = sortSpacesForRail(spacesData ?? []).filter(s => s.status === 'open');
  const fixedSpace = initialSpaceId ? sortedSpaces.find(s => s.id === initialSpaceId) : undefined;
  const [attachments, setAttachments] = useState<Array<{ name: string; contentBase64: string }>>([]);
  const [browserSessionProfileId, setBrowserSessionProfileId] = useState<number | null>(null);
  const [mcpDisabled, setMcpDisabled] = useState(false);
  const [skillsDisabled, setSkillsDisabled] = useState(false);
  const [error, setError] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [isScheduled, setIsScheduled] = useState(false);
  const [schedule, setSchedule] = useState({
    scheduleType: 'daily',
    hour: 9,
    minute: 0,
    dayOfWeek: 1,
    dayOfMonth: 1,
    cronExpression: '',
    scheduledAt: '',
  });

  const resolvedPieces = resolvePieceOptions(pieces ?? []);
  const selectedPiece = resolvedPieces.find(p => p.name === form.piece);
  const missingMcp = selectedPiece?.requiredMcp
    ? selectedPiece.requiredMcp.filter(
        (id) => !(connections ?? []).find((c) => c.serverId === id && c.connected),
      )
    : [];

  const handleSubmit = async () => {
    if (!form.body.trim()) {
      setError(t('errors.bodyRequired'));
      return;
    }
    try {
      setSubmitting(true);
      setError('');
      if (isScheduled) {
        const res = await fetch('/api/scheduled-tasks', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            title: form.body.trim().slice(0, 40),
            body: form.body.trim(),
            piece: form.piece,
            visibility,
            visibilityScopeOrgId: visibility === 'org' ? visibilityScopeOrgId : null,
            browserSessionProfileId: browserSessionProfileId ?? undefined,
            ...schedule,
          }),
        });
        if (!res.ok) throw new Error(t('errors.scheduleFailed'));
        onClose();
        return;
      }
      const options: Record<string, boolean> = {};
      if (mcpDisabled) options.mcpDisabled = true;
      if (skillsDisabled) options.skillsDisabled = true;
      const submitForm = {
        ...form,
        // initialPiece が指定されているヘルプアシスタント等は piece を固定。
        // それ以外は form.piece (詳細設定で選択した値、無指定なら 'auto') を尊重する。
        piece: initialPiece ?? form.piece,
        title: undefined,
        body: form.body.trim(),
        visibility,
        visibilityScopeOrgId: visibility === 'org' ? visibilityScopeOrgId : null,
        browserSessionProfileId: browserSessionProfileId ?? undefined,
        // 固定スペースを最優先、無ければ選択値。未指定なら個人スペースに解決される。
        spaceId: initialSpaceId ?? selectedSpaceId ?? undefined,
        ...(Object.keys(options).length > 0 ? { options } : {}),
      };
      await onSubmit(submitForm, attachments);
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Dialog.Root open onOpenChange={(open) => { if (!open) onClose(); }}>
      <Dialog.Portal>
        <Dialog.Overlay className="fixed inset-0 bg-slate-900/50 z-30" />
        <Dialog.Content
          className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-surface rounded-2xl shadow-2xl w-full overflow-auto z-40 focus:outline-none"
          style={{ maxWidth: 'min(860px, 92vw)', maxHeight: '88dvh' }}
          onOpenAutoFocus={e => {
            e.preventDefault();
          }}
        >
        <div className="p-5">
          <div className="flex items-start justify-between gap-3 mb-5">
            <div>
              <Dialog.Title className="text-xl font-extrabold text-slate-900 m-0">
                {initialPiece === 'help' ? t('title.help') : t('title.new')}
              </Dialog.Title>
              <Dialog.Description className="mt-1 text-[13px] text-slate-500">
                {initialPiece === 'help' ? t('subtitle.help') : t('subtitle.new')}
              </Dialog.Description>
            </div>
            <Dialog.Close asChild>
              <button
                aria-label={t('close')}
                className="p-1.5 rounded-lg text-slate-400 hover:text-slate-600 hover:bg-slate-100 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="2" strokeLinecap="round">
                  <path d="M4 4l8 8M12 4l-8 8"/>
                </svg>
              </button>
            </Dialog.Close>
          </div>

          <div className="flex flex-col gap-4">
            {/* Textarea */}
            <div>
              <label className="block text-[13px] text-slate-600 mb-1.5">{t('body.label')}</label>
              <textarea
                autoFocus
                data-testid="create-task-body"
                value={form.body}
                onChange={e => setForm(prev => ({ ...prev, body: e.target.value }))}
                onKeyDown={e => {
                  if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {
                    e.preventDefault();
                    void handleSubmit();
                  }
                }}
                rows={8}
                className="w-full px-3 py-2 border border-slate-200 rounded-xl text-sm outline-none focus:border-accent resize-y leading-relaxed"
                placeholder={placeholder ?? (initialPiece === 'help' ? t('body.placeholderHelp') : t('body.placeholder'))}
              />
            </div>

            {/* Workspace mode (永続/一時的) + スペース選択 */}
            <div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:gap-4">
              <div>
                <label className="block text-2xs text-slate-500 mb-1">{t('workspace.modeLabel')}</label>
                <div className="inline-flex rounded-lg border border-slate-200 p-0.5">
                  {([['persistent', t('workspace.persistent')], ['ephemeral', t('workspace.ephemeral')]] as const).map(([mode, label]) => {
                    const active = (form.workspaceMode ?? 'persistent') === mode;
                    return (
                      <button
                        key={mode}
                        type="button"
                        onClick={() => setForm(prev => ({ ...prev, workspaceMode: mode }))}
                        className={`px-3 py-1.5 rounded-md text-xs font-semibold transition-colors ${
                          active ? 'bg-accent text-accent-fg' : 'text-slate-600 hover:bg-slate-50'
                        }`}
                      >
                        {label}
                      </button>
                    );
                  })}
                </div>
                <p className="text-2xs text-slate-400 mt-1">
                  {t('workspace.modeHint')}
                </p>
                {(form.workspaceMode ?? 'persistent') === 'ephemeral' && (
                  <p className="text-2xs text-amber-600 mt-1" data-testid="ephemeral-warning">
                    {t('workspace.ephemeralWarning')}
                  </p>
                )}
              </div>

              {/* スペース: 固定 or ピッカー（既定=個人） */}
              <div className="min-w-0 flex-1">
                <label className="block text-2xs text-slate-500 mb-1">{t('workspace.spaceLabel')}</label>
                {initialSpaceId ? (
                  <div className="px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs text-slate-700 bg-slate-50 truncate">
                    {fixedSpace?.title ?? t('workspace.thisWorkspace')}
                  </div>
                ) : (
                  <select
                    value={selectedSpaceId ?? ''}
                    onChange={e => setSelectedSpaceId(e.target.value || undefined)}
                    className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                  >
                    <option value="">{t('workspace.personalDefault')}</option>
                    {sortedSpaces
                      .filter(s => s.kind === 'case')
                      .map(s => (
                        <option key={s.id} value={s.id}>{s.title}</option>
                      ))}
                  </select>
                )}
              </div>
            </div>

            {/* Attachments */}
            <AttachmentDropzone attachments={attachments} onFilesChange={setAttachments} />

            {/* Prompt coach (on-demand draft evaluation) */}
            <PromptCoachPanel
              body={form.body}
              piece={initialPiece ?? form.piece}
              onApplyRewrite={(text) => setForm(prev => ({ ...prev, body: text }))}
            />

            {/* MCP warnings (always visible when applicable) */}
            {missingMcp.length > 0 && (
              <div className="p-3 bg-yellow-50 dark:bg-yellow-500/15 border border-yellow-300 dark:border-yellow-500/30 rounded text-xs text-yellow-900 dark:text-yellow-300 space-y-2">
                <div>
                  <strong>{t('mcp.required')}</strong> {missingMcp.join(', ')}
                </div>
                <div className="flex flex-wrap gap-2">
                  {missingMcp.map((id) => (
                    <a
                      key={id}
                      className="px-2 py-0.5 rounded bg-yellow-600 text-white hover:bg-yellow-700 text-2xs font-semibold"
                      href={`/auth/mcp/${encodeURIComponent(id)}/start`}
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      {t('mcp.connect', { id })}
                    </a>
                  ))}
                </div>
                <div className="text-2xs text-yellow-700 dark:text-yellow-300">
                  {t('mcp.note')}
                </div>
              </div>
            )}

            {/* Advanced Settings toggle + content */}
            <div>
              <button
                onClick={() => setShowAdvanced(prev => !prev)}
                className="px-3 py-1.5 border border-slate-200 rounded-xl text-xs font-bold text-slate-600 hover:bg-slate-50"
              >
                {showAdvanced ? t('advanced.hide') : t('advanced.show')}
              </button>
              {showAdvanced && (
                <div className="mt-3 space-y-4 border border-slate-100 rounded-xl p-4 bg-slate-50/50">
                  {/* Row 1: Piece, Profile, Priority */}
                  <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
                    <div>
                      <label className="block text-2xs text-slate-500 mb-1">{t('advanced.taskType')}</label>
                      <select
                        value={form.piece}
                        onChange={e => setForm(prev => ({ ...prev, piece: e.target.value }))}
                        className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                      >
                        <option value="auto">{t('advanced.auto')}</option>
                        {resolvedPieces.map(p => (
                          <option key={p.name} value={p.name}>{p.name}</option>
                        ))}
                      </select>
                    </div>
                    <div>
                      <label className="block text-2xs text-slate-500 mb-1">{t('advanced.profile')}</label>
                      <select
                        value={form.profile}
                        onChange={e => setForm(prev => ({ ...prev, profile: e.target.value as CreateLocalTaskInput['profile'] }))}
                        className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                      >
                        {[['auto', 'auto'], ['fast', 'fast'], ['quality', 'quality']].map(([v, l]) => (
                          <option key={v} value={v}>{l}</option>
                        ))}
                      </select>
                    </div>
                    <div>
                      <label className="block text-2xs text-slate-500 mb-1">{t('advanced.priority')}</label>
                      <select
                        value={form.priority}
                        onChange={e => setForm(prev => ({ ...prev, priority: e.target.value as CreateLocalTaskInput['priority'] }))}
                        className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                      >
                        {[['low', 'low'], ['medium', 'medium'], ['high', 'high']].map(([v, l]) => (
                          <option key={v} value={v}>{l}</option>
                        ))}
                      </select>
                    </div>
                  </div>

                  {/* Row 2: Output Format, Ask Policy */}
                  <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                    <div>
                      <label className="block text-2xs text-slate-500 mb-1">{t('advanced.outputFormat')}</label>
                      <select
                        value={form.outputFormat}
                        onChange={e => setForm(prev => ({ ...prev, outputFormat: e.target.value as CreateLocalTaskInput['outputFormat'] }))}
                        className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                      >
                        {[['markdown', 'markdown'], ['text', 'text'], ['json', 'json']].map(([v, l]) => (
                          <option key={v} value={v}>{l}</option>
                        ))}
                      </select>
                    </div>
                    <div>
                      <label className="block text-2xs text-slate-500 mb-1">{t('advanced.askPolicy')}</label>
                      <select
                        value={form.askPolicy}
                        onChange={e => setForm(prev => ({ ...prev, askPolicy: e.target.value as CreateLocalTaskInput['askPolicy'] }))}
                        className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                      >
                        <option value="low">{t('advanced.askLow')}</option>
                        <option value="high">{t('advanced.askHigh')}</option>
                      </select>
                    </div>
                  </div>

                  {/* Row 3: MCP disable, Skills disable checkboxes */}
                  <div className="flex flex-wrap gap-x-6 gap-y-2">
                    <label className="flex items-center gap-2 text-xs text-slate-600 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={mcpDisabled}
                        onChange={e => setMcpDisabled(e.target.checked)}
                        className="rounded"
                      />
                      {t('advanced.disableMcp')}
                    </label>
                    <label className="flex items-center gap-2 text-xs text-slate-600 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={skillsDisabled}
                        onChange={e => setSkillsDisabled(e.target.checked)}
                        className="rounded"
                      />
                      {t('advanced.disableSkills')}
                    </label>
                  </div>

                  {/* Browser Session (only if active profiles exist) */}
                  {activeSessionProfiles.length > 0 && (
                    <div>
                      <label className="block text-2xs text-slate-500 mb-1">{t('advanced.browserSession')}</label>
                      <select
                        value={browserSessionProfileId ?? ''}
                        onChange={e =>
                          setBrowserSessionProfileId(e.target.value ? Number(e.target.value) : null)
                        }
                        className="w-full px-2.5 py-1.5 border border-slate-200 rounded-lg text-xs outline-none focus:border-accent"
                      >
                        <option value="">{t('advanced.none')}</option>
                        {activeSessionProfiles.map(p => (
                          <option key={p.id} value={p.id}>{p.label}</option>
                        ))}
                      </select>
                      <p className="text-2xs text-slate-400 mt-1">
                        {t('advanced.browserSessionHint')}
                      </p>
                    </div>
                  )}

                  {/* Visibility */}
                  <div>
                    <label className="block text-2xs text-slate-500 mb-1">{t('visibility.label')}</label>
                    <div className="flex gap-3 text-xs">
                      <label className="flex items-center gap-1 cursor-pointer">
                        <input type="radio" checked={visibility === 'private'} onChange={() => setVisibility('private')} />
                        {t('visibility.private')}
                      </label>
                      <label className="flex items-center gap-1 cursor-pointer">
                        <input type="radio" checked={visibility === 'org'} onChange={() => setVisibility('org')} disabled={orgs.length === 0} />
                        {t('visibility.org')}
                      </label>
                      <label className="flex items-center gap-1 cursor-pointer">
                        <input type="radio" checked={visibility === 'public'} onChange={() => setVisibility('public')} />
                        {t('visibility.public')}
                      </label>
                    </div>
                    {visibility === 'org' && orgs.length > 1 && (
                      <select
                        className="mt-1 px-2 py-1 border border-slate-200 rounded text-xs"
                        value={visibilityScopeOrgId ?? ''}
                        onChange={e => setVisibilityScopeOrgId(e.target.value)}
                      >
                        {orgs.map(o => <option key={o.orgId} value={o.orgId}>{o.orgName}</option>)}
                      </select>
                    )}
                    {visibility === 'org' && orgs.length === 1 && (
                      <div className="mt-1 text-2xs text-slate-500">{t('visibility.sharedWith', { org: orgs[0].orgName })}</div>
                    )}
                    {visibility === 'org' && orgs.length === 0 && (
                      <div className="mt-1 text-2xs text-slate-400">{t('visibility.orgLoginHint')}</div>
                    )}
                  </div>

                  {/* Schedule toggle + sub-form */}
                  <div>
                    <div className="flex items-center gap-2">
                      <input
                        type="checkbox"
                        id="schedule-toggle"
                        checked={isScheduled}
                        onChange={e => setIsScheduled(e.target.checked)}
                        className="rounded"
                      />
                      <label htmlFor="schedule-toggle" className="text-xs text-slate-600 cursor-pointer">{t('schedule.enable')}</label>
                    </div>
                    {isScheduled && (
                      <ScheduleFields schedule={schedule} onChange={setSchedule} />
                    )}
                  </div>
                </div>
              )}
            </div>

            {error && <div className="text-[13px] text-red-600">{error}</div>}

            {/* Action buttons */}
            <div className="flex justify-end items-center gap-2 pt-1">
              <Dialog.Close asChild>
                <button className="px-4 py-2 border border-slate-200 rounded-xl text-[13px] text-slate-600 hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-ring">
                  {t('cancel')}
                </button>
              </Dialog.Close>
              <button
                disabled={submitting}
                data-testid="create-task-submit"
                onClick={() => void handleSubmit()}
                className="px-4 py-2 bg-accent text-accent-fg rounded-xl text-[13px] font-bold disabled:opacity-50 hover:bg-accent-deep"
              >
                {submitting ? t('submitting') : isScheduled ? t('submitSchedule') : t('submit')}
              </button>
            </div>
          </div>
        </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}
