/**
 * Color Strip Sources — Gradient entity management (modal + CRUD).
 * Extracted from color-strips.ts to reduce file size.
 */

import { fetchWithAuth } from '../../core/api.ts';
import { gradientsCache, GradientEntity } from '../../core/state.ts';
import { t } from '../../core/i18n.ts';
import { showToast, showConfirm } from '../../core/ui.ts';
import { Modal } from '../../core/modal.ts';
import { ICON_PALETTE, ICON_TRASH } from '../../core/icons.ts';
import { TagInput, renderTagChips } from '../../core/tag-input.ts';
import { escapeHtml } from '../../core/api.ts';
import {
    gradientInit, gradientRenderAll, getGradientStops, gradientSetIdPrefix,
} from '../css-gradient-editor.ts';

/* ── Helpers ──────────────────────────────────────────────────── */

function _getGradients(): GradientEntity[] {
    return gradientsCache.data || [];
}

function _findGradient(id: string): GradientEntity | undefined {
    return _getGradients().find(g => g.id === id);
}

function _gradientEntityStripHTML(stops: Array<{ position: number; color: number[] }>, w = 80, h = 16) {
    const css = stops.map(s => `rgb(${s.color.join(',')}) ${(s.position * 100).toFixed(0)}%`).join(', ');
    return `<span style="display:inline-block;width:${w}px;height:${h}px;border-radius:3px;background:linear-gradient(to right,${css});flex-shrink:0"></span>`;
}

/* ── Gradient entity items builder (shared with palettes) ────── */

export function buildGradientEntityItems() {
    const gradients = _getGradients();
    return gradients.map(g => ({
        value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
    }));
}

/** Sync <option> elements in a <select> from items array. */
export function syncSelectOptions(sel: HTMLSelectElement, items: Array<{ value: string; label: string }>) {
    sel.innerHTML = '';
    for (const item of items) {
        const opt = document.createElement('option');
        opt.value = item.value;
        opt.textContent = item.label;
        sel.appendChild(opt);
    }
}

/* ── Gradient preset picker refresh ──────────────────────────── */

export { _getGradients as getGradients, _findGradient as findGradient, _gradientEntityStripHTML as gradientEntityStripHTML };

/* ── Custom preset list below gradient editor ─────────────────── */

export function renderCustomPresetList() {
    const container = document.getElementById('css-editor-custom-presets-list') as HTMLElement | null;
    if (!container) return;
    const userGradients = _getGradients().filter(g => !g.is_builtin);
    if (userGradients.length === 0) {
        container.innerHTML = '';
        return;
    }
    container.innerHTML = userGradients.map(g => {
        const strip = _gradientEntityStripHTML(g.stops, 60, 14);
        const safeName = escapeHtml(g.name);
        return `<div class="custom-preset-row">
            ${strip}
            <span class="custom-preset-name">${safeName}</span>
            <button type="button" class="btn btn-icon btn-sm btn-secondary"
                onclick="onGradientPresetChange('${g.id}')"
                title="${t('color_strip.gradient.preset.apply')}">&#x2713;</button>
            <button type="button" class="btn btn-icon btn-sm btn-danger"
                onclick="deleteAndRefreshGradientPreset('${g.id}')"
                title="${t('common.delete')}">${ICON_TRASH}</button>
        </div>`;
    }).join('');
}

/* ── Inline preset actions (from CSS editor) ──────────────────── */

export function onGradientPresetChange(value: any) {
    if (!value) return;
    const g = _findGradient(value);
    if (g) {
        gradientInit(g.stops);
    }
}

export async function promptAndSaveGradientPreset() {
    const name = window.prompt(t('color_strip.gradient.preset.save_prompt'), '');
    if (!name || !name.trim()) return;
    const stops = getGradientStops().map(s => ({
        position: s.position,
        color: s.color,
    }));
    try {
        await fetchWithAuth('/gradients', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ name: name.trim(), stops }),
        });
        await gradientsCache.fetch({ force: true });
        showToast(t('color_strip.gradient.preset.saved'), 'success');
    } catch (e: any) {
        showToast(e.message || 'Failed to save gradient', 'error');
    }
}

export async function deleteAndRefreshGradientPreset(gradientId: any) {
    try {
        await fetchWithAuth(`/gradients/${gradientId}`, { method: 'DELETE' });
        await gradientsCache.fetch({ force: true });
        showToast(t('color_strip.gradient.preset.deleted'), 'success');
    } catch (e: any) {
        showToast(e.message || 'Failed to delete gradient', 'error');
    }
}

/* ── Gradient Editor Modal ────────────────────────────────────── */

class GradientEditorModal extends Modal {
    constructor() { super('gradient-editor-modal'); }

    snapshotValues() {
        return {
            name: (document.getElementById('gradient-editor-name') as HTMLInputElement).value,
            description: (document.getElementById('gradient-editor-description') as HTMLInputElement).value,
            stops: JSON.stringify(getGradientStops()),
            tags: JSON.stringify(_gradientTagsInput ? _gradientTagsInput.getValue() : []),
        };
    }

    onForceClose() {
        if (_gradientTagsInput) { _gradientTagsInput.destroy(); _gradientTagsInput = null; }
        gradientSetIdPrefix('');
    }
}

const gradientEditorModal = new GradientEditorModal();
let _gradientTagsInput: any = null;

export async function showGradientModal(editId: string | null = null, cloneData: any = null) {
    const titleEl = document.getElementById('gradient-editor-title')!;
    const idInput = document.getElementById('gradient-editor-id') as HTMLInputElement;
    const nameInput = document.getElementById('gradient-editor-name') as HTMLInputElement;
    const descInput = document.getElementById('gradient-editor-description') as HTMLInputElement;
    const errorEl = document.getElementById('gradient-editor-error') as HTMLElement;

    idInput.value = '';
    nameInput.value = '';
    descInput.value = '';
    errorEl.style.display = 'none';

    if (_gradientTagsInput) { _gradientTagsInput.destroy(); _gradientTagsInput = null; }
    const tagsContainer = document.getElementById('gradient-editor-tags-container')!;
    _gradientTagsInput = new TagInput(tagsContainer, { placeholder: t('tags.placeholder') });

    let stops = [{ position: 0.0, color: [255, 0, 0] }, { position: 1.0, color: [0, 0, 255] }];

    if (editId) {
        const g = _findGradient(editId);
        if (!g) return;
        idInput.value = g.id;
        nameInput.value = g.name;
        descInput.value = g.description || '';
        _gradientTagsInput.setValue(g.tags || []);
        stops = g.stops;
        titleEl.innerHTML = `${ICON_PALETTE} ${t('gradient.edit')}`;
    } else if (cloneData) {
        nameInput.value = (cloneData.name || '') + ' (Copy)';
        descInput.value = cloneData.description || '';
        _gradientTagsInput.setValue(cloneData.tags || []);
        stops = cloneData.stops || stops;
        titleEl.innerHTML = `${ICON_PALETTE} ${t('gradient.add')}`;
    } else {
        titleEl.innerHTML = `${ICON_PALETTE} ${t('gradient.add')}`;
    }

    gradientEditorModal.open();
    requestAnimationFrame(() => {
        gradientSetIdPrefix('ge-');
        gradientInit(stops);
        gradientEditorModal.snapshot();
    });
}

export async function closeGradientEditor() {
    await gradientEditorModal.close();
}

export async function saveGradientEntity() {
    const id = (document.getElementById('gradient-editor-id') as HTMLInputElement).value;
    const name = (document.getElementById('gradient-editor-name') as HTMLInputElement).value.trim();
    const description = (document.getElementById('gradient-editor-description') as HTMLInputElement).value.trim() || null;
    const tags = _gradientTagsInput ? _gradientTagsInput.getValue() : [];
    const errorEl = document.getElementById('gradient-editor-error') as HTMLElement;

    if (!name) {
        errorEl.textContent = t('gradient.error.name_required');
        errorEl.style.display = '';
        return;
    }

    const stops = getGradientStops().map(s => ({
        position: s.position,
        color: [...s.color],
    }));

    if (stops.length < 2) {
        errorEl.textContent = t('gradient.error.min_stops');
        errorEl.style.display = '';
        return;
    }

    const payload: any = { name, stops, description, tags };

    try {
        const url = id ? `/gradients/${id}` : '/gradients';
        const method = id ? 'PUT' : 'POST';
        const res = await fetchWithAuth(url, { method, body: JSON.stringify(payload) });
        if (!res!.ok) {
            const err = await res!.json();
            throw new Error(err.detail || 'Failed to save gradient');
        }

        showToast(id ? t('gradient.updated') : t('gradient.created'), 'success');
        gradientsCache.invalidate();
        gradientEditorModal.forceClose();
        if (window.loadPictureSources) await window.loadPictureSources();
    } catch (e: any) {
        if (e.isAuth) return;
        errorEl.textContent = e.message;
        errorEl.style.display = '';
    }
}

export async function cloneGradient(gradientId: string) {
    const g = _findGradient(gradientId);
    if (!g) return;
    await showGradientModal(null, g);
}

export async function editGradient(gradientId: string) {
    await showGradientModal(gradientId);
}

export async function deleteGradient(gradientId: string) {
    const g = _findGradient(gradientId);
    if (!g) return;
    const ok = await showConfirm(t('gradient.confirm_delete', { name: g.name }));
    if (!ok) return;
    try {
        await fetchWithAuth(`/gradients/${gradientId}`, { method: 'DELETE' });
        gradientsCache.invalidate();
        showToast(t('gradient.deleted'), 'success');
        if (window.loadPictureSources) await window.loadPictureSources();
    } catch (e: any) {
        if (e.isAuth) return;
        showToast(e.message || t('gradient.error.delete_failed'), 'error');
    }
}
