export type Simulation = {
    id: number;
    name: string;
    created_at: string;
    config: string;
};

export function parseConfig(config: string) {
    let def = {
        altitude: null,
        uavMin: null,
        uavMax: null,
        ugvMin: null,
        ugvMax: null,
        pattern: null,
    };
    if (!config) return def;

    try {
        let cleanedConfig = config.replace(/"([^"]+)\.yaml"\s*:/g, '"$1":');
        let parsed = JSON.parse(cleanedConfig);
        let searchObj = parsed["search"] || parsed;
        let uavObj = parsed["uav"] || parsed;
        let ugvObj = parsed["ugv"] || parsed;

        let pattern = null;
        if (searchObj.spiral) pattern = "spiral";
        else if (searchObj.lawnmower) pattern = "lawnmower";
        else if (searchObj.levy) pattern = "levy";

        return {
            altitude: searchObj.altitude != null ? parseFloat(searchObj.altitude) : null,
            uavMin: uavObj.speed?.min_mph != null ? parseFloat(uavObj.speed.min_mph) : null,
            uavMax: uavObj.speed?.max_mph != null ? parseFloat(uavObj.speed.max_mph) : null,
            ugvMin: ugvObj.speed?.min_mph != null ? parseFloat(ugvObj.speed.min_mph) : null,
            ugvMax: ugvObj.speed?.max_mph != null ? parseFloat(ugvObj.speed.max_mph) : null,
            pattern: pattern,
        };
    } catch (e) {
        return def;
    }
}

export function formatDate(dateStr: string) {
    if (!dateStr) return "";
    return new Date(dateStr).toLocaleString("en-US", {
        timeZone: "America/New_York",
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        timeZoneName: "short"
    });
}

export class SimulationState {
    simulations = $state<Simulation[]>([]);
    error = $state("");

    searchQuery = $state("");
    filterDateFrom = $state("");
    filterDateTo = $state("");
    filterAltMin = $state("");
    filterAltMax = $state("");
    filterUavMin = $state("");
    filterUavMax = $state("");
    filterUgvMin = $state("");
    filterUgvMax = $state("");
    filterPattern = $state("any");

    sortOrder = $state("newest");
    currentPage = $state(1);
    itemsPerPage = 10;

    constructor() {
        $effect(() => {
            // Reset to page 1 whenever filters change
            if (
                this.searchQuery !== undefined ||
                this.sortOrder !== undefined ||
                this.filterDateFrom !== undefined ||
                this.filterDateTo !== undefined ||
                this.filterAltMin !== undefined ||
                this.filterAltMax !== undefined ||
                this.filterUavMin !== undefined ||
                this.filterUavMax !== undefined ||
                this.filterUgvMin !== undefined ||
                this.filterUgvMax !== undefined ||
                this.filterPattern !== undefined
            ) {
                // Tracking any mutation will trigger this effect
                let triggerVar = this.searchQuery + this.sortOrder + this.filterDateFrom + this.filterDateTo + this.filterAltMin + this.filterAltMax + this.filterUavMin + this.filterUavMax + this.filterUgvMin + this.filterUgvMax + this.filterPattern;
                this.currentPage = 1;
            }
        });
    }

    get filteredSimulations() {
        return this.simulations.filter((sim) => {
            let matchText = sim.id.toString().includes(this.searchQuery);
            if (!matchText) return false;

            let simDate = new Date(sim.created_at).getTime();
            if (this.filterDateFrom && simDate < new Date(this.filterDateFrom).getTime()) return false;
            // Provide +86400000 ms (1 day) to include the "To" date fully.
            if (this.filterDateTo && simDate > new Date(this.filterDateTo).getTime() + 86400000) return false;

            let p = parseConfig(sim.config);
            if (this.filterAltMin && p.altitude !== null && p.altitude < parseFloat(this.filterAltMin)) return false;
            if (this.filterAltMax && p.altitude !== null && p.altitude > parseFloat(this.filterAltMax)) return false;
            if (this.filterUavMin && p.uavMin !== null && p.uavMin < parseFloat(this.filterUavMin)) return false;
            if (this.filterUavMax && p.uavMax !== null && p.uavMax > parseFloat(this.filterUavMax)) return false;
            if (this.filterUgvMin && p.ugvMin !== null && p.ugvMin < parseFloat(this.filterUgvMin)) return false;
            if (this.filterUgvMax && p.ugvMax !== null && p.ugvMax > parseFloat(this.filterUgvMax)) return false;

            if (this.filterPattern !== "any" && p.pattern !== this.filterPattern) return false;

            return true;
        });
    }

    get sortedSimulations() {
        return [...this.filteredSimulations].sort((a, b) => {
            if (this.sortOrder === "newest") return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
            else if (this.sortOrder === "oldest") return new Date(a.created_at).getTime() - new Date(b.created_at).getTime();
            else if (this.sortOrder === "fastest" || this.sortOrder === "slowest") {
                let pA = parseConfig(a.config);
                let pB = parseConfig(b.config);
                let speedA = (pA.uavMax || 0) + (pA.ugvMax || 0);
                let speedB = (pB.uavMax || 0) + (pB.ugvMax || 0);
                if (this.sortOrder === "fastest") return speedB - speedA;
                else return speedA - speedB;
            }
            return 0;
        });
    }

    get totalPages() {
        return Math.max(1, Math.ceil(this.sortedSimulations.length / this.itemsPerPage));
    }

    get paginatedSimulations() {
        return this.sortedSimulations.slice(
            (this.currentPage - 1) * this.itemsPerPage,
            this.currentPage * this.itemsPerPage
        );
    }

    resetFilters() {
        this.searchQuery = "";
        this.filterDateFrom = "";
        this.filterDateTo = "";
        this.filterAltMin = "";
        this.filterAltMax = "";
        this.filterUavMin = "";
        this.filterUavMax = "";
        this.filterUgvMin = "";
        this.filterUgvMax = "";
        this.filterPattern = "any";
        this.sortOrder = "newest";
        this.currentPage = 1;
    }

    goToPage(page: number) {
        if (page >= 1 && page <= this.totalPages) {
            this.currentPage = page;
        }
    }
}
