
import { ContentEditable } from "@common/components/ContentEditable";
import { useState } from "preact/hooks";
import styles from '../../assets/character-editor.module.css';
import { CharacterRole, useAppState, type Character } from "../../contexts/state";
import LLM from "../../utils/llm";
import { extractString } from "@common/utils";

export const CharacterEditor = ({ visible }: { visible: boolean }) => {
    const { currentWorld, currentStory, mergedCharacters, dispatch, connection, model } = useAppState();
    const [newNickname, setNewNickname] = useState<Record<string, string>>({});
    const [newRelation, setNewRelation] = useState<Record<string, { name: string; relation: string }>>({});
    const [showDeleteConfirm, setShowDeleteConfirm] = useState<string | null>(null);
    const [generatingShortDesc, setGeneratingShortDesc] = useState<string | null>(null);

    if (!currentWorld || !visible) {
        return null;
    }

    // When a story is selected, edit story-level characters; otherwise world-level
    const storyId = currentStory?.id ?? null;
    const worldId = currentWorld.id;
    const characters = currentStory ? currentStory.characters : currentWorld.characters;

    const handleAddCharacter = () => {
        dispatch({
            type: 'ADD_CHARACTER',
            worldId,
            storyId,
            character: {
                id: crypto.randomUUID(),
                name: 'New Character',
                role: CharacterRole.Main,
                nicknames: [],
                shortDescription: '',
                description: '',
                relations: [],
            },
        });
    };

    const handleEditCharacter = (characterId: string, field: keyof Character, value: string[] | string | Event) => {
        if (!Array.isArray(value)) {
            value = extractString(value);
        }
        dispatch({
            type: 'EDIT_CHARACTER',
            worldId,
            storyId,
            characterId,
            updates: { [field]: value },
        });
    };

    const handleDeleteCharacter = (characterId: string) => {
        dispatch({
            type: 'DELETE_CHARACTER',
            worldId,
            storyId,
            characterId,
        });
    };

    const handleAddRelation = (characterId: string) => {
        const rel = newRelation[characterId] || { name: '', relation: '' };
        if (!rel.name.trim() || !rel.relation.trim()) return;

        dispatch({
            type: 'ADD_CHARACTER_RELATION',
            worldId,
            storyId,
            characterId,
            relation: { name: rel.name.trim(), relation: rel.relation.trim() },
        });
        setNewRelation({ ...newRelation, [characterId]: { name: '', relation: '' } });
    };

    const handleEditRelation = (characterId: string, targetName: string, field: 'name' | 'relation', value: string | Event) => {
        dispatch({
            type: 'EDIT_CHARACTER_RELATION',
            worldId,
            storyId,
            characterId,
            targetName,
            updates: { [field]: extractString(value) },
        });
    };

    const handleDeleteRelation = (characterId: string, targetName: string) => {
        dispatch({
            type: 'DELETE_CHARACTER_RELATION',
            worldId,
            storyId,
            characterId,
            targetName,
        });
    };

    const handleNicknameAdd = (characterId: string) => {
        const nickname = (newNickname[characterId] || '').trim();
        if (!nickname) return;

        const character = characters.find(c => c.id === characterId);
        if (character) {
            handleEditCharacter(characterId, 'nicknames', [...character.nicknames, nickname]);
            setNewNickname({ ...newNickname, [characterId]: '' });
        }
    };

    const handleNicknameDelete = (characterId: string, nickname: string) => {
        const character = characters.find(c => c.id === characterId);
        if (character) {
            handleEditCharacter(characterId, 'nicknames', character.nicknames.filter(n => n !== nickname));
        }
    };

    const handleNewRelationChange = (characterId: string, field: 'name' | 'relation', value: string | Event) => {
        value = extractString(value);
        const current = newRelation[characterId] || { name: '', relation: '' };
        setNewRelation({ ...newRelation, [characterId]: { ...current, [field]: value } });
    };

    const handleGenerateShortDescription = async (characterId: string) => {
        if (!connection || !model) return;

        const character = characters.find(c => c.id === characterId);
        if (!character || !character.description.trim()) return;

        setGeneratingShortDesc(characterId);
        try {
            const shortDesc = await LLM.summarize(connection, model.id, character.description, 'sentence');
            handleEditCharacter(characterId, 'shortDescription', shortDesc.trim());
        } catch (error) {
            console.error('Failed to generate short description:', error);
        } finally {
            setGeneratingShortDesc(null);
        }
    };

    return (
        <div class={styles.characterEditor}>
            <div class={styles.header}>
                <h2>{currentStory ? 'Story Characters' : 'World Characters'}</h2>
                <button class={styles.addButton} onClick={handleAddCharacter}>
                    + Add Character
                </button>
            </div>

            <div class={styles.list}>
                {characters.length === 0 && (
                    <p class={styles.empty}>No characters yet. Add your first character!</p>
                )}

                {characters.map((character) => (
                    <div key={character.id} class={styles.characterCard}>
                        <div class={styles.cardHeader}>
                            <input
                                type="text"
                                class={styles.nameInput}
                                value={character.name}
                                onInput={(e) => handleEditCharacter(character.id, 'name', e)}
                                onFocus={(e) => e.currentTarget.select()}
                                placeholder="Character name"
                            />
                            {showDeleteConfirm === character.id ? (
                                <div class={styles.deleteConfirm}>
                                    <span>Delete?</span>
                                    <button
                                        class={styles.confirmButton}
                                        onClick={() => {
                                            handleDeleteCharacter(character.id);
                                            setShowDeleteConfirm(null);
                                        }}
                                    >
                                        Yes
                                    </button>
                                    <button
                                        class={styles.cancelButton}
                                        onClick={() => setShowDeleteConfirm(null)}
                                    >
                                        No
                                    </button>
                                </div>
                            ) : (
                                <button
                                    class={styles.deleteButton}
                                    onClick={() => setShowDeleteConfirm(character.id)}
                                >
                                    ×
                                </button>
                            )}
                        </div>

                        <div class={styles.field}>
                            <div class={styles.label}>Role</div>
                            <select
                                class={styles.select}
                                value={character.role}
                                onInput={(e) => handleEditCharacter(character.id, 'role', e)}
                            >
                                {Object.entries(CharacterRole)
                                    .filter(([, value]) => typeof value === 'string')
                                    .map(([key, value]) => (
                                        <option key={key} value={value}>
                                            {key.charAt(0).toUpperCase() + key.slice(1).toLowerCase()}
                                        </option>
                                    ))}
                            </select>
                        </div>

                        <div class={styles.field}>
                            <div class={styles.label}>Description</div>
                            <ContentEditable
                                autoLines
                                class={styles.textarea}
                                value={character.description}
                                onInput={(e) => handleEditCharacter(character.id, 'description', e)}
                                placeholder="Full character description..."
                            />
                        </div>

                        <div class={styles.field}>
                            <div class={styles.label}>
                                Short Description
                                <button
                                    class={styles.generateButton}
                                    onClick={() => handleGenerateShortDescription(character.id)}
                                    disabled={!character.description.trim() || generatingShortDesc === character.id || !connection || !model}
                                >
                                    {generatingShortDesc === character.id ? 'Generating...' : 'Generate'}
                                </button>
                            </div>
                            <textarea
                                class={styles.textarea}
                                value={character.shortDescription}
                                onInput={(e) => handleEditCharacter(character.id, 'shortDescription', e)}
                                placeholder="Brief description (one line)..."
                                rows={1}
                            />
                        </div>

                        <div class={styles.field}>
                            <div class={styles.label}>
                                Nicknames
                                <div class={styles.addInput}>
                                    <input
                                        type="text"
                                        class={styles.addInputField}
                                        value={newNickname[character.id] || ''}
                                        onInput={(e) => setNewNickname({ ...newNickname, [character.id]: extractString(e) })}
                                        onKeyDown={(e) => {
                                            if (e.key === 'Enter') {
                                                e.preventDefault();
                                                handleNicknameAdd(character.id);
                                            }
                                        }}
                                        placeholder="Add nickname..."
                                    />
                                    <button
                                        class={styles.smallButton}
                                        onClick={() => handleNicknameAdd(character.id)}
                                    >
                                        +
                                    </button>
                                </div>
                            </div>
                            <div class={styles.nicknames}>
                                {character.nicknames.length === 0 && (
                                    <span class={styles.empty}>No nicknames</span>
                                )}
                                {character.nicknames.map((nickname, idx) => (
                                    <span key={idx} class={styles.badge}>
                                        {nickname}
                                        <button
                                            class={styles.badgeRemove}
                                            onClick={() => handleNicknameDelete(character.id, nickname)}
                                        >
                                            ×
                                        </button>
                                    </span>
                                ))}
                            </div>
                        </div>

                        <div class={styles.field}>
                            <div class={styles.label}>
                                Relations
                                <div class={styles.addInput}>
                                    <select
                                        class={styles.addInputField}
                                        value={(newRelation[character.id]?.name) || ''}
                                        onInput={(e) => handleNewRelationChange(character.id, 'name', e)}
                                    >
                                        <option value="" disabled>Select character</option>
                                        {mergedCharacters
                                            .filter(c => c.id !== character.id)
                                            .map(c => (
                                                <option key={c.id} value={c.name}>{c.name}</option>
                                            ))}
                                    </select>
                                    <input
                                        type="text"
                                        class={styles.addInputField}
                                        value={(newRelation[character.id]?.relation) || ''}
                                        onInput={(e) => handleNewRelationChange(character.id, 'relation', e)}
                                        onKeyDown={(e) => {
                                            if (e.key === 'Enter') {
                                                e.preventDefault();
                                                handleAddRelation(character.id);
                                            }
                                        }}
                                        placeholder="Relationship"
                                    />
                                    <button
                                        class={styles.smallButton}
                                        onClick={() => handleAddRelation(character.id)}
                                    >
                                        +
                                    </button>
                                </div>
                            </div>
                            <div class={styles.relations}>
                                {character.relations.length === 0 && (
                                    <span class={styles.empty}>No relations</span>
                                )}
                                {character.relations.map((rel, idx) => (
                                    <div key={idx} class={styles.relationRow}>
                                        <select
                                            class={styles.relationInput}
                                            value={rel.name}
                                            onInput={(e) => handleEditRelation(character.id, rel.name, 'name', e)}
                                        >
                                            {mergedCharacters
                                                .filter(c => c.id !== character.id)
                                                .map(c => (
                                                    <option key={c.id} value={c.name}>{c.name}</option>
                                                ))}
                                        </select>
                                        <input
                                            type="text"
                                            class={styles.relationInput}
                                            value={rel.relation}
                                            onInput={(e) => handleEditRelation(character.id, rel.name, 'relation', e)}
                                            placeholder="Relationship"
                                        />
                                        <button
                                            class={styles.smallButton}
                                            onClick={() => handleDeleteRelation(character.id, rel.name)}
                                        >
                                            ×
                                        </button>
                                    </div>
                                ))}
                            </div>
                        </div>
                    </div>
                ))}
            </div>
        </div>
    );
};
