import ActivityRunner from '../activities/ActivityRunner';
import ShowBalanceErrorPopup from '../activities/ShowBalanceErrorPopup';
import ShowErrorPopup from '../activities/ShowErrorPopup';
import ShowLoadingError from '../activities/ShowLoadingError';
import Locator from '../services/Locator';
import { getLatestSpinKey, getLatestSpinTimeKey } from '../utils/utils';
import BackendError, { type BackendErrorDetail } from './BackendError';
import LobbyLinkNotFoundError from './LobbyLinkNotFoundError';

const LOADER_FAILURE_TOKEN = '[Loader.load]';

/** Maps domain errors to UI activities that guide recovery. */
export class ErrorProcessor
{
    constructor(private readonly activityRunner: ActivityRunner)
    {}

    /**
     * Clears cached spin data and dispatches activities for the error.
     * @param error
     */
    process(error: unknown): void
    {
        Locator.storage.delete(getLatestSpinKey());
        Locator.storage.delete(getLatestSpinTimeKey());

        console.log('this.activityRunner.isError', this.activityRunner.isError);
        console.log(this.activityRunner.isRunning);

        const resolvedError = error instanceof Error ? error : new Error(String(error));

        if (resolvedError instanceof LobbyLinkNotFoundError)
        {
            this.showPopup(resolvedError.message);

            return;
        }

        if (resolvedError.message?.includes(LOADER_FAILURE_TOKEN))
        {
            console.warn(`Error: ${resolvedError.message}`);
            this.activityRunner.addActivity(new ShowLoadingError('Loading error'));

            return;
        }

        if (!(resolvedError instanceof BackendError))
        {
            console.error('Unknown error is got', resolvedError);
            this.activityRunner.addActivity(new ShowErrorPopup('Unknown error is got'));

            return;
        }

        resolvedError.details.forEach((detail) =>
        {
            this.handleBackendErrorDetail(detail);
        });
    }

    private handleBackendErrorDetail(detail: BackendErrorDetail): void
    {
        switch (detail.code)
        {
            case 101:
            case 102:
            case 103:
            case 104:
            case 105:
            case 201:
            case 202:
            case 203:
            case 204:
            case 205:
            case 206:
            case 302:
            case 303:
            case 401:
            case 402:
            case '301nodep':
            case '206i':
            case 'some_error':
            case 'many_tabs_error':
                this.showLocalizedPopup(detail.code);
                break;
            case 301:
                this.handleDepositRequired(detail.code);
                break;
            default:
                this.showDefaultPopup(detail.code);
                break;
        }
    }

    private showLocalizedPopup(code: BackendErrorDetail['code']): void
    {
        const rawMessage = Locator.locales.get(String(code));
        const message = typeof rawMessage === 'string' ? rawMessage : String(code);

        this.showPopup(message);
    }

    private handleDepositRequired(code: BackendErrorDetail['code']): void
    {
        const rawMessage = Locator.locales.get(String(code));
        const message = typeof rawMessage === 'string' ? rawMessage : String(code);

        console.warn(`Error: ${message}`);

        if (__OPTIONS__.deposit_url)
        {
            this.activityRunner.addActivity(new ShowBalanceErrorPopup(message));

            return;
        }

        const fallbackRaw = Locator.locales.get(`${String(code)}nodep`);
        const fallback = typeof fallbackRaw === 'string' ? fallbackRaw : message;

        console.warn(`Error: ${fallback}`);
        this.activityRunner.addActivity(new ShowErrorPopup(fallback));
    }

    private showDefaultPopup(code: BackendErrorDetail['code']): void
    {
        const template = Locator.locales.get('default');
        const [prefix, suffix] = typeof template === 'string' ? template.split('{code}') : ['Error code', ''];
        const message = `${prefix?.trim() ?? ''} ${code} ${suffix?.trim() ?? ''}`.trim();

        this.showPopup(message);
    }

    private showPopup(message: string): void
    {
        console.warn(`Error: ${message}`);
        this.activityRunner.addActivity(new ShowErrorPopup(message));
    }
}
