package p.studio.workspaces.assets.details.schema;

import p.studio.workspaces.assets.messages.AssetWorkspaceBankCompositionFile;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

record AssetDetailsColorSchemaDraft(
        String schemaId,
        boolean existingSchema,
        boolean removeRequested,
        List<AssetWorkspaceBankCompositionFile> availableTiles,
        List<AssetWorkspaceBankCompositionFile> assignedTiles,
        List<String> preferredColors,
        boolean deriveColorsFromTiles) {

    AssetDetailsColorSchemaDraft {
        availableTiles = List.copyOf(availableTiles);
        assignedTiles = List.copyOf(assignedTiles);
        preferredColors = normalize(preferredColors);
    }

    static AssetDetailsColorSchemaDraft noSelection() {
        return new AssetDetailsColorSchemaDraft(null, false, false, List.of(), List.of(), List.of(), false);
    }

    boolean selected() {
        return schemaId != null && !schemaId.isBlank();
    }

    AssetDetailsColorSchemaDraft moveToAssigned(List<AssetWorkspaceBankCompositionFile> files) {
        final List<AssetWorkspaceBankCompositionFile> nextAvailable = new ArrayList<>(availableTiles);
        final List<AssetWorkspaceBankCompositionFile> nextAssigned = new ArrayList<>(assignedTiles);
        for (AssetWorkspaceBankCompositionFile file : files) {
            if (nextAvailable.remove(file) && !nextAssigned.contains(file)) {
                nextAssigned.add(file);
            }
        }
        return withTiles(nextAvailable, nextAssigned);
    }

    AssetDetailsColorSchemaDraft moveToAvailable(List<AssetWorkspaceBankCompositionFile> files) {
        final List<AssetWorkspaceBankCompositionFile> nextAvailable = new ArrayList<>(availableTiles);
        final List<AssetWorkspaceBankCompositionFile> nextAssigned = new ArrayList<>(assignedTiles);
        for (AssetWorkspaceBankCompositionFile file : files) {
            if (nextAssigned.remove(file) && !nextAvailable.contains(file)) {
                nextAvailable.add(file);
            }
        }
        return withTiles(nextAvailable, nextAssigned);
    }

    AssetDetailsColorSchemaDraft moveAssignedUp(int index) {
        if (index <= 0 || index >= assignedTiles.size()) {
            return this;
        }
        final List<AssetWorkspaceBankCompositionFile> nextAssigned = new ArrayList<>(assignedTiles);
        final AssetWorkspaceBankCompositionFile file = nextAssigned.remove(index);
        nextAssigned.add(index - 1, file);
        return withTiles(availableTiles, nextAssigned);
    }

    AssetDetailsColorSchemaDraft moveAssignedDown(int index) {
        if (index < 0 || index >= assignedTiles.size() - 1) {
            return this;
        }
        final List<AssetWorkspaceBankCompositionFile> nextAssigned = new ArrayList<>(assignedTiles);
        final AssetWorkspaceBankCompositionFile file = nextAssigned.remove(index);
        nextAssigned.add(index + 1, file);
        return withTiles(availableTiles, nextAssigned);
    }

    AssetDetailsColorSchemaDraft markForRemoval() {
        if (!selected()) {
            return this;
        }
        return new AssetDetailsColorSchemaDraft(schemaId, existingSchema, true, availableTiles, assignedTiles, preferredColors, deriveColorsFromTiles);
    }

    AssetDetailsColorSchemaDraft asUpdateDraft() {
        return new AssetDetailsColorSchemaDraft(schemaId, existingSchema, false, availableTiles, assignedTiles, orderedColors(), true);
    }

    List<String> orderedColors() {
        if (!deriveColorsFromTiles) {
            return preferredColors;
        }
        final LinkedHashSet<String> active = new LinkedHashSet<>();
        for (AssetWorkspaceBankCompositionFile tile : assignedTiles) {
            AssetDetailsColorSchemaCoordinator.tileColors(tile).stream()
                    .map(AssetDetailsColorSchemaDraft::normalize)
                    .forEach(active::add);
        }
        final List<String> ordered = new ArrayList<>();
        for (String preferredColor : preferredColors) {
            if (active.contains(preferredColor) && !ordered.contains(preferredColor)) {
                ordered.add(preferredColor);
            }
        }
        for (String color : active) {
            if (!ordered.contains(color)) {
                ordered.add(color);
            }
        }
        return List.copyOf(ordered);
    }

    private AssetDetailsColorSchemaDraft withTiles(
            List<AssetWorkspaceBankCompositionFile> nextAvailable,
            List<AssetWorkspaceBankCompositionFile> nextAssigned) {
        return new AssetDetailsColorSchemaDraft(schemaId, existingSchema, false, nextAvailable, nextAssigned, orderedColors(), true);
    }

    private static List<String> normalize(List<String> colors) {
        final List<String> normalized = new ArrayList<>();
        for (String color : colors) {
            if (color == null || color.isBlank()) {
                continue;
            }
            normalized.add(normalize(color));
        }
        return List.copyOf(normalized);
    }

    private static String normalize(String color) {
        return color.trim().toUpperCase();
    }
}
