// Questo file fa parte di MyTown.
// MyTown è software libero: puoi ridistribuirlo e/o modificarlo secondo
// i termini della GNU Affero General Public License come pubblicata dalla
// Free Software Foundation, versione 3.
// Distribuito senza ALCUNA GARANZIA; vedi la GNU AGPL v3 per i dettagli.
// Copyright (C) Kondor Consulting & Services S.r.l.
// SPDX-License-Identifier: AGPL-3.0-or-later

import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Capacitor } from '@capacitor/core';
import { ToastController } from '@ionic/angular';
import { TranslateService } from '@ngx-translate/core';
import { throwError } from 'rxjs/internal/observable/throwError';

import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
import { BRAND } from '../../brand/active-brand';

@Injectable()
export class ConfigService {
	public imageBaseURL = '';
	public onlineshopImageUrl = '';
	public bakekaImageUrl = '';
	public placesImageUrl = '';
	public placesAudioUrl = '';
	language = 'it';
	public serviceUrl = '';
	public serviceUrl_Login = '';
	public serviceUrl_PortalManager = '';
	public serviceUrl_Companies = '';
	public serviceUrl_Documentary = '';
	public serviceUrl_HelpDesk_RFI = '';
	public onlineshopurl = '';
	public bakekaUrl = '';
	public bookingUrl = '';

	public wfUrl = '';
	public paymentUrl = '';
	public paypal_clientId = '';
	public nexi_script = '';
	public serviceUrl_BizAppointments = '';
	public platform = Capacitor.getPlatform();
	public url_privacy = '';
	public url_condizioni_commerciali = '';
	public apiGoogleMapsKey = '';
	public ddtConfig: { fg_id: number; ft_id: number } = { fg_id: 1, ft_id: 1 };

	public natificationBadgeObserver: any;
	public natificationBadge: any;

	public change_connection_locked: boolean = false;
	public is_scanner_active: boolean = false;
	public scannert_injected_function: string = '';
	public scanner_started_from: string = '';
	public viewCamera: boolean = false;

	//Blocco le chiamate di refresh token per ogni chiamate se una già presente
	private wait_until_refreshtoken_done = false;
	private autoSignOutTimeout: any;

	private toasts: HTMLIonToastElement[] = [];

	/* public log_group: Log_Group[] = []; */

	constructor(private router: Router, private toast: ToastController, private http: HttpClient, private translate: TranslateService) {
		this.natificationBadgeObserver = null;
		this.natificationBadge = new Observable((observer: any) => {
			this.natificationBadgeObserver = observer;
		});
	}

	load() {
		// Config caricata a compile-time da src/environments/environment.ts
		// (sostituito dai fileReplacements di angular.json per i profili edil,
		// mytown, edil-test, mytown-test, production). Niente più fetch runtime su config.json.
		const env = environment;

		this.imageBaseURL = env.imageBaseURL;
		this.url_privacy = env.url_privacy;
		this.url_condizioni_commerciali = env.url_condizioni_commerciali;

		this.serviceUrl = env.base_url;
		this.serviceUrl_Login = env.base_url + env.service_url_login;
		this.serviceUrl_PortalManager = env.base_url + env.service_url_portal_manager;
		this.serviceUrl_Companies = env.base_url + env.service_url_companies;
		this.serviceUrl_Documentary = env.base_url + env.service_url_documentary;
		this.serviceUrl_HelpDesk_RFI = env.base_url + env.service_url_helpdesk_rfi;
		this.bookingUrl = env.base_url + env.service_url_booking;
		this.wfUrl = env.base_url + env.service_url_workflow;
		this.onlineshopurl = env.base_url + env.service_url_onlineshop;
		// URL HTTP da cui vengono serviti i file caricati: imageBaseURL + sottocartella (da env).
		this.onlineshopImageUrl = this.imageBaseURL + env.onlineshop_image_path;
		// Foto/audio turismo (bacheca + luoghi): servite staticamente da LSWS dalla cartella
		// PERSISTENTE /var/www/bacheca/turismo (NON /temp), mappata sul dominio come /bacheca/turismo.
		// Base derivata dall'host di imageBaseURL (che termina con /assets).
		const turismoBase = this.imageBaseURL.replace(/\/assets\/?$/, '') + '/bacheca/turismo';
		this.bakekaImageUrl = turismoBase + env.bakeka_image_path;
		this.placesImageUrl = turismoBase + env.places_image_path;
		this.placesAudioUrl = turismoBase + env.places_audio_path;
		this.bakekaUrl = env.base_url + env.service_url_bakeka;
		this.paymentUrl = env.base_url + env.service_url_payment;
		this.paypal_clientId = env.paypal_clientId || '';
		this.nexi_script = env.nexi_script || '';
		this.serviceUrl_BizAppointments = env.base_url + env.service_url_biz_appointments;

		this.apiGoogleMapsKey = env.apiGoogleMapsKey;

		if (env.ddt_config) {
			this.ddtConfig = env.ddt_config;
		}

		return Promise.resolve(true);
	}

	getUser(): any {
		let currentUser: any;
		let currentUserString = localStorage.getItem('currentUser');
		if (currentUserString) {
			currentUser = JSON.parse(currentUserString);
		}
		return currentUser;
	}

	isLogged(): boolean {
		let usr = this.getUser();
		if (usr && usr.usr_id > 0) {
			return true;
		}
		return false;
	}

	/** Brand di build (single source of truth: src/brand/active-brand.ts). */
	isMyTown(): boolean {
		return BRAND.id === 'mytown';
	}

	/** Pagina di atterraggio dopo il login. */
	getLandingRoute(): string {
		return this.isMyTown() ? '/bakeka' : '/servizi';
	}

	isUserAuthorizedAs(role: string): boolean {
		let usr = this.getUser();
		if (usr) {
			let token = usr.token;
			let decryped_token = atob(token.substring(token.indexOf('.') + 1, token.lastIndexOf('.')));
			let roles = JSON.parse(decryped_token).role.split(',');
			if (roles.includes(role)) {
				return true;
			}
			return false;
		}
		return false;
	}

	handleError(error: HttpErrorResponse) {
		let msgError = 'Something bad happened; please try again later.';
		if (error.status === 0) {
			// A client-side or network error occurred. Handle it accordingly.
			console.error('An error occurred:', error.error);
			msgError = error.message;
		} else {
			// The backend returned an unsuccessful response code.
			// The response body may contain clues as to what went wrong.
			console.error(`Backend returned code ${error.status}, body was: `, error.error);
			msgError = error.error.message;
		}
		// Return an observable with a user-facing error message.
		//return throwError(() => new Error('Something bad happened; please try again later.'));
		return throwError(() => msgError);
	}

	private getToastHeight(toast: HTMLIonToastElement): Promise<number> {
		return new Promise((resolve) => {
			if (toast && toast.shadowRoot) {
				const toastContent = toast.shadowRoot.querySelector('.toast-container');
				if (toastContent) {
					resolve(toastContent.clientHeight);
				} else {
					resolve(0);
				}
			} else {
				resolve(0);
			}
		});
	}

	private removeToast(toast: HTMLIonToastElement) {
		const index = this.toasts.indexOf(toast);
		if (index > -1) {
			this.toasts.splice(index, 1);
			this.updateToastPositions();
		}
	}

	private async updateToastPositions() {
		let offset = 0;
		for (const toast of this.toasts) {
			const height = await this.getToastHeight(toast);
			toast.style.setProperty('top', `-${offset}px`);
			offset += height + 10; // Add 10px gap between toasts
		}
	}

	async presentToast(msg: string) {
		if (msg.toLocaleLowerCase().startsWith('successo:')) {
			this.presentToastSuccess(msg.split(':').slice(1).join(':'));
		} else if (msg.toLocaleLowerCase().startsWith('errore:')) {
			this.presentToastError(msg.split(':').slice(1).join(':'));
		} else if (msg.toLocaleLowerCase().startsWith('attenzione:')) {
			this.presentToastWarning(msg.split(':').slice(1).join(':'));
		}
	}

	async presentToastError(msg: string) {
		if (msg) {
			const toast = await this.toast.create({
				message: msg,
				duration: 4000,
				color: 'danger',
				cssClass: 'custom-toast',
			});
			this.toasts.push(toast);
			this.updateToastPositions();
			toast.present();

			// Wait for the toast to be added to the DOM
			await new Promise((resolve) => setTimeout(resolve, 100));

			this.updateToastPositions();

			toast.onDidDismiss().then(() => {
				this.removeToast(toast);
			});
		}
	}

	async presentToastSuccess(msg: string) {
		if (msg) {
			const toast = await this.toast.create({
				message: msg,
				duration: 3000,
				color: 'success',
				cssClass: 'custom-toast',
			});
			this.toasts.push(toast);
			this.updateToastPositions();
			toast.present();

			// Wait for the toast to be added to the DOM
			await new Promise((resolve) => setTimeout(resolve, 100));

			this.updateToastPositions();

			toast.onDidDismiss().then(() => {
				this.removeToast(toast);
			});
		}
	}

	async presentToastWarning(msg: string) {
		if (msg) {
			const toast = await this.toast.create({
				message: msg,
				duration: 4000,
				color: 'warning',
				cssClass: 'custom-toast',
			});
			this.toasts.push(toast);
			this.updateToastPositions();
			toast.present();

			// Wait for the toast to be added to the DOM
			await new Promise((resolve) => setTimeout(resolve, 100));

			this.updateToastPositions();

			toast.onDidDismiss().then(() => {
				this.removeToast(toast);
			});
		}
	}

	public isStringNotNull(string: string): Boolean {
		if (string) {
			let trimmed_string = string.trim();
			if (trimmed_string) {
				return true;
			}
		}
		return false;
	}

	public getTranslate(word: string) {
		let translate = word;
		this.translate.get(word).subscribe((r: any) => {
			translate = r;
		});
		return translate;
	}

	getLocalStorageObjectJson(key: string) {
		let _val = JSON.parse(localStorage.getItem(key) || '{}');
		if (Object.keys(_val).length === 0) {
			return null;
		}
		return _val;
	}

	saveSessionVariable(key: string, value: string) {
		sessionStorage.setItem(key, value);
	}

	getSessionVariable(key: string): string {
		return sessionStorage.getItem(key) || '';
	}

	removeSessionVariable(key: string) {
		sessionStorage.removeItem(key);
	}

	getUserID(): number {
		let res = 0;
		let localData = localStorage.getItem('currentUser');
		if (localData) {
			let currentUser = JSON.parse(localData);
			res = currentUser.usr_id;
		}
		return res;
	}

	getUserName(): string {
		let res = '';
		let localData = localStorage.getItem('currentUser');
		if (localData) {
			let currentUser = JSON.parse(localData);
			res = currentUser.usr_username;
		}
		return res;
	}

	public getLanguage() {
		if (this.getUser() && this.getUser().lang) {
			return this.getUser().lang;
		}
		return this.language;
	}

	public getLocalStorageLanguage() {
		let locallang = localStorage.getItem('language');
		if (locallang) {
			return locallang;
		}
		return 'KO';
	}

	setLanguage(language: string) {
		localStorage.setItem('language', language.toLocaleLowerCase());
	}

	isAuthenticated(): boolean {
		let usr = this.getUser();
		if (usr && usr.token) {
			try {
				let payload = JSON.parse(atob(usr.token.split('.')[1]));
				let currentTime = Math.floor(Date.now() / 1000);
				return payload.exp > currentTime;
			} catch (e) {
				return false;
			}
		}
		return false;
	}

	logout() {
		localStorage.clear();
	}

	private colors = [
		'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
		'linear-gradient(135deg, #ff6b6b 0%, #ff8e53 100%)',
		'linear-gradient(135deg, #4ecdc4 0%, #45b7d1 100%)',
		'linear-gradient(135deg, #3498db 0%, #2ecc71 100%)',
		'linear-gradient(135deg, #e74c3c 0%, #f1c40f 100%)',
		'linear-gradient(135deg, #1abc9c 0%, #e67e22 100%)',
		'linear-gradient(135deg, #c0392b 0%, #2980b9 100%)',
		'linear-gradient(135deg, #27ae60 0%, #f39c12 100%)',
		'linear-gradient(135deg, #16a085 0%, #d35400 100%)',
		'linear-gradient(135deg, #cc2b5e 0%, #753a88 100%)',
		'linear-gradient(135deg, #42275a 0%, #734b6d 100%)',
		'linear-gradient(135deg, #de6262 0%, #ffb88c 100%)',
		'linear-gradient(135deg, #06beb6 0%, #48b1bf 100%)',
		'linear-gradient(135deg, #eb3349 0%, #f45c43 100%)',
		'linear-gradient(135deg, #dd5e89 0%, #f7bb97 100%)',
		'linear-gradient(135deg, #56ab2f 0%, #a8e063 100%)',
		'linear-gradient(135deg, #614385 0%, #516395 100%)',
		'linear-gradient(135deg, #02aab0 0%, #00cdac 100%)',
		'linear-gradient(135deg, #d66d75 0%, #e29587 100%)',
		'linear-gradient(135deg, #000428 0%, #004e92 100%)',
		'linear-gradient(135deg, #7b4397 0%, #dc2430 100%)',
		'linear-gradient(135deg, #43cea2 0%, #185a9d 100%)',
		'linear-gradient(135deg, #ba5370 0%, #f4e2d8 100%)',
		'linear-gradient(135deg, #ff512f 0%, #dd2476 100%)',
		'linear-gradient(135deg, #4568dc 0%, #b06ab3 100%)',
		'linear-gradient(135deg, #ec6f66 0%, #f3a183 100%)',
		'linear-gradient(135deg, #3a1c71 0%, #ffaf7b 100%)',
		'linear-gradient(135deg, #4ca1af 0%, #c4e0e5 100%)',
		'linear-gradient(135deg, #ff5f6d 0%, #ffc371 100%)',
		'linear-gradient(135deg, #36d1dc 0%, #5b86e5 100%)',
		'linear-gradient(135deg, #c33764 0%, #1d2671 100%)',
		'linear-gradient(135deg, #141e30 0%, #243b55 100%)',
		'linear-gradient(135deg, #ff7e5f 0%, #feb47b 100%)',
		'linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)',
		'linear-gradient(135deg, #ff8177 0%, #b12a5b 100%)',
		'linear-gradient(135deg, #f6d365 0%, #fda085 100%)',
		'linear-gradient(135deg, #a6c0fe 0%, #f68084 100%)',
		'linear-gradient(135deg, #fccb90 0%, #d57eeb 100%)',
		'linear-gradient(135deg, #e0c3fc 0%, #8ec5fc 100%)',
	];

	getColorFromEmail(email: string): string {
		let hash = 0;
		for (let i = 0; i < email.length; i++) {
			hash = email.charCodeAt(i) + ((hash << 5) - hash);
		}
		return this.colors[Math.abs(hash) % this.colors.length];
	}

	getColorFromDisplayName(_displayname: string = ''): string {
		// Null-safe: dopo il logout (localStorage.clear) getUser() è undefined ma la pagina
		// corrente è ancora renderizzata durante la transizione verso /login.
		let displayname = _displayname ? _displayname : this.getUser()?.usr_displayname || '';
		let hash = 0;
		for (let i = 0; i < displayname.length; i++) {
			hash = displayname.charCodeAt(i) + ((hash << 5) - hash);
		}
		return this.colors[Math.abs(hash) % this.colors.length];
	}

	getUsernameInitials(_name: string = '', _surname: string = ''): string {
		let name = _name ? _name : this.getUser()?.usr_firstname || '';
		let surname = _surname ? _surname : this.getUser()?.usr_lastname || '';
		return `${name.charAt(0)}${surname.charAt(0)}`.toUpperCase();
	}

	// Immagine profilo dell'utente corrente (data-URL base64), '' se non impostata.
	// Solo i data-URL sono validi: il DB legacy conteneva path tipo '/avatar/default.svg'
	// (file inesistente) che darebbero un'immagine rotta.
	getUserAvatar(): string {
		const avatar = this.getUser()?.avatar || '';
		return avatar.startsWith('data:image') ? avatar : '';
	}

	// Aggiorna l'avatar nel currentUser in localStorage così header e pagine lo mostrano subito.
	setUserAvatar(avatar: string): void {
		const currentUser = this.getUser();
		if (!currentUser) return;
		currentUser.avatar = avatar || '';
		localStorage.setItem('currentUser', JSON.stringify(currentUser));
	}

	getFileIcon(fileName: string, mimeType?: string): string {
		// Get file extension
		const extension = fileName?.split('.').pop()?.toLowerCase() || '';

		// Check MIME type first if available
		if (mimeType) {
			// PDF files
			if (mimeType.includes('pdf')) {
				return 'pi pi-file-pdf text-danger file-pdf';
			}

			// Excel files
			if (mimeType.includes('spreadsheet') || mimeType.includes('excel')) {
				return 'pi pi-file-excel text-success file-excel';
			}

			// Word files
			if (mimeType.includes('word') || mimeType.includes('document')) {
				return 'pi pi-file-word text-primary file-word';
			}

			// Images
			if (mimeType.startsWith('image/')) {
				return 'pi pi-image text-purple file-image';
			}

			// Videos
			if (mimeType.startsWith('video/')) {
				return 'pi pi-video text-pink file-video';
			}

			// Audio
			if (mimeType.startsWith('audio/')) {
				return 'pi pi-volume-up text-orange file-audio';
			}
		}

		// Fallback to extension-based detection
		switch (extension) {
			// PDF
			case 'pdf':
				return 'pi pi-file-pdf text-danger file-pdf';

			// Excel files
			case 'xls':
			case 'xlsx':
			case 'xlsm':
			case 'xlsb':
			case 'csv':
				return 'pi pi-file-excel text-success file-excel';

			// Word files
			case 'doc':
			case 'docx':
			case 'docm':
			case 'dot':
			case 'dotx':
				return 'pi pi-file-word text-primary file-word';

			// Images
			case 'jpg':
			case 'jpeg':
			case 'png':
			case 'gif':
			case 'bmp':
			case 'svg':
			case 'webp':
			case 'ico':
			case 'tiff':
			case 'tif':
				return 'pi pi-image text-purple file-image';

			// Videos
			case 'mp4':
			case 'avi':
			case 'mov':
			case 'wmv':
			case 'flv':
			case 'mkv':
			case 'webm':
			case 'm4v':
				return 'pi pi-video text-pink file-video';

			// Audio
			case 'mp3':
			case 'wav':
			case 'flac':
			case 'aac':
			case 'ogg':
			case 'wma':
			case 'm4a':
				return 'pi pi-volume-up text-orange file-audio';

			// Archives
			case 'zip':
			case 'rar':
			case '7z':
			case 'tar':
			case 'gz':
			case 'bz2':
			case 'xz':
				return 'pi pi-box text-lime file-archive';

			// Code files
			case 'js':
			case 'ts':
			case 'jsx':
			case 'tsx':
			case 'html':
			case 'css':
			case 'scss':
			case 'sass':
			case 'json':
			case 'xml':
			case 'py':
			case 'java':
			case 'cpp':
			case 'c':
			case 'cs':
			case 'php':
			case 'rb':
			case 'go':
			case 'rs':
			case 'swift':
			case 'kt':
				return 'pi pi-code text-cyan file-code';

			// Text files
			case 'txt':
			case 'md':
			case 'log':
			case 'rtf':
				return 'pi pi-file-o text-gray file-text';

			// Default
			default:
				return 'pi pi-file text-primary file-default';
		}
	}

	convertToISOSameDate(dateString: string): string {
		// Parse the date string
		const date = new Date(dateString);

		// Extract the local date components (these represent the visual date we want to preserve)
		const year = date.getFullYear();
		const month = date.getMonth();
		const day = date.getDate();
		const hours = date.getHours();
		const minutes = date.getMinutes();
		const seconds = date.getSeconds();
		const milliseconds = date.getMilliseconds();

		// Create a new Date object in UTC with the same calendar date components
		const utcDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, milliseconds));

		// Return as ISO string
		return utcDate.toISOString();
	}

	formatDateToString(event: Date) {
		if (event) {
			const year = event.getFullYear();
			const month = ('0' + (event.getMonth() + 1)).slice(-2); // Add leading zero
			const day = ('0' + event.getDate()).slice(-2); // Add leading zero
			return `${year}-${month}-${day}`;
		}
		return '';
	}

	// format time to string 00:00
	formatTimeToString(event: any) {
		const arr = event;
		if (arr && arr.length >= 2) {
			const hours = ('0' + event[0]).slice(-2);
			const minutes = ('0' + event[1]).slice(-2);
			return `${hours}:${minutes}`;
		}
		return '';
	}

	// format obj to date
	formatDate(event: any) {
		const arr = event;
		if (arr && arr.length >= 3) {
			event = new Date(arr[0], arr[1] - 1, arr[2], arr[3] || 0, arr[4] || 0, arr[5] || 0);
		} else {
			event = null;
		}
		return event;
	}

	// normalize
	_normDate(d: string | number[] | number | any): string {
		if (!d) return '';
		if (Array.isArray(d)) {
			const [y, m, day] = d as number[];
			return `${y}-${String(m).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
		}
		if (typeof d === 'number') {
			const dt = new Date(d);
			return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, '0')}-${String(dt.getDate()).padStart(2, '0')}`;
		}
		return typeof d === 'string' ? d.substring(0, 10) : '';
	}
}
