"use strict";
// #region Constants
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
const DEFAULT_CONTENT_SETTINGS = {
    eventId: 3730,
    quantity: 1,
    searchType: "Resale",
    minPrice: 0,
    maxPrice: 6000,
    interval: 7000,
    sound: "none",
    errorSound: "none",
    startSound: "none"
};
var SearchTypesEnum;
(function (SearchTypesEnum) {
    SearchTypesEnum["Regular"] = "Regular";
    SearchTypesEnum["Resale"] = "Resale";
})(SearchTypesEnum || (SearchTypesEnum = {}));
// #region Factory
class TicketmasterRequestsFactory {
    create(gameId, searchType, quantity, searchIndex = 0) {
        switch (searchType) {
            case SearchTypesEnum.Regular:
                return new SearchListTickets(gameId, searchType, quantity, searchIndex);
                break;
            case SearchTypesEnum.Resale:
                return new SearchListTickets(gameId, searchType, quantity, searchIndex);
                break;
            default:
                return new SearchListTickets(gameId, searchType, quantity, searchIndex);
                break;
        }
    }
}
// #endregion Factory
const getHeaders = (gameId) => {
    return {
        'accept': 'application/json, text/plain, */*',
        'accept-language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7',
        'cookie': document.cookie,
        'priority': 'u=1, i',
        'referer': gameId === 0
            ? 'https://www.eticketing.co.uk/arsenal/Events'
            : `https://www.eticketing.co.uk/arsenal/EDP/Event/Index/${gameId}?position=1`,
        'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"macOS"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
        'content-type': "application/json",
    };
};
const handleRequest = (gameId_1, url_1, method_1, body_1, ...args_1) => __awaiter(void 0, [gameId_1, url_1, method_1, body_1, ...args_1], void 0, function* (gameId, url, method, body, responseJson = true) {
    let options = {
        method: method,
        headers: getHeaders(gameId)
    };
    if (body)
        options.body = JSON.stringify(body);
    let response = null;
    try {
        response = yield fetch(url, options);
    }
    catch (error) {
        console.log('Error handling the request. Trying again.');
        console.log(error);
    }
    if (response === null)
        return { isSuccess: false, status: -1, body: null };
    let responseBody = null;
    try {
        responseBody = (responseJson) ? yield response.json() : null;
    }
    catch (error) {
        responseBody = null;
    }
    let resultResponse = {
        status: response.status,
        isSuccess: (response.status === 200) ? true : false,
        body: responseBody,
    };
    return resultResponse;
});
const deletePurgLocks = (gameId) => __awaiter(void 0, void 0, void 0, function* () {
    let url = `https://www.eticketing.co.uk/arsenal/EDP/BestAvailable/PurgeLocks`;
    let response = yield handleRequest(gameId, url, 'DELETE', { eventId: gameId }, false);
    return response.isSuccess;
});
const basketSeats = (gameId) => __awaiter(void 0, void 0, void 0, function* () {
    let url = `https://www.eticketing.co.uk/arsenal/EDP/Ism/BasketSeats`;
    let response = yield handleRequest(gameId, url, 'GET', { eventId: gameId }, false);
    return response.isSuccess;
});
class SearchListTickets {
    constructor(gameId, searchType, quantity, searchIndex, minPrice = 0, maxPrice = 6000) {
        this.gameId = gameId;
        this.searchType = searchType;
        this.quantity = quantity;
        this.seatsTogehther = (quantity > 1) ? true : false;
        this.searchIndex = searchIndex;
        this.minPrice = minPrice;
        this.maxPrice = maxPrice;
        this.searchUrl = `https://www.eticketing.co.uk/arsenal/EDP/Seats/Available${this.searchType}?AreSeatsTogether=${this.seatsTogehther}&EventId=${this.gameId}&MarketType=1&MaximumPrice=${this.maxPrice}&MinimumPrice=0&Quantity=${this.quantity}`;
        this.lockTicketUrl = `https://www.eticketing.co.uk/arsenal/EDP/BestAvailable/${this.searchType}Seats`;
    }
    handle() {
        return __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            let searchResponse = yield handleRequest(this.gameId, this.searchUrl, 'GET');
            // If search fails (but not just 404 'no tickets'), throw to trigger error sound
            if (!searchResponse.isSuccess && searchResponse.status !== 404 && searchResponse.status !== -1) {
                throw new Error(`Search request failed with status ${searchResponse.status}`);
            }
            if (searchResponse.body && searchResponse.body.length > 0) {
                let cheapestTicket = searchResponse.body[this.searchIndex];
                for (let i = 0; i < searchResponse.body.length; i++) {
                    if (searchResponse.body[i].PriceBands[0].MinimalBayerAmount < cheapestTicket.PriceBands[0].MinimalBayerAmount) {
                        cheapestTicket = searchResponse.body[i];
                    }
                }
                // //console.log(cheapestTicket.PriceBands[0]?.MinimalBayerAmount!);
                if (((_a = cheapestTicket.PriceBands[0]) === null || _a === void 0 ? void 0 : _a.MinimalBayerAmount) < this.minPrice ||
                    ((_b = cheapestTicket.PriceBands[0]) === null || _b === void 0 ? void 0 : _b.MinimalBayerAmount) > this.maxPrice) {
                    console.log('not in price range');
                    return false;
                }
                let postLockTicketResponse = yield handleRequest(this.gameId, this.lockTicketUrl, 'POST', {
                    EventId: this.gameId,
                    Quantity: this.quantity,
                    AreSeatsTogether: this.seatsTogehther,
                    AreaId: cheapestTicket.AreaId,
                    PriceBandId: cheapestTicket.PriceBands[0].PriceBandCode,
                    IsGeneralAdmissionEnabled: false,
                    SeatAttributeIds: [],
                    MinimumPrice: 0,
                    MaximumPrice: 10000000
                });
                if (!postLockTicketResponse.isSuccess) {
                    throw new Error(`Lock request (POST) failed with status ${postLockTicketResponse.status}`);
                }
                let putLockTicketResponse = yield handleRequest(this.gameId, this.lockTicketUrl, 'PUT', {
                    EventId: this.gameId,
                    Seats: postLockTicketResponse.body.LockedSeats.map(seat => {
                        return {
                            Id: seat.Id,
                            PriceClassId: 1
                            // PriceClassId: seat.Prices[0]?.PriceType ?? 1
                        };
                    })
                });
                if (!putLockTicketResponse.isSuccess) {
                    throw new Error(`Lock request (PUT) failed with status ${putLockTicketResponse.status}`);
                }
                return true;
            }
            return false;
        });
    }
}
// #endregion Interfaces
// #region TicketMasterRequests Class
// class TicketmasterRequests {
//     private gameId: number = 0;
//     private searchType: SearchTypes;
//     private quantity: number = 1;
//     private seatsTogehther: boolean = false;
//     constructor(gameId: number, searchType: SearchTypes, quantity: number) {
//         this.gameId = gameId;
//         this.searchType = searchType;
//         this.quantity = quantity;
//         this.seatsTogehther = (quantity > 1) ? true : false;
//     }
//     async handleRequest<T, B>(url: string, method: string, body?: B, responseJson: boolean = true): Promise<RequestResult<T>> {
//         let options: RequestInit = {
//             method: method,
//             headers: this.getHeaders()
//         };
//         if (body) options.body = JSON.stringify(body);
//         let response = await fetch(url, options);
//         let resultResponse : RequestResult<T> = {
//             status: response.status,
//             isSuccess: this.checkStatus(response.status),
//             body: (responseJson) ? await response.json() as T : null as T
//         }
//         return resultResponse;
//     }
//     checkStatus(statusCode: number) : boolean {
//         switch (statusCode) {
//             case 200:
//                 return true;
//             case 401:
//                 return false;
//             case 403:
//                 return false;
//             default:
//                 return false;
//         }
//     }
//     async getCheckForRegularTicketsRequest(): Promise<AvaliableSeatResponse[]> {
//         let url = `https://www.eticketing.co.uk/arsenal/EDP/Seats/AvailableRegular?AreSeatsTogether=${ this.seatsTogehther }&EventId=${this.gameId}&MaximumPrice=10000000&MinimumPrice=0&Quantity=${this.quantity}`;
//         let response = await this.handleRequest<AvaliableSeatResponse[], undefined>(url, 'GET');
//         return response.body;
//     }
//     async getCheckForResaleTicketsRequest():Promise<AvaliableSeatResponse[]> {
//         let url = `https://www.eticketing.co.uk/arsenal/EDP/Seats/AvailableResale?AreSeatsTogether=${this.seatsTogehther}&EventId=${this.gameId}&MarketType=1&MaximumPrice=10000000&MinimumPrice=0&Quantity=${this.quantity}`;
//         let response = await this.handleRequest<AvaliableSeatResponse[], undefined>(url, 'GET');
//         return response.body;
//     }
//     async handleTicketFound(avaliableSeatResponse: AvaliableSeatResponse) : Promise<boolean> {
//         let postLockTicket = await this.postLockTicketsRequest({
//             EventId: this.gameId,
//             Quantity: this.quantity,
//             AreSeatsTogether: this.seatsTogehther,
//             AreaId: avaliableSeatResponse.AreaId,
//             PriceBandId: avaliableSeatResponse.PriceBands[0].PriceBandCode,
//             SeatAttributeIds: [],
//             MinimumPrice: 0,
//             MaximumPrice: 10000000
//         });
//         if (!postLockTicket.isSuccess) return false;
//         let putLockTicket = await this.putLockTicketsRequest({
//             EventId: this.gameId,
//             Seats: postLockTicket.body.LockedSeats.map(seat => {
//                 return {
//                     Id: seat.Id,
//                     PriceClassId: 1
//                 }
//             })
//         });
//         if (!putLockTicket.isSuccess) return false;
//         let basketSeats = await this.getBasketSeatsRequest();
//         if (!basketSeats.isSuccess) return false;
//         return true
//     }
//     async deletePurgeLocksRequest(): Promise<void> {
//         let url = `https://www.eticketing.co.uk/arsenal/EDP/BestAvailable/PurgeLocks`;
//         let response = await this.handleRequest<null, EventIdPayload>(url, 'DELETE', {eventId: this.gameId}, false);
//     }
//     getLockSeatUrl(): string {
//         let resaleUrl = `https://www.eticketing.co.uk/arsenal/EDP/BestAvailable/ResaleSeats`;
//         let regularUrl = `https://www.eticketing.co.uk/arsenal/EDP/BestAvailable/RegularSeats`;
//         switch(this.searchType) {
//             case SearchTypesEnum.Regular:
//                 return regularUrl
//                 break;
//             case SearchTypesEnum.Resale:
//                 return resaleUrl;
//                 break;
//             default:
//                 return resaleUrl;
//                 break;
//         }
//     }
//     async postLockTicketsRequest(lockSeatsPayload: PostLockSeatsPayload): Promise<RequestResult<PostLockSeatsResponse>> {
//         //let url = (this.searchType === this.searchType.)`https://www.eticketing.co.uk/arsenal/EDP/BestAvailable/RegularSeats`;
//         let url = this.getLockSeatUrl();
//         let response = await this.handleRequest<PostLockSeatsResponse, PostLockSeatsPayload>(url, 'POST', lockSeatsPayload);
//         return response;
//     }
//     async putLockTicketsRequest(lockSeatsPayload: PutLockSeatsPayload): Promise<RequestResult<PostLockSeatsResponse>> {
//         let url = this.getLockSeatUrl();
//         let response = await this.handleRequest<PostLockSeatsResponse, PutLockSeatsPayload>(url, 'PUT', lockSeatsPayload);
//         return response;
//     }
//     async getBasketSeatsRequest(): Promise<RequestResult<BasketSeatsResponse[]>> {
//         let url = `https://www.eticketing.co.uk/arsenal/EDP/Ism/BasketSeats`;
//         let response = await this.handleRequest<BasketSeatsResponse[], EventIdPayload>(url, 'GET', {eventId: this.gameId});
//         return response;
//     }
// }
// #endregion TicketMasterRequests Class
// #region Main
console.log('Okaaaay, lets go');
// Aggressive helper to play audio with fallback
const playAudio = (soundUrl, logName) => {
    const attemptPlay = (isRetry = false) => {
        const audio = new Audio(soundUrl);
        console.log(`🎵 [${isRetry ? 'Retry' : 'Initial'}] Playing ${logName}...`);
        audio.play().then(() => {
            console.log(`✅ success: ${logName} played.`);
        }).catch(e => {
            if (!isRetry) {
                console.warn(`⚠️ Autoplay blocked for ${logName}. Bitte klicke einmal irgendwo auf die Arsenal-Webseite (nicht das Popup!), um den Ton zu aktivieren.`);
                const onInteraction = () => {
                    console.log('🖱️ Interaktion erkannt! Versuche Ton erneut abzuspielen...');
                    attemptPlay(true);
                    window.removeEventListener('click', onInteraction, true);
                    window.removeEventListener('keydown', onInteraction, true);
                };
                // Use capture: true to ensure we see the event even if the page tries to stop it
                window.addEventListener('click', onInteraction, true);
                window.addEventListener('keydown', onInteraction, true);
            }
            else {
                console.error(`❌ Playback failed even after interaction for ${logName}:`, e);
            }
        });
    };
    attemptPlay();
};
const run = (settings) => __awaiter(void 0, void 0, void 0, function* () {
    console.log('Starting with settings:', settings);
    // Play start sound
    if (settings.startSound && settings.startSound !== 'none') {
        const soundUrl = chrome.runtime.getURL(`sounds/${settings.startSound}`);
        playAudio(soundUrl, `Start Sound (${settings.startSound})`);
    }
    // Search index is not in settings yet, default to 0
    const SEARCH_INDEX = 0;
    let ticketHandler = new TicketmasterRequestsFactory().create(settings.eventId, settings.searchType, settings.quantity, SEARCH_INDEX);
    // Re-instantiate with full params
    ticketHandler = new SearchListTickets(settings.eventId, settings.searchType, settings.quantity, SEARCH_INDEX, settings.minPrice, settings.maxPrice);
    yield deletePurgLocks(settings.eventId);
    let ticketFound = false;
    while (ticketFound === false) {
        try {
            let result = yield ticketHandler.handle();
            if (result) {
                yield basketSeats(settings.eventId);
                console.log('Ticket in basket');
                // Play success sound
                if (settings.sound && settings.sound !== 'none') {
                    const soundUrl = chrome.runtime.getURL(`sounds/${settings.sound}`);
                    playAudio(soundUrl, `Success Sound (${settings.sound})`);
                }
                ticketFound = true;
                break;
            }
        }
        catch (error) {
            // results of break statement
            console.log('try again');
            console.log(error);
            // Play failure sound on specific errors (e.g., 404 or other request failures)
            // Assuming error object or flow implies failure
            if (settings.errorSound && settings.errorSound !== 'none') {
                const soundUrl = chrome.runtime.getURL(`sounds/${settings.errorSound}`);
                playAudio(soundUrl, `Failure Sound (${settings.errorSound})`);
            }
        }
        let randomInterval = settings.interval + (Math.random() * settings.interval * 0.2) - (Math.random() * settings.interval * 0.2);
        console.log('No ticket found - waiting for ' + randomInterval.toFixed(2) + ' ms');
        yield new Promise(resolve => setTimeout(resolve, randomInterval));
    }
});
// #endregion Main
// #endregion Main
// Start logic only if we are on an event page
if (typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local) {
    // Basic check if we are on an event detail page before running the sniper
    if (window.location.href.includes('/EDP/Event/Index/')) {
        console.log('Event page detected, starting sniper...');
        chrome.storage.local.get(['extensionSettings'], (result) => {
            // Merge defaults with stored settings to ensure new properties (like startSound) exist
            // even if the user has old settings saved.
            const settings = Object.assign(Object.assign({}, DEFAULT_CONTENT_SETTINGS), result.extensionSettings);
            run(settings);
        });
    }
    else {
        console.log('Not an event page, sniper idle. Waiting for messages...');
    }
}
else {
    // Fallback
    console.log('Chrome storage not available or fallback mode');
}
// #endregion Message Listener
