import { useState, useEffect, useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { stringify, parse } from 'yaml';
import { usePiece } from '../../hooks/usePieces';
import { updatePiece, deletePiece } from '../../api';
import { useUrlState } from '../../hooks/useUrlState';
import { PieceMetaForm } from './PieceMetaForm';
import { MovementAccordion } from './MovementAccordion';

export interface PieceEditorProps {
  name: string;
  /** Whether the current user has admin role. Controls edit access for built-in/global-custom pieces. */
  isAdmin?: boolean;
  /**
   * Source hint from URL / list selection — used for the targeted GET request.
   * The read-only gate uses the SOURCE the API actually resolved (authoritative),
   * so a deep link without pieceSource still renders correctly for non-admins.
   */
  source?: 'builtin' | 'user-custom' | 'global-custom';
}

export function PieceEditor({ name, isAdmin = true, source }: PieceEditorProps) {
  const { data: fetchResult, isLoading, error } = usePiece(name, source);
  // Use the server-resolved source as the authoritative value; fall back to the
  // prop only while the fetch hasn't completed yet (avoids flicker on known paths).
  const piece = fetchResult?.piece ?? null;
  const effectiveSource = fetchResult?.source ?? source;
  const queryClient = useQueryClient();
  const { setUrlState } = useUrlState();

  const [draft, setDraft] = useState<any>(null);
  const [isDirty, setIsDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const [toast, setToast] = useState<string | null>(null);

  // YAML editing mode
  const [editMode, setEditMode] = useState<'visual' | 'yaml'>('visual');
  const [yamlText, setYamlText] = useState('');
  const [yamlError, setYamlError] = useState<string | null>(null);

  useEffect(() => {
    if (piece) {
      setDraft(structuredClone(piece));
      setIsDirty(false);
      setEditMode('visual');
      setYamlError(null);
    }
  }, [piece]); // piece is derived from fetchResult above

  const showToast = (msg: string, duration = 2000) => {
    setToast(msg);
    setTimeout(() => setToast(null), duration);
  };

  const handleMetaChange = useCallback((field: string, value: any) => {
    setDraft((prev: any) => {
      if (field === 'triggers.keywords') {
        return { ...prev, triggers: { ...prev.triggers, keywords: value } };
      }
      return { ...prev, [field]: value };
    });
    setIsDirty(true);
  }, []);

  const handleMovementChange = useCallback((index: number, field: string, value: any) => {
    setDraft((prev: any) => {
      const movements = [...prev.movements];
      movements[index] = { ...movements[index], [field]: value };
      return { ...prev, movements };
    });
    setIsDirty(true);
  }, []);

  const handleAddMovement = useCallback(() => {
    setDraft((prev: any) => ({
      ...prev,
      movements: [
        ...prev.movements,
        {
          name: `step_${prev.movements.length + 1}`,
          persona: '',
          default_next: 'COMPLETE',
          edit: false,
          instruction: '',
          allowed_tools: [],
          rules: [],
        },
      ],
    }));
    setIsDirty(true);
  }, []);

  const handleRemoveMovement = useCallback((index: number) => {
    setDraft((prev: any) => ({
      ...prev,
      movements: prev.movements.filter((_: any, i: number) => i !== index),
    }));
    setIsDirty(true);
  }, []);

  const handleMoveMovement = useCallback((index: number, direction: 'up' | 'down') => {
    setDraft((prev: any) => {
      const movements = [...prev.movements];
      const targetIndex = direction === 'up' ? index - 1 : index + 1;
      if (targetIndex < 0 || targetIndex >= movements.length) return prev;
      [movements[index], movements[targetIndex]] = [movements[targetIndex], movements[index]];
      return { ...prev, movements };
    });
    setIsDirty(true);
  }, []);

  // Switch to YAML editing mode
  const switchToYaml = () => {
    const text = stringify(draft, { lineWidth: 120 });
    setYamlText(text);
    setYamlError(null);
    setEditMode('yaml');
  };

  // Switch to visual editing mode
  const switchToVisual = () => {
    try {
      const parsed = parse(yamlText);
      if (!parsed || typeof parsed !== 'object') {
        setYamlError('YAML のパースに失敗しました');
        return;
      }
      setDraft(parsed);
      setYamlError(null);
      setEditMode('visual');
      setIsDirty(true);
    } catch (e: any) {
      setYamlError(e.message);
    }
  };

  const handleYamlChange = (text: string) => {
    setYamlText(text);
    setYamlError(null);
    setIsDirty(true);
  };

  const handleDiscard = () => {
    if (piece) {
      setDraft(structuredClone(piece));
      setIsDirty(false);
      setEditMode('visual');
      setYamlError(null);
    }
  };

  const handleSave = async () => {
    if (!draft) return;

    let saveData = draft;
    if (editMode === 'yaml') {
      try {
        saveData = parse(yamlText);
        if (!saveData || typeof saveData !== 'object') {
          showToast('エラー: YAML のパースに失敗しました', 3000);
          return;
        }
      } catch (e: any) {
        showToast(`エラー: YAML パースエラー — ${e.message}`, 3000);
        return;
      }
    }

    // Ensure name matches
    saveData.name = name;

    setSaving(true);
    try {
      await updatePiece(name, saveData, effectiveSource);
      await queryClient.invalidateQueries({ queryKey: ['piece', name] });
      await queryClient.invalidateQueries({ queryKey: ['pieces'] });
      setIsDirty(false);
      if (editMode === 'yaml') {
        setDraft(saveData);
      }
      showToast('保存しました');
    } catch (e: any) {
      showToast(`エラー: ${e.message}`, 3000);
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!confirm(`Piece "${name}" を削除しますか？この操作は取り消せません。`)) return;
    try {
      await deletePiece(name, effectiveSource);
      await queryClient.invalidateQueries({ queryKey: ['pieces'] });
      setUrlState((prev) => ({ ...prev, piece: undefined, section: 'provider' as any }));
    } catch (e: any) {
      showToast(`エラー: ${e.message}`, 3000);
    }
  };

  if (isLoading) return <div className="text-sm text-slate-400">Loading...</div>;
  if (error) return <div className="text-sm text-red-500">Piece の読み込みに失敗しました</div>;
  if (!draft) return null;

  // Non-admins cannot edit built-in or global-custom pieces — read-only view.
  // user-custom stays editable for its owner. Admins can edit all sources.
  // Use the SERVER-RESOLVED source (effectiveSource) as the authoritative value so
  // that deep links without a ?pieceSource param still render read-only for non-admins.
  const readonly = !isAdmin && (effectiveSource === 'builtin' || effectiveSource === 'global-custom');

  const movementNames = (draft.movements ?? []).map((m: any) => m.name ?? '');

  return (
    <div className="max-w-2xl">
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div>
          <h2 className="text-lg font-semibold text-slate-800">{draft.name}</h2>
          {draft.description && (
            <p className="text-sm text-slate-500 mt-0.5 line-clamp-2">{String(draft.description).split('\n')[0]}</p>
          )}
        </div>
        {/* Delete is hidden for ALL built-in pieces (non-deletable by everyone, including admins). */}
        {!readonly && effectiveSource !== 'builtin' && (
          <button
            type="button"
            onClick={handleDelete}
            className="px-3 py-1.5 text-xs text-red-600 hover:bg-red-50 rounded-lg border border-red-200"
          >
            Delete
          </button>
        )}
        {readonly && (
          <span className="px-2 py-1 text-xs text-slate-400 bg-slate-100 rounded border border-slate-200">
            読み取り専用
          </span>
        )}
      </div>

      {/* Mode toggle */}
      <div className="flex items-center gap-1 mb-4 bg-slate-100 rounded-lg p-0.5 w-fit">
        <button
          onClick={() => editMode === 'yaml' ? switchToVisual() : undefined}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            editMode === 'visual'
              ? 'bg-white text-slate-800 shadow-sm'
              : 'text-slate-500 hover:text-slate-700'
          }`}
        >
          Visual
        </button>
        <button
          onClick={() => editMode === 'visual' ? switchToYaml() : undefined}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            editMode === 'yaml'
              ? 'bg-white text-slate-800 shadow-sm'
              : 'text-slate-500 hover:text-slate-700'
          }`}
        >
          YAML
        </button>
      </div>

      {editMode === 'visual' ? (
        <>
          {/* Meta form */}
          <div className="mb-8">
            <PieceMetaForm
              piece={draft}
              onChange={handleMetaChange}
              movementNames={movementNames}
              disabled={readonly}
            />
          </div>

          {/* Movements */}
          <div className="mb-6">
            <MovementAccordion
              movements={draft.movements ?? []}
              onChange={handleMovementChange}
              onAdd={handleAddMovement}
              onRemove={handleRemoveMovement}
              onMove={handleMoveMovement}
              disabled={readonly}
            />
          </div>
        </>
      ) : (
        /* YAML editor */
        <div className="mb-6">
          {yamlError && (
            <div className="mb-2 px-3 py-2 bg-red-50 border border-red-200 rounded-lg text-xs text-red-600">
              {yamlError}
            </div>
          )}
          <textarea
            value={yamlText}
            onChange={(e) => handleYamlChange(e.target.value)}
            spellCheck={false}
            readOnly={readonly}
            disabled={readonly}
            className={`w-full px-4 py-3 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none font-mono leading-relaxed resize-y ${readonly ? 'bg-slate-100 text-slate-500 cursor-not-allowed' : 'bg-slate-50'}`}
            style={{ minHeight: '500px', tabSize: 2 }}
          />
          <p className="text-xs text-slate-400 mt-1">
            YAML を直接編集できます。Visual モードに切り替えると自動でパースされます。
          </p>
        </div>
      )}

      {/* Footer */}
      {!readonly && (
        <div className="flex items-center justify-end gap-3 pt-4 mt-6 border-t border-slate-200">
          {toast && (
            <span className={`text-xs mr-auto ${toast.startsWith('エラー') ? 'text-red-500' : 'text-green-600'}`}>
              {toast}
            </span>
          )}
          <button
            onClick={handleDiscard}
            disabled={!isDirty}
            className="px-4 py-2 text-sm text-slate-600 hover:bg-slate-100 rounded-lg disabled:opacity-50"
          >
            Discard Changes
          </button>
          <button
            onClick={handleSave}
            disabled={!isDirty || saving}
            className="px-4 py-2 text-sm bg-accent text-accent-fg rounded-lg hover:bg-accent-deep disabled:opacity-50"
          >
            {saving ? 'Saving...' : 'Save'}
          </button>
        </div>
      )}
    </div>
  );
}
