// 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 } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AlertController, ModalController } from '@ionic/angular';
import { ConfigService } from '../../../providers/config.service';
import { LayoutService } from '../../../providers/layout.service';
import { SopralluoghiCmpService } from '../../../providers/sopralluoghi-cmp.service';
import { WorksiteService } from '../../../providers/worksite.service';
import { FileDownloadService } from '../../../providers/fileDownload.service';
import { FunctionService } from '../../../providers/function.service';
import { DrawingModalComponent } from '../../../components/drawing-modal/drawing-modal.component';
import { SopralluogoCmp, SopralluogoTipo, SOPR_STATO, isSopralluogoRfi, sopralluogoStatoLabel } from '../../../models/sopralluogo-cmp.model';
import { WorksiteCmp } from '../../../models/worksite-cmp.model';

@Component({
	selector: 'app-sopralluogo-cmp-form',
	templateUrl: './sopralluogo-cmp-form.page.html',
	styleUrls: ['./sopralluogo-cmp-form.page.scss'],
	standalone: false,
})
export class SopralluogoCmpFormPage {
	cmp_id = 0;
	prt_id = 0;
	sl_id = 0;
	wsPreset = 0;

	s: SopralluogoCmp = this.empty();
	tipi: SopralluogoTipo[] = [];
	cantieri: WorksiteCmp[] = [];
	documenti: any[] = [];

	saving = false;
	uploadingDoc = false;
	dateReady = false;

	// permesso di modifica via funzione di modulo 'modifica' (ruolo): senza, il form è in sola lettura
	moduleName = 'Lista Sopralluoghi';
	canEdit = false;

	readonly SOPR = SOPR_STATO;

	constructor(
		private route: ActivatedRoute,
		private router: Router,
		private alertCtrl: AlertController,
		private modalCtrl: ModalController,
		private config: ConfigService,
		public layout: LayoutService,
		private service: SopralluoghiCmpService,
		private worksite: WorksiteService,
		private fileDownload: FileDownloadService,
		private funService: FunctionService,
	) {}

	ionViewWillEnter() {
		this.resolveIds();
		this.wsPreset = +(this.route.snapshot.queryParamMap.get('ws') || 0);
		this.layout.setPageConfig({ title: this.sl_id > 0 ? 'Sopralluogo' : 'Nuovo sopralluogo', showBack: true, backButtonHref: `/portale/${this.prt_id}/company/${this.cmp_id}/service/sopralluoghi-cmp/list` });
		this.service.getTipi().subscribe((t) => (this.tipi = t || []));
		this.worksite.getWorksites(this.cmp_id, '', '', 500, 1).subscribe((w) => (this.cantieri = w || []));
		// carico prima il permesso (gateway sola lettura), poi i dati: evita race su ensureFolder/readonly
		this.funService.funzionibyuser(this.moduleName).subscribe((res: any[]) => {
			this.canEdit = (res || []).some((f) => f.mdfu_function === 'modifica');
			if (this.sl_id > 0) {
				this.loadSopralluogo();
			} else {
				this.s = this.empty();
				this.s.sl_ws_id = this.wsPreset || null;
				this.dateReady = true;
			}
		});
	}

	private resolveIds() {
		let r: ActivatedRoute | null = this.route;
		while (r) {
			const pm = r.snapshot.paramMap;
			if (pm.get('cmp_id')) this.cmp_id = +(pm.get('cmp_id') as string);
			if (pm.get('prt_id')) this.prt_id = +(pm.get('prt_id') as string);
			if (pm.get('id')) this.sl_id = +(pm.get('id') as string);
			r = r.parent;
		}
	}

	private empty(): SopralluogoCmp {
		return {
			sl_id: 0,
			sl_ws_id: null,
			sl_cmp_id: null,
			sl_tpi_id: null,
			sl_stato: 0,
			sl_protocollo: '',
			sl_descrizione: '',
			sl_note: '',
			sl_descrizione_oggetto: '',
			sl_costo: null,
			sl_costo_effettivo: null,
			sl_data_apertura_sopralluogo: null,
			sl_lavagna: null,
			sl_lavagna_thumbnails: null,
			sl_folder_id: null,
			origin: 'general',
		};
	}

	// sola lettura se RFI (vecchia gestione) oppure se manca il permesso di modifica (es. condomino)
	get readonly(): boolean {
		return isSopralluogoRfi(this.s.origin) || !this.canEdit;
	}
	get isRfi(): boolean {
		return isSopralluogoRfi(this.s.origin);
	}
	get cantiereFisso(): boolean {
		return this.wsPreset > 0;
	}
	get statoLabel(): string {
		return sopralluogoStatoLabel(this.s.sl_stato);
	}

	private loadSopralluogo() {
		this.service.getSopralluogo(this.sl_id).subscribe((a) => {
			if (!a) return;
			this.s = { ...a, sl_data_apertura_sopralluogo: this.toIso(a.sl_data_apertura_sopralluogo) };
			this.dateReady = true;
			this.ensureAndListDocs();
		});
	}

	private ensureAndListDocs() {
		if (this.s.sl_folder_id) {
			this.listDocs(this.s.sl_folder_id);
			return;
		}
		if (this.readonly) return;
		this.service.ensureFolder(this.cmp_id, this.s.sl_id, this.s.sl_protocollo || '').subscribe({
			next: (f) => {
				if (f > 0) {
					this.s.sl_folder_id = f;
					this.listDocs(f);
				}
			},
			error: () => {},
		});
	}

	private listDocs(folderId: number) {
		this.service.listDocumenti(folderId, this.cmp_id).subscribe((d) => (this.documenti = d || []));
	}

	private toIso(v: any): string | null {
		if (v === null || v === undefined || v === '') return null;
		const d = new Date(typeof v === 'string' ? v.replace(' ', 'T') : v);
		if (isNaN(d.getTime())) return null;
		const p = (n: number) => String(n).padStart(2, '0');
		return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}T${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
	}

	// ─── lavagna (stesso modale del vecchio RFI) ──────────────────
	async openDrawingModal() {
		const modal = await this.modalCtrl.create({
			component: DrawingModalComponent,
			componentProps: {
				title: this.s.sl_protocollo || 'Lavagna',
				lavagna: this.s.sl_lavagna || '',
				isInView: this.readonly,
				prt_id: this.prt_id,
				sopralluogo_id: this.s.sl_id,
			},
		});
		modal.onDidDismiss().then((result) => {
			if (result.data) {
				this.s.sl_lavagna = result.data[0];
				if (result.data[1]) this.s.sl_lavagna_thumbnails = result.data[1];
			}
		});
		return await modal.present();
	}

	// ─── salvataggio ──────────────────────────────────────────────
	save() {
		if (this.readonly) return;
		if (!this.s.sl_ws_id) {
			this.config.presentToastWarning('Seleziona il cantiere');
			return;
		}
		this.saving = true;
		this.persist();
	}

	private persist() {
		this.s.sl_cmp_id = this.cmp_id;
		const wasNew = !(this.s.sl_id > 0);
		this.service.addUpdSopralluogo(this.s).subscribe({
			next: (id) => {
				this.saving = false;
				const newId = id || this.s.sl_id;
				this.config.presentToastSuccess('Sopralluogo salvato');
				if (wasNew && newId > 0) {
					this.s.sl_id = newId;
					this.sl_id = newId;
					this.layout.setPageConfig({ title: 'Sopralluogo' });
					// crea la cartella documentale per gli allegati
					this.service.ensureFolder(this.cmp_id, newId, this.s.sl_protocollo || '').subscribe((f) => {
						if (f > 0) {
							this.s.sl_folder_id = f;
							this.listDocs(f);
						}
					});
				}
			},
			error: () => {
				this.saving = false;
				this.config.presentToastError('Errore nel salvataggio del sopralluogo');
			},
		});
	}

	// ─── documenti ────────────────────────────────────────────────
	onDocSelected(ev: Event) {
		const input = ev.target as HTMLInputElement;
		const file = input.files && input.files[0];
		input.value = '';
		if (!file) return;
		if (!this.s.sl_folder_id) {
			this.config.presentToastWarning('Salva prima il sopralluogo per allegare documenti');
			return;
		}
		const folderId = this.s.sl_folder_id;
		this.uploadingDoc = true;
		this.service.uploadDocumento(folderId, file).subscribe({
			next: (id) => {
				this.uploadingDoc = false;
				if (id > 0) {
					this.config.presentToastSuccess('Documento caricato');
					this.listDocs(folderId);
				} else this.config.presentToastError('Errore caricamento documento');
			},
			error: () => {
				this.uploadingDoc = false;
				this.config.presentToastError('Errore caricamento documento');
			},
		});
	}

	docId(d: any): number {
		return d?.drfl_id ?? d?.id ?? d?.fileId ?? 0;
	}
	docName(d: any): string {
		return d?.drfl_name || d?.drfl_filename || d?.name || d?.nameView || '(documento)';
	}
	scaricaDoc(d: any) {
		const id = this.docId(d);
		if (!id) return;
		this.service.fileDownloadUrl(id).subscribe((url) => {
			if (url) this.fileDownload.downloadAndOpenFile(url, this.docName(d));
			else this.config.presentToastError('Errore download del documento');
		});
	}

	// ─── flusso stati ─────────────────────────────────────────────
	get canFlow(): boolean {
		return this.s.sl_id > 0 && !this.readonly;
	}

	get flowHint(): string {
		switch (this.s.sl_stato) {
			case SOPR_STATO.CONVALIDATO:
				return 'Convalidato. Procedi con la contabilizzazione, oppure annullalo.';
			case SOPR_STATO.CONTABILIZZATO:
				return 'Contabilizzato. Procedi con la fatturazione.';
			case SOPR_STATO.FATTURATO:
				return 'Fatturato. Per modificarlo, riaprilo (tornerà ad “Aperto”).';
			case SOPR_STATO.ANNULLATO:
				return 'Annullato. Per riattivarlo, riaprilo (tornerà ad “Aperto”).';
			default:
				return 'Aperto. Convalidalo quando i dati sono completi.';
		}
	}

	private reload() {
		if (this.sl_id > 0) this.loadSopralluogo();
	}

	async convalida() {
		await this.runFlow('Convalidare il sopralluogo?', () => this.service.convalida(this.s.sl_id, this.s.sl_costo_effettivo ?? null));
	}
	async contabilizza() {
		await this.runFlow('Contabilizzare il sopralluogo?', () => this.service.contabilizza(this.s.sl_id));
	}
	async fattura() {
		await this.runFlow('Marcare come fatturato?', () => this.service.fattura(this.s.sl_id));
	}
	async annulla() {
		await this.runFlow('Annullare il sopralluogo?', () => this.service.annulla(this.s.sl_id), 'destructive');
	}
	async resetStato() {
		await this.runFlow('Riportare il sopralluogo ad Aperto?', () => this.service.resetStato(this.s.sl_id));
	}

	private async runFlow(message: string, action: () => any, role?: string) {
		const al = await this.alertCtrl.create({
			header: 'Conferma',
			message,
			buttons: [
				{ text: 'Annulla', role: 'cancel' },
				{
					text: 'Conferma',
					role: role,
					handler: () => {
						action().subscribe({
							next: () => {
								this.config.presentToastSuccess('Operazione eseguita');
								this.reload();
							},
							error: () => this.config.presentToastError('Errore'),
						});
					},
				},
			],
		});
		await al.present();
	}
}
