import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { LocalTask, MissionBrief, SubtaskActivity, putFeedback, updateMissionBrief, updateLocalTask, regenerateTaskTitle } from '../../../api';
import { StatusBadge } from '../../shared/StatusBadge';
import { SubtasksPanel, type SubtaskFilePreviewHandler } from './SubtasksPanel';
import { ContextUsageGauge } from '../ContextUsageGauge';
import { ReflectionBadge } from '../ReflectionBadge';

const GOOD_TAGS = ['出力の精度が高い', 'フォーマットが適切', '指示をよく理解していた', '速度が適切だった'];
const BAD_TAGS = ['出力の精度が低い', 'フォーマットが不適切', '指示と違う結果になった', '不要な作業をしていた', '途中で止まった / ASKが多すぎた'];

function FeedbackPanel({ task }: { task: LocalTask }) {
  const { t } = useTranslation('detail');
  const qc = useQueryClient();
  const isComplete = task.latestJob?.status === 'succeeded' || task.latestJob?.status === 'failed';
  const hasFeedback = !!task.feedbackRating;

  const [rating, setRating] = useState<'good' | 'bad' | null>(task.feedbackRating ?? null);
  const [selectedTags, setSelectedTags] = useState<string[]>(task.feedbackTags ?? []);
  const [comment, setComment] = useState(task.feedbackComment ?? '');
  const [editing, setEditing] = useState(!hasFeedback);

  const mutation = useMutation({
    mutationFn: (fb: { rating: 'good' | 'bad'; tags: string[]; comment?: string }) =>
      putFeedback(task.id, fb),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['localTasks'] });
      qc.invalidateQueries({ queryKey: ['localTaskDetail', task.id] });
      setEditing(false);
    },
  });

  if (!isComplete) return null;

  const tags = rating === 'good' ? GOOD_TAGS : rating === 'bad' ? BAD_TAGS : [];
  const toggleTag = (tag: string) => {
    setSelectedTags(prev => prev.includes(tag) ? prev.filter(t => t !== tag) : [...prev, tag]);
  };
  const handleSubmit = () => {
    if (!rating) return;
    mutation.mutate({ rating, tags: selectedTags, comment: comment || undefined });
  };
  const handleRatingClick = (r: 'good' | 'bad') => {
    setRating(r);
    setSelectedTags([]);
    setEditing(true);
  };

  if (!editing && hasFeedback) {
    return (
      <div className="bg-canvas border border-slate-200 rounded-xl p-4 shadow-sm">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2">
            <span className="text-sm font-semibold text-slate-700">{t('feedback.title')}</span>
            <span className={`text-lg ${task.feedbackRating === 'good' ? 'text-green-500' : 'text-red-500'}`}>
              {task.feedbackRating === 'good' ? '👍' : '👎'}
            </span>
          </div>
          <button
            onClick={() => setEditing(true)}
            className="text-xs text-slate-400 hover:text-slate-600"
          >
            {t('feedback.change')}
          </button>
        </div>
        {task.feedbackTags && task.feedbackTags.length > 0 && (
          <div className="flex flex-wrap gap-1.5 mt-2">
            {task.feedbackTags.map(tag => (
              <span key={tag} className="px-2 py-0.5 rounded-full text-2xs bg-slate-100 text-slate-600">{tag}</span>
            ))}
          </div>
        )}
        {task.feedbackComment && (
          <div className="mt-2 text-xs text-slate-500">{task.feedbackComment}</div>
        )}
      </div>
    );
  }

  return (
    <div className="bg-canvas border border-slate-200 rounded-xl p-4 shadow-sm">
      <div className="text-sm font-semibold text-slate-700 mb-2">{t('feedback.title')}</div>
      <div className="flex gap-2 mb-3">
        <button
          onClick={() => handleRatingClick('good')}
          className={`px-3 py-1.5 rounded-lg text-sm border transition-colors ${
            rating === 'good' ? 'bg-green-50 dark:bg-green-500/15 border-green-300 dark:border-green-500/30 text-green-700 dark:text-green-300' : 'border-slate-200 text-slate-500 hover:border-slate-300'
          }`}
        >
          👍 {t('feedback.good')}
        </button>
        <button
          onClick={() => handleRatingClick('bad')}
          className={`px-3 py-1.5 rounded-lg text-sm border transition-colors ${
            rating === 'bad' ? 'bg-red-50 dark:bg-red-500/15 border-red-300 dark:border-red-500/30 text-red-700 dark:text-red-300' : 'border-slate-200 text-slate-500 hover:border-slate-300'
          }`}
        >
          👎 {t('feedback.bad')}
        </button>
      </div>

      {rating && (
        <>
          <div className="flex flex-wrap gap-1.5 mb-3">
            {tags.map(tag => (
              <button
                key={tag}
                onClick={() => toggleTag(tag)}
                className={`px-2 py-0.5 rounded-full text-2xs border transition-colors ${
                  selectedTags.includes(tag)
                    ? 'bg-accent-soft border-accent text-accent'
                    : 'border-slate-200 text-slate-500 hover:border-slate-300'
                }`}
              >
                {tag}
              </button>
            ))}
          </div>
          <textarea
            value={comment}
            onChange={e => setComment(e.target.value)}
            placeholder={t('feedback.commentPlaceholder')}
            maxLength={1000}
            rows={2}
            className="w-full px-3 py-2 text-xs border border-slate-200 rounded-lg resize-none focus:outline-none focus:ring-1 focus:ring-accent-ring mb-2"
          />
          <div className="flex justify-end gap-2">
            {hasFeedback && (
              <button
                onClick={() => { setEditing(false); setRating(task.feedbackRating ?? null); setSelectedTags(task.feedbackTags ?? []); setComment(task.feedbackComment ?? ''); }}
                className="px-3 py-1 text-xs text-slate-400 hover:text-slate-600"
              >
                {t('feedback.cancel')}
              </button>
            )}
            <button
              onClick={handleSubmit}
              disabled={mutation.isPending}
              className="px-3 py-1 text-xs bg-accent text-accent-fg rounded-lg hover:bg-accent-deep disabled:opacity-50"
            >
              {mutation.isPending ? t('feedback.submitting') : t('feedback.submit')}
            </button>
          </div>
        </>
      )}
    </div>
  );
}

/**
 * Mission Brief card. Per-task pinned memo with goal / done / open /
 * clarifications. The LLM updates these via the MissionUpdate tool;
 * the user can edit them here to anchor or correct the agent. Always
 * shown so the user can guide the agent before the conversation drifts.
 */
const MISSION_FIELDS: Array<{ key: keyof MissionBrief }> = [
  { key: 'goal' },
  { key: 'done' },
  { key: 'open' },
  { key: 'clarifications' },
];

const EMPTY_MISSION: MissionBrief = { goal: '', done: '', open: '', clarifications: '' };

function MissionCard({ task }: { task: LocalTask }) {
  const { t } = useTranslation('detail');
  const qc = useQueryClient();
  const current = task.missionBrief ?? EMPTY_MISSION;
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState<MissionBrief>(current);
  const [error, setError] = useState<string | null>(null);

  // Keep draft in sync with server-side updates (e.g. LLM writes via
  // MissionUpdate while we're not editing). Don't clobber an active edit.
  useEffect(() => {
    if (!editing) setDraft(task.missionBrief ?? EMPTY_MISSION);
  }, [task.missionBrief, editing]);

  const mutation = useMutation({
    mutationFn: () => updateMissionBrief(task.id, draft),
    onSuccess: () => {
      setEditing(false);
      setError(null);
      qc.invalidateQueries({ queryKey: ['localTaskDetail', task.id] });
      qc.invalidateQueries({ queryKey: ['localTasks'] });
    },
    onError: (err: unknown) => {
      setError(err instanceof Error ? err.message : 'Failed to save mission brief');
    },
  });

  const isEmpty = !current.goal && !current.done && !current.open && !current.clarifications;

  return (
    <div className="bg-canvas border border-hairline rounded-md p-3.5">
      <div className="flex items-center justify-between mb-2.5">
        <div className="flex items-center gap-1.5">
          <svg className="w-3.5 h-3.5 text-slate-500" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
            <path d="M3 2v12M3 2h7l-1 2 1 2H3" />
          </svg>
          <span className="section-label">Mission Brief</span>
          <span className="text-[10px] text-slate-400">— {t('mission.pinnedMemo')}</span>
        </div>
        {!editing ? (
          <button
            type="button"
            onClick={() => { setDraft(current); setEditing(true); setError(null); }}
            className="px-2 h-7 text-2xs font-medium border border-hairline bg-canvas text-slate-700 hover:bg-surface rounded-md transition-colors"
          >
            {t('mission.edit')}
          </button>
        ) : null}
      </div>

      {editing ? (
        <div className="flex flex-col gap-2.5">
          {MISSION_FIELDS.map(({ key }) => (
            <div key={key}>
              <label className="block text-[10px] font-mono uppercase tracking-wider text-slate-500 mb-1">{t(`mission.fields.${key}.label`)}</label>
              <textarea
                value={draft[key] ?? ''}
                onChange={(e) => setDraft({ ...draft, [key]: e.target.value })}
                placeholder={t(`mission.fields.${key}.placeholder`)}
                rows={key === 'goal' ? 2 : 3}
                className="w-full px-2.5 py-1.5 text-xs border border-hairline rounded-md focus:outline-none focus:ring-2 focus:ring-accent-ring focus:border-accent transition-shadow font-mono leading-snug"
              />
            </div>
          ))}
          {error && <div className="text-2xs text-red-600">{error}</div>}
          <div className="flex justify-end gap-1.5">
            <button
              type="button"
              onClick={() => { setEditing(false); setError(null); setDraft(current); }}
              disabled={mutation.isPending}
              className="px-3 h-7 text-xs rounded-md border border-hairline bg-canvas text-slate-700 hover:bg-surface transition-colors disabled:opacity-50"
            >
              {t('mission.cancel')}
            </button>
            <button
              type="button"
              onClick={() => mutation.mutate()}
              disabled={mutation.isPending}
              className="px-3 h-7 text-xs font-semibold rounded-md bg-accent text-accent-fg hover:bg-accent-deep transition-colors disabled:opacity-50"
            >
              {mutation.isPending ? t('mission.saving') : t('mission.save')}
            </button>
          </div>
        </div>
      ) : isEmpty ? (
        <div className="text-xs text-slate-500 leading-relaxed">
          {t('mission.emptyHelp')}
        </div>
      ) : (
        <div className="flex flex-col gap-2.5">
          {MISSION_FIELDS.map(({ key }) => {
            const value = current[key];
            return (
              <div key={key}>
                <div className="text-[10px] font-mono uppercase tracking-wider text-slate-500 mb-0.5">{t(`mission.fields.${key}.label`)}</div>
                {value ? (
                  <div className="text-xs text-slate-800 whitespace-pre-wrap leading-snug font-mono">{value}</div>
                ) : (
                  <div className="text-2xs text-slate-400 italic">{t(`mission.fields.${key}.emptyHint`)}</div>
                )}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

/**
 * Editable task title with on-demand AI regeneration. The title is set to a
 * cheap fallback at creation and upgraded by the agent (derived from the
 * Mission Brief goal) during the run. A manual edit pins it (title_source =
 * 'user') so the agent never overwrites it afterwards.
 */
function TaskTitleRow({ task }: { task: LocalTask }) {
  const { t } = useTranslation('detail');
  const qc = useQueryClient();
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(task.title);
  const [error, setError] = useState<string | null>(null);

  // Sync the displayed title with server-side updates (the agent rewrites it
  // mid-run) unless the user is actively editing.
  useEffect(() => {
    if (!editing) setDraft(task.title);
  }, [task.title, editing]);

  const invalidate = () => {
    qc.invalidateQueries({ queryKey: ['localTaskDetail', task.id] });
    qc.invalidateQueries({ queryKey: ['localTasks'] });
  };

  const saveMutation = useMutation({
    mutationFn: () => updateLocalTask(task.id, { title: draft.trim() }),
    onSuccess: () => { setEditing(false); setError(null); invalidate(); },
    onError: (err: unknown) => setError(err instanceof Error ? err.message : 'Failed to save title'),
  });

  const regenMutation = useMutation({
    mutationFn: () => regenerateTaskTitle(task.id),
    onSuccess: () => { setError(null); invalidate(); },
    onError: (err: unknown) => setError(err instanceof Error ? err.message : 'Failed to regenerate title'),
  });

  const save = () => { if (draft.trim()) saveMutation.mutate(); };

  if (editing) {
    return (
      <div className="flex flex-col gap-1.5">
        <input
          value={draft}
          autoFocus
          maxLength={200}
          onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Enter') { e.preventDefault(); save(); }
            if (e.key === 'Escape') { setEditing(false); setError(null); setDraft(task.title); }
          }}
          className="w-full px-2.5 py-1.5 text-lg font-extrabold text-slate-900 border border-hairline rounded-md focus:outline-none focus:ring-2 focus:ring-accent-ring focus:border-accent"
        />
        {error && <div className="text-2xs text-red-600">{error}</div>}
        <div className="flex justify-end gap-1.5">
          <button
            type="button"
            onClick={() => { setEditing(false); setError(null); setDraft(task.title); }}
            disabled={saveMutation.isPending}
            className="px-3 h-7 text-xs rounded-md border border-hairline bg-canvas text-slate-700 hover:bg-surface transition-colors disabled:opacity-50"
          >
            {t('title.cancel')}
          </button>
          <button
            type="button"
            onClick={save}
            disabled={saveMutation.isPending || !draft.trim()}
            className="px-3 h-7 text-xs font-semibold rounded-md bg-accent text-accent-fg hover:bg-accent-deep transition-colors disabled:opacity-50"
          >
            {saveMutation.isPending ? t('title.saving') : t('title.save')}
          </button>
        </div>
      </div>
    );
  }

  return (
    <div>
      <div className="group flex items-start justify-between gap-2">
      <div className="text-lg font-extrabold text-slate-900 break-words leading-tight min-w-0">{task.title}</div>
      <div className="flex items-center gap-1 flex-shrink-0">
        <button
          type="button"
          onClick={() => regenMutation.mutate()}
          disabled={regenMutation.isPending}
          title={t('title.regenerate')}
          aria-label={t('title.regenerate')}
          className="inline-flex items-center justify-center w-7 h-7 rounded-md text-slate-400 hover:text-accent hover:bg-surface transition-colors disabled:opacity-50"
        >
          <svg className={`w-3.5 h-3.5 ${regenMutation.isPending ? 'animate-spin' : ''}`} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3" />
          </svg>
        </button>
        <button
          type="button"
          onClick={() => { setDraft(task.title); setEditing(true); setError(null); }}
          title={t('title.edit')}
          aria-label={t('title.edit')}
          className="inline-flex items-center justify-center w-7 h-7 rounded-md text-slate-400 hover:text-slate-700 hover:bg-surface transition-colors"
        >
          <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="M11.5 2.5l2 2L6 12l-2.5.5L4 10l7.5-7.5z" />
          </svg>
        </button>
      </div>
      </div>
      {error && <div className="text-2xs text-red-600 mt-1">{error}</div>}
    </div>
  );
}

interface OverviewTabProps {
  task: LocalTask;
  subtaskActivities?: SubtaskActivity[];
  onSubtaskFilePreview?: SubtaskFilePreviewHandler;
}

export function OverviewTab({ task, subtaskActivities, onSubtaskFilePreview }: OverviewTabProps) {
  const status = task.latestJob?.status ?? 'queued';

  return (
    <div className="flex flex-col gap-3">
      <div className="bg-canvas border border-slate-200 rounded-xl p-4 shadow-sm">
        <TaskTitleRow task={task} />
        <div className="flex flex-wrap gap-2 mt-2">
          <StatusBadge status={status} />
          <span className="inline-flex items-center px-2 py-0.5 rounded-full text-2xs bg-slate-100 text-slate-600">{task.pieceName}</span>
          <span className="inline-flex items-center px-2 py-0.5 rounded-full text-2xs bg-slate-100 text-slate-600">{task.priority}</span>
        </div>
        <div className="mt-3 text-[13px] text-slate-600 whitespace-pre-wrap leading-relaxed">{task.body || '(no body)'}</div>
      </div>

      <MissionCard task={task} />

      <ContextUsageGauge
        promptTokens={task.latestJob?.contextPromptTokens}
        limitTokens={task.latestJob?.contextLimitTokens}
        jobStatus={task.latestJob?.status}
      />

      <FeedbackPanel task={task} />

      <ReflectionBadge taskId={task.id} />

      {task.subtasks && task.subtasks.length > 0 && (
        <SubtasksPanel
          taskId={task.id}
          subtasks={task.subtasks}
          subtaskCount={task.subtaskCount ?? task.subtasks.length}
          subtaskCompleted={task.subtaskCompleted ?? 0}
          subtaskActivities={subtaskActivities}
          onFilePreview={onSubtaskFilePreview}
        />
      )}
    </div>
  );
}
