// 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 { IonModal, AlertController } from '@ionic/angular';
import { Router, ActivatedRoute } from '@angular/router';

import { ConfigService } from 'src/app/providers/config.service';
import { CompaniesService } from 'src/app/providers/companies.service';
import { FavoritesService } from 'src/app/providers/favorites.service';
import { LayoutService } from 'src/app/providers/layout.service';
import { ServiceCard } from 'src/app/models/serviceCard.model';
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 { BizReviewsService } from 'src/app/providers/biz-reviews.service';
import { MessagingService } from 'src/app/providers/messaging.service';
import { Appointment, AppointmentStatusColors, AppointmentStatus } from 'src/models/biz-appointments/appointment.model';
import { ServiceType } from 'src/models/biz-appointments/service-type.model';
import { WeeklyTemplate } from 'src/models/biz-appointments/availability.model';
import { Review, ReviewStats, ReportReasonOptions } from 'src/models/biz-appointments/review.model';

interface BusinessHoursDay {
	dayName: string;
	hoursLabel: string;
	isOpen: boolean;
}

interface ServiceGroup {
	category_name: string;
	services: ServiceType[];
	expanded: boolean;
}

interface ServiceListItem {
	type: 'category' | 'service';
	category?: ServiceGroup;
	service?: ServiceType;
}

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

	cmp_id: number = 0;
	isGestore: boolean = false;
	// Chat cliente->azienda disponibile solo se l'azienda e' in modalita' COMPANY (gruppo).
	// Default false (fail-safe): si abilita solo quando getChatMode conferma COMPANY.
	chatEnabled: boolean = false;

	// Chat modal state
	chatMessage: string = '';
	chatSending: boolean = false;

	company: any = null;
	businessHours: BusinessHoursDay[] = [];
	serviceTypes: ServiceType[] = [];
	groupedServiceTypes: ServiceGroup[] = [];
	serviceListItems: ServiceListItem[] = [];
	upcomingAppointments: Appointment[] = [];
	gestoreAppointments: Appointment[] = [];

	loadingCompany: boolean = false;
	loadingServices: boolean = false;
	loadingAppointments: boolean = false;
	loadingGestoreAppointments: boolean = false;

	galleryPhotos: any[] = [];

	activeTab: 'services' | 'gallery' | 'info' | 'reviews' = 'services';

	// Recensioni
	reviewStats: ReviewStats | null = null;
	reviews: Review[] = [];
	loadingReviews: boolean = false;
	stars = [1, 2, 3, 4, 5];

	// Service selection state
	selectedService: ServiceType | null = null;
	additionalServices: ServiceType[] = [];

	// Hero image
	heroImage: string | null = null;
	heroBackgroundClass: string = '';
	heroOpacity: number = 0.8;
	isFavorite: boolean = false;
	serviceDescription: string = '';
	private activeCard: ServiceCard | null = null;

	statusColors = AppointmentStatusColors;

	private dayNames = ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'];

	constructor(
		private router: Router,
		private route: ActivatedRoute,
		private configService: ConfigService,
		private companiesService: CompaniesService,
		private favoritesService: FavoritesService,
		private layoutService: LayoutService,
		private appointmentsService: BizAppointmentsService,
		private serviceTypesService: BizServiceTypesService,
		private availabilityService: BizAvailabilityService,
		private reviewsService: BizReviewsService,
		private messagingService: MessagingService,
		private alertController: AlertController,
	) {}

	ngOnInit(): void {
		this.cmp_id = Number(this.route.snapshot.paramMap.get('cmp_id') || this.route.parent?.snapshot.paramMap.get('cmp_id') || 0);
		this.isGestore = this.configService.isUserAuthorizedAs('ADMIN');
		this.activeTab = 'services';
		this.layoutService.setPageConfig({ showBack: true, title: '' });
		this.initHeroImage();
		if (!this.isGestore && this.cmp_id) {
			this.companiesService.getChatMode(this.cmp_id).subscribe((mode) => {
				this.chatEnabled = mode === 'COMPANY';
			});
		}
		this.loadCompanyInfo();
		this.loadBusinessHours();
		this.loadServiceTypes();
		this.loadGallery();
		this.loadReviews();
		if (this.isGestore) {
			this.loadGestoreAppointments();
		} else {
			this.loadUpcomingAppointments();
		}
	}

	private initHeroImage(): void {
		const card: ServiceCard | null = this.companiesService.activeServiceCard;
		if (card) {
			this.activeCard = card;
			this.serviceDescription = card.srv_description || '';
			this.isFavorite = this.favoritesService.isFavorite(card.srv_id, card.company?.id || 0);
			if (card.srv_show_hero_image && card.srv_background_image) {
				this.heroImage = card.srv_background_image;
				this.heroBackgroundClass = card.srv_background_class || '';
				this.heroOpacity = card.srv_background_opacity ?? 0.8;
			}
		}
	}

	isToday(dayName: string): boolean {
		return dayName === this.dayNames[new Date().getDay()];
	}

	toggleFavorite(): void {
		if (!this.activeCard) return;
		const srvId = this.activeCard.srv_id;
		const cmpId = this.activeCard.company?.id || 0;
		this.favoritesService.toggleFavorite(srvId, cmpId);
		this.isFavorite = this.favoritesService.isFavorite(srvId, cmpId);
	}

	doRefresh(event: any): void {
		this.loadCompanyInfo();
		this.loadBusinessHours();
		this.loadServiceTypes();
		this.loadGallery();
		this.loadReviews();
		if (this.isGestore) {
			this.loadGestoreAppointments();
		} else {
			this.loadUpcomingAppointments();
		}
		setTimeout(() => event.target.complete(), 1000);
	}

	loadGallery(): void {
		this.companiesService.GetCompanyGallery(this.cmp_id).subscribe({
			next: (data: any) => {
				this.galleryPhotos = data || [];
			},
		});
	}

	loadReviews(): void {
		this.loadingReviews = true;
		this.reviewsService.getStats(this.cmp_id).subscribe({
			next: (s) => (this.reviewStats = s),
		});
		this.reviewsService.getReviews(this.cmp_id, null, 20, 0).subscribe({
			next: (res: any) => {
				this.reviews = res.list || [];
			},
			complete: () => {
				this.loadingReviews = false;
			},
		});
	}

	/** Distribuzione 1-5 stelle (per le barre). */
	get reviewDistribution(): { stars: number; count: number; pct: number }[] {
		const s = this.reviewStats;
		if (!s) return [];
		const total = s.total_count || 0;
		const rows = [
			{ stars: 5, count: s.star5 },
			{ stars: 4, count: s.star4 },
			{ stars: 3, count: s.star3 },
			{ stars: 2, count: s.star2 },
			{ stars: 1, count: s.star1 },
		];
		return rows.map((r) => ({ ...r, pct: total > 0 ? Math.round((r.count / total) * 100) : 0 }));
	}

	reviewClientName(r: Review): string {
		const n = `${r.client_firstname || ''} ${(r.client_lastname || '').charAt(0)}`.trim();
		return n ? n + '.' : 'Cliente';
	}

	async reportReview(r: Review): Promise<void> {
		const alert = await this.alertController.create({
			header: 'Segnala recensione',
			inputs: ReportReasonOptions.map((opt, i) => ({
				type: 'radio' as const,
				label: opt.label,
				value: opt.value,
				checked: i === 0,
			})),
			buttons: [
				{ text: 'Annulla', role: 'cancel' },
				{
					text: 'Segnala',
					handler: (reason: string) => {
						this.reviewsService.reportReview(r.rev_id, reason).subscribe({
							next: () => this.configService.presentToastSuccess('Segnalazione inviata'),
							error: () => this.configService.presentToastError('Errore segnalazione'),
						});
					},
				},
			],
		});
		await alert.present();
	}

	loadCompanyInfo(): void {
		this.loadingCompany = true;
		this.companiesService.GetCompany(this.cmp_id).subscribe({
			next: (data: any) => {
				this.company = data;
				if (data?.name) {
					this.layoutService.setPageConfig({ title: data.name });
				}
			},
			complete: () => {
				this.loadingCompany = false;
			},
		});
	}

	loadBusinessHours(): void {
		this.availabilityService.getWeeklyTemplates(this.cmp_id).subscribe({
			next: (data: any) => {
				const templates: WeeklyTemplate[] = data || [];
				this.businessHours = this.computeBusinessHours(templates);
			},
		});
	}

	private computeBusinessHours(templates: WeeklyTemplate[]): BusinessHoursDay[] {
		const days: BusinessHoursDay[] = [];
		// Lunedì (1) a Sabato (6), poi Domenica (0)
		const dayOrder = [1, 2, 3, 4, 5, 6, 0];

		for (const dayNum of dayOrder) {
			const dayTemplates = templates.filter((t) => t.wt_day_of_week === dayNum && t.wt_active);
			if (dayTemplates.length === 0) {
				days.push({ dayName: this.dayNames[dayNum], hoursLabel: 'Chiuso', isOpen: false });
			} else {
				const ranges = dayTemplates
					.map((t) => {
						const start = t.wt_start_time?.substring(0, 5) || '';
						const end = t.wt_end_time?.substring(0, 5) || '';
						if (t.wt_break_start && t.wt_break_end) {
							const bs = t.wt_break_start.substring(0, 5);
							const be = t.wt_break_end.substring(0, 5);
							return `${start}-${bs}, ${be}-${end}`;
						}
						return `${start}-${end}`;
					})
					.join(' | ');
				days.push({ dayName: this.dayNames[dayNum], hoursLabel: ranges, isOpen: true });
			}
		}
		return days;
	}

	loadServiceTypes(): void {
		this.loadingServices = true;
		this.serviceTypesService.getServiceTypes(this.cmp_id).subscribe({
			next: (data: any) => {
				this.serviceTypes = (data || []).filter((st: ServiceType) => st.st_active);
				this.groupServiceTypesByCategory();
			},
			complete: () => {
				this.loadingServices = false;
			},
		});
	}

	private groupServiceTypesByCategory(): void {
		const groups = new Map<string, ServiceType[]>();
		for (const st of this.serviceTypes) {
			const catName = st.category_name || '';
			if (!groups.has(catName)) {
				groups.set(catName, []);
			}
			groups.get(catName)!.push(st);
		}
		this.groupedServiceTypes = [];
		groups.forEach((services, category_name) => {
			this.groupedServiceTypes.push({ category_name: category_name || 'Altro', services, expanded: false });
		});

		// Build flat list: categories as items, uncategorized services as direct items
		this.serviceListItems = [];
		for (const group of this.groupedServiceTypes) {
			if (group.category_name === 'Altro') {
				// Services without category shown directly
				for (const st of group.services) {
					this.serviceListItems.push({ type: 'service', service: st });
				}
			} else {
				// Category as a clickable item
				this.serviceListItems.push({ type: 'category', category: group });
			}
		}
	}

	toggleCategory(group: ServiceGroup): void {
		group.expanded = !group.expanded;
	}

	getCategoryColor(group: ServiceGroup): string {
		return group.services[0]?.st_color || '#94A3B8';
	}

	hasGroupSelection(group: ServiceGroup): boolean {
		return group.services.some((s) => this.isSelected(s) || this.isAdditional(s));
	}

	onServiceTap(st: ServiceType): void {
		if (this.isGestore) {
			this.goToRequest(st);
			return;
		}
		if (this.isSelected(st)) {
			this.selectedService = null;
			this.additionalServices = [];
		} else if (this.isAdditional(st)) {
			this.additionalServices = this.additionalServices.filter((s) => s.st_id !== st.st_id);
		} else if (!this.selectedService) {
			this.selectedService = st;
		} else {
			this.additionalServices.push(st);
		}
	}

	isSelected(st: ServiceType): boolean {
		return this.selectedService?.st_id === st.st_id;
	}

	isAdditional(st: ServiceType): boolean {
		return this.additionalServices.some((s) => s.st_id === st.st_id);
	}

	getTotalDuration(): number {
		const main = this.selectedService?.st_duration_minutes || 0;
		const extra = this.additionalServices.reduce((sum, s) => sum + (s.st_duration_minutes || 0), 0);
		return main + extra;
	}

	clearSelection(): void {
		this.selectedService = null;
		this.additionalServices = [];
	}

	proceedToRequest(): void {
		if (!this.selectedService) return;
		const params: any = { service_type_id: this.selectedService.st_id };
		if (this.additionalServices.length > 0) {
			params.additional_ids = this.additionalServices.map((s) => s.st_id).join(',');
		}
		this.router.navigate(['../request'], { relativeTo: this.route, queryParams: params });
	}

	loadUpcomingAppointments(): void {
		this.loadingAppointments = true;
		const filters: any = {
			client_usr_id: this.configService.getUserID(),
		};

		this.appointmentsService.getAppointments(this.cmp_id, '', '', 5, 0, filters).subscribe({
			next: (data: any) => {
				this.upcomingAppointments = (data.list || []).filter((a: Appointment) => !['COMPLETATO', 'ANNULLATO', 'RIFIUTATO'].includes(a.apt_status));
			},
			complete: () => {
				this.loadingAppointments = false;
			},
		});
	}

	loadGestoreAppointments(): void {
		this.loadingGestoreAppointments = true;
		this.appointmentsService.getAppointments(this.cmp_id, '', '', 50, 0).subscribe({
			next: (data: any) => {
				this.gestoreAppointments = (data.list || []).filter((a: Appointment) => !['COMPLETATO', 'ANNULLATO', 'RIFIUTATO'].includes(a.apt_status));
			},
			complete: () => {
				this.loadingGestoreAppointments = false;
			},
		});
	}

	// --- Navigazione ---

	goToRequest(st?: ServiceType): void {
		if (st) {
			this.router.navigate(['../request'], { relativeTo: this.route, queryParams: { service_type_id: st.st_id } });
		} else {
			this.router.navigate(['../request'], { relativeTo: this.route });
		}
	}

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

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

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

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

	openChat(): void {
		this.chatMessage = '';
		this.chatSending = false;
		this.chatModal.present();
	}

	closeChatModal(): void {
		this.chatModal.dismiss();
	}

	sendChatMessage(): void {
		const text = this.chatMessage.trim();
		this.chatSending = true;
		this.messagingService.findOrCreateConversationByCompany(this.cmp_id).subscribe({
			next: (conv) => {
				const navigate = () => {
					this.chatSending = false;
					this.chatModal.dismiss();
					this.router.navigate(['/messaging/chat', conv.conv_id], {
						state: {
							chatWith: conv.other_company_name || this.company?.cmp_name || 'Chat',
							isCompany: true,
						},
					});
				};
				if (text) {
					this.messagingService.sendMessage(conv.conv_id, text).subscribe({ next: navigate, error: navigate });
				} else {
					navigate();
				}
			},
			error: () => {
				this.chatSending = false;
				this.configService.presentToastError('Impossibile avviare la chat con questa azienda');
			},
		});
	}

	getCompanyInitials(): string {
		const name: string = this.company?.name || this.company?.cmp_name || '';
		return name
			.split(' ')
			.slice(0, 2)
			.map((w: string) => w.charAt(0).toUpperCase())
			.join('');
	}

	getCompanyAvatarGradient(): string {
		const name: string = this.company?.name || this.company?.cmp_name || 'A';
		const hue = name.split('').reduce((acc, c) => acc + c.charCodeAt(0), 0) % 360;
		return `linear-gradient(135deg, hsl(${hue}, 65%, 50%), hsl(${(hue + 40) % 360}, 75%, 40%))`;
	}

	// --- Actions ---

	callCompany(): void {
		if (this.company?.cmp_phone_number) {
			window.open(`tel:${this.company.cmp_phone_number}`, '_system');
		}
	}

	openWebsite(): void {
		if (this.company?.cmp_web) {
			let url = this.company.cmp_web;
			if (!url.startsWith('http')) {
				url = 'https://' + url;
			}
			window.open(url, '_system');
		}
	}

	getDirections(): void {
		const addr = this.getCompanyAddress();
		if (addr) {
			window.open(`https://maps.google.com/maps?q=${encodeURIComponent(addr)}`, '_system');
		}
	}

	getCompanyAddress(): string {
		if (!this.company) return '';
		// Sede legale (oggetto annidato "of")
		const of = this.company.of;
		if (of) {
			const parts = [of.of_address, of.of_number, of.of_cap, of.of_municipality_name].filter(Boolean);
			if (parts.length > 0) return parts.join(', ');
		}
		// Fallback: indirizzo rappresentante legale
		const parts = [this.company.cmp_rlegal_res_address, this.company.cmp_rlegal_res_number, this.company.cmp_rlegal_res_cup, this.company.cmp_rlegal_res_city].filter(Boolean);
		return parts.join(', ');
	}

	getBusinessHoursSummary(): string {
		const today = new Date().getDay();
		const todayHours = this.businessHours.find((d) => d.dayName === this.dayNames[today]);
		if (!todayHours) return '';
		return todayHours.isOpen ? todayHours.hoursLabel : 'Chiuso oggi';
	}

	// --- Helpers ---

	getStatusLabel(status: AppointmentStatus): string {
		const labels: Record<string, string> = {
			IN_ATTESA: 'In Attesa',
			PROPOSTA_RICEVUTA: 'Proposta',
			ATTENDE_CONFERMA: 'Attende Conferma',
			CONFERMATO: 'Confermato',
			IN_CORSO: 'In Corso',
		};
		return labels[status] || 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', { weekday: 'short', day: 'numeric', month: 'short' });
		return time ? `${dateStr} ore ${time.substring(0, 5)}` : dateStr;
	}
}
