// 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 { Component, OnInit, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { LoadingController, IonInfiniteScroll, NavController } from '@ionic/angular';

import { ConfigService } from 'src/app/providers/config.service';
import { BizAppointmentsService } from 'src/app/providers/biz-appointments.service';
import { BizServiceTypesService } from 'src/app/providers/biz-service-types.service';
import { BizAvailabilityService } from 'src/app/providers/biz-availability.service';
import { FunctionService } from 'src/app/providers/function.service';
import { Appointment, AppointmentFilter, AppointmentStatusOptions, AppointmentStatusColors, AppointmentStatus } from 'src/models/biz-appointments/appointment.model';
import { ServiceType } from 'src/models/biz-appointments/service-type.model';
import { OperatorSimple } from 'src/models/biz-appointments/availability.model';

@Component({
	standalone: false,
	selector: 'app-biz-appointments-list',
	templateUrl: './biz-appointments-list.page.html',
	styleUrls: ['./biz-appointments-list.page.scss'],
})
export class BizAppointmentsListPage implements OnInit {
	@ViewChild(IonInfiniteScroll) infiniteScroll!: IonInfiniteScroll;

	list: Appointment[] = [];
	loading: boolean = false;
	cerca: string = '';
	totalRows: number = 0;
	currentPage: number = 1;
	pageelement: number = 20;

	// Filtri
	filters: AppointmentFilter = {};
	statusOptions = AppointmentStatusOptions;
	serviceTypes: ServiceType[] = [];
	operators: OperatorSimple[] = [];
	filterPopoverOpen: boolean = false;

	// Route params
	prt_id: number = 0;
	cmp_id: number = 0;

	// Role
	isGestore: boolean = false;

	// Costanti
	statusColors = AppointmentStatusColors;

	constructor(
		private router: Router,
		private route: ActivatedRoute,
		private navCtrl: NavController,
		private loadingController: LoadingController,
		private configService: ConfigService,
		private appointmentsService: BizAppointmentsService,
		private serviceTypesService: BizServiceTypesService,
		private availabilityService: BizAvailabilityService,
		private funService: FunctionService,
	) {}

	ngOnInit(): void {
		this.prt_id = Number(this.route.snapshot.paramMap.get('prt_id') || this.route.parent?.snapshot.paramMap.get('prt_id') || 0);
		this.cmp_id = Number(this.route.snapshot.paramMap.get('cmp_id') || this.route.parent?.snapshot.paramMap.get('cmp_id') || 0);
		// Operatore/gestore via module function 'gestione' (non piu' ruolo ADMIN); poi inizializza
		this.funService.funzionibyuser('Appuntamenti').subscribe({
			next: (res: any[]) => {
				this.isGestore = (res || []).map((f) => f.mdfu_function).includes('gestione');
				this.initList();
			},
			error: () => {
				this.isGestore = false;
				this.initList();
			},
		});
	}

	private initList(): void {
		if (!this.isGestore) {
			this.filters.client_usr_id = this.configService.getUserID();
		}
		this.loadServiceTypes();
		if (this.isGestore) {
			this.loadOperators();
		}
		this.getList();
	}

	async getList(event?: any) {
		if (!event) {
			this.loading = true;
		}
		const offset = (this.currentPage - 1) * this.pageelement;

		this.appointmentsService.getAppointments(this.cmp_id, this.cerca, '', this.pageelement, offset, this.filters).subscribe({
			next: (data: any) => {
				// Accoda SOLO per l'infinite-scroll (pagina > 1); refresh/ricerca/primo load sostituiscono
				// (prima: `if (event)` accodava anche sul pull-to-refresh → appuntamenti duplicati)
				if (this.currentPage > 1) {
					this.list = [...this.list, ...(data.list || [])];
				} else {
					this.list = data.list || [];
				}
				this.totalRows = data.totalRows || 0;
			},
			error: (err: any) => {
				this.configService.presentToastError('Errore caricamento appuntamenti');
			},
			complete: () => {
				this.loading = false;
				if (event) {
					event.target.complete();
					// Disabilita SOLO l'infinite-scroll (pagina > 1) quando è tutto caricato.
					// MAI sul pull-to-refresh (pagina 1), altrimenti dopo il primo refresh il controllo resta disabilitato.
					if (this.currentPage > 1 && this.list.length >= this.totalRows) {
						event.target.disabled = true;
					}
				}
			},
		});
	}

	loadServiceTypes(): void {
		this.serviceTypesService.getServiceTypes(this.cmp_id).subscribe({
			next: (data: any) => {
				this.serviceTypes = data || [];
			},
		});
	}

	loadOperators(): void {
		this.availabilityService.getOperators(this.cmp_id).subscribe({
			next: (data: any) => {
				this.operators = data || [];
			},
		});
	}

	onSearch(): void {
		this.currentPage = 1;
		if (this.infiniteScroll) {
			this.infiniteScroll.disabled = false;
		}
		this.getList();
	}

	clearFilters(): void {
		this.cerca = '';
		this.filters = {};
		if (!this.isGestore) {
			this.filters.client_usr_id = this.configService.getUserID();
		}
		this.filterPopoverOpen = false;
		this.onSearch();
	}

	doRefresh(event: any): void {
		this.currentPage = 1;
		if (this.infiniteScroll) {
			this.infiniteScroll.disabled = false;
		}
		this.getList(event);
	}

	loadMore(event: any): void {
		this.currentPage++;
		this.getList(event);
	}

	goToDetail(apt: Appointment): void {
		this.router.navigate(['../detail', apt.apt_id], { relativeTo: this.route });
	}

	goToRequest(): void {
		this.router.navigate(['../request'], { relativeTo: this.route });
	}

	goToServiceTypes(): void {
		this.router.navigate(['../service-types'], { relativeTo: this.route });
	}

	goToAvailability(): void {
		this.router.navigate(['../availability'], { relativeTo: this.route });
	}

	getStatusLabel(status: AppointmentStatus): string {
		const opt = this.statusOptions.find((o) => o.value === status);
		return opt ? opt.label : status;
	}

	getStatusColor(status: AppointmentStatus): string {
		return this.statusColors[status] || '#999';
	}

	getAppointmentDate(apt: Appointment): string {
		const date = apt.apt_confirmed_date || apt.apt_proposed_date || apt.apt_requested_date;
		const time = apt.apt_confirmed_time || apt.apt_proposed_time || apt.apt_requested_time;
		if (!date) return '';
		const d = new Date(date);
		const dateStr = d.toLocaleDateString('it-IT', { day: '2-digit', month: '2-digit', year: 'numeric' });
		return time ? `${dateStr} ${time.substring(0, 5)}` : dateStr;
	}

	getClientName(apt: Appointment): string {
		return [apt.client_firstname, apt.client_lastname].filter(Boolean).join(' ') || '-';
	}

	getOperatorName(apt: Appointment): string {
		return [apt.operator_firstname, apt.operator_lastname].filter(Boolean).join(' ') || 'Non assegnato';
	}

	applyFilters(): void {
		this.filterPopoverOpen = false;
		this.onSearch();
	}

	getDateGroup(apt: Appointment): string {
		const date = apt.apt_confirmed_date || apt.apt_proposed_date || apt.apt_requested_date;
		if (!date) return 'nodate';
		const d = new Date(date);
		d.setHours(0, 0, 0, 0);
		const today = new Date();
		today.setHours(0, 0, 0, 0);
		const tomorrow = new Date(today);
		tomorrow.setDate(today.getDate() + 1);
		if (d.getTime() === today.getTime()) return 'today';
		if (d.getTime() === tomorrow.getTime()) return 'tomorrow';
		return d.toISOString().substring(0, 10);
	}

	getDateGroupLabel(apt: Appointment): string {
		const key = this.getDateGroup(apt);
		if (key === 'today') return 'Oggi';
		if (key === 'tomorrow') return 'Domani';
		if (key === 'nodate') return 'Data non definita';
		const d = new Date(key + 'T00:00:00');
		const today = new Date();
		today.setHours(0, 0, 0, 0);
		if (d < today) {
			return d.toLocaleDateString('it-IT', { day: 'numeric', month: 'long', year: 'numeric' });
		}
		return d.toLocaleDateString('it-IT', { weekday: 'long', day: 'numeric', month: 'short' });
	}

	shouldShowDateHeader(apt: Appointment, index: number): boolean {
		if (index === 0) return true;
		return this.getDateGroup(apt) !== this.getDateGroup(this.list[index - 1]);
	}
}
