<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Sabriel_Orari {

	public static function orari_configurati() {
		$salvati = Sabriel_Base::get( 'orari_apertura', [] );
		if ( ! is_array( $salvati ) ) {
			return [];
		}
		return $salvati;
	}

	public static function normalizza_giorno( $raw ) {
		$aperto = ! empty( $raw['aperto'] );
		$fasce  = [];
		if ( isset( $raw['fasce'] ) && is_array( $raw['fasce'] ) ) {
			foreach ( $raw['fasce'] as $f ) {
				$d = isset( $f['dalle'] ) ? (string) $f['dalle'] : '';
				$a = isset( $f['alle'] ) ? (string) $f['alle'] : '';

				if ( '' !== $d && '' !== $a && self::minuti_orario( $d ) !== self::minuti_orario( $a ) ) {
					$fasce[] = [ 'dalle' => $d, 'alle' => $a ];
				}
			}
		} elseif ( ! empty( $raw['dalle'] ) && ! empty( $raw['alle'] ) ) {
			$fasce[] = [ 'dalle' => (string) $raw['dalle'], 'alle' => (string) $raw['alle'] ];
		}
		if ( empty( $fasce ) ) {
			$aperto = false;
		}
		return [
			'aperto' => $aperto,
			'fasce'  => $fasce,
			'dalle'  => $fasce[0]['dalle'] ?? '',
			'alle'   => $fasce[0]['alle'] ?? '',
		];
	}

	public static function orari_del_giorno( $dow ) {
		$tutti = self::orari_configurati();
		return self::normalizza_giorno( $tutti[ (int) $dow ] ?? [] );
	}

	private static function minuti_orario( $hm ) {
		$parti  = explode( ':', trim( (string) $hm ) );
		$ore    = isset( $parti[0] ) ? (int) $parti[0] : 0;
		$minuti = isset( $parti[1] ) ? (int) $parti[1] : 0;
		return $ore * 60 + $minuti;
	}

	public static function fascia_minuti( $dalle, $alle ) {
		$apre       = self::minuti_orario( $dalle );
		$chiude_raw = self::minuti_orario( $alle );
		$chiude     = ( $chiude_raw <= $apre ) ? $chiude_raw + 1440 : $chiude_raw;
		return [ $apre, $chiude ];
	}

	public static function orari_sono_configurati() {
		foreach ( self::orari_configurati() as $info ) {
			$g = self::normalizza_giorno( $info );
			if ( ! empty( $g['aperto'] ) && ! empty( $g['fasce'] ) ) {
				return true;
			}
		}
		return false;
	}

	public static function aperto_adesso() {
		$adesso   = Sabriel_Helpers::now();
		$ora_min  = (int) $adesso->format( 'G' ) * 60 + (int) $adesso->format( 'i' );
		$dow_oggi = (int) $adesso->format( 'N' );

		$oggi = self::orari_del_giorno( $dow_oggi );
		if ( ! empty( $oggi['aperto'] ) ) {
			foreach ( $oggi['fasce'] as $f ) {
				list( $apre, $chiude ) = self::fascia_minuti( $f['dalle'], $f['alle'] );
				if ( $ora_min >= $apre && $ora_min < $chiude ) {
					return true;
				}
			}
		}

		$dow_ieri = ( 1 === $dow_oggi ) ? 7 : $dow_oggi - 1;
		$ieri     = self::orari_del_giorno( $dow_ieri );
		if ( ! empty( $ieri['aperto'] ) ) {
			foreach ( $ieri['fasce'] as $f ) {
				list( $apre, $chiude ) = self::fascia_minuti( $f['dalle'], $f['alle'] );
				if ( $chiude > 1440 && ( $ora_min + 1440 ) >= $apre && ( $ora_min + 1440 ) < $chiude ) {
					return true;
				}
			}
		}
		return false;
	}

	public static function descrizione_orari_per_prompt( $per_modello = false ) {
		if ( ! self::orari_sono_configurati() ) {
			return '';
		}
		$tutti  = self::orari_configurati();
		$gruppi = [];
		$fasce_giorno = [];
		// Si scorrono sempre tutti e 7 i giorni, non solo quelli salvati: un giorno
		// mancante deve risultare "chiuso" nella descrizione data all'AI, altrimenti
		// il bot non sa di essere chiuso e rischia di accettare prenotazioni.
		for ( $dow = 1; $dow <= 7; $dow++ ) {
			$info = $tutti[ $dow ] ?? ( $tutti[ (string) $dow ] ?? [] );
			$g    = self::normalizza_giorno( $info );
			$fasce_giorno[ $dow ] = ( ! empty( $g['aperto'] ) && ! empty( $g['fasce'] ) ) ? $g['fasce'] : [];
		}

		/*
		 * ⚠ IL TURNO DELLA NOTTE SI RIMETTE INSIEME, MA SOLO QUI.
		 * Un turno che passa le 24 viene spezzato al salvataggio in «lunedi 15:00-00:00»
		 * + «martedi 00:00-02:00»: quella divisione e' GIUSTA e non si tocca, perche' e'
		 * su quella che nascono gli slot e le prenotazioni. Il guaio era raccontarla
		 * cosi' com'e': il cliente leggeva «lunedi fino alle 00:00» e credeva che a
		 * mezzanotte fosse chiuso, mentre il locale tira avanti fino alle due.
		 * Qui la coda dopo mezzanotte viene ricucita al giorno prima («lunedi
		 * 15:00-02:00») e tolta dall'elenco del giorno dopo. Nessun dato salvato cambia.
		 */
		$coda   = [];
		$togli  = [];
		for ( $dow = 1; $dow <= 7; $dow++ ) {
			$domani = ( 7 === $dow ) ? 1 : $dow + 1;
			if ( empty( $fasce_giorno[ $dow ] ) || empty( $fasce_giorno[ $domani ] ) ) {
				continue;
			}
			/* ⚠ SI CERCA DOVUNQUE NELL'ELENCO, non in testa e non in coda.
			   Le fasce non sono in ordine di orario: quella dopo mezzanotte viene
			   APPESA IN FONDO al giorno di arrivo quando si salva. */
			$i_notte = null;
			foreach ( $fasce_giorno[ $dow ] as $i => $f ) {
				if ( '00:00' === $f['alle'] ) {
					$i_notte = $i;
					break;
				}
			}
			if ( null === $i_notte ) {
				continue;
			}
			$i_coda = null;
			foreach ( $fasce_giorno[ $domani ] as $j => $f ) {
				if ( '00:00' === $f['dalle'] && '00:00' !== $f['alle'] ) {
					$i_coda = $j;
					break;
				}
			}
			if ( null === $i_coda ) {
				continue;
			}
			$coda[ $dow ]     = [ 'i' => $i_notte, 'alle' => $fasce_giorno[ $domani ][ $i_coda ]['alle'] ];
			$togli[ $domani ] = $i_coda;
		}
		for ( $dow = 1; $dow <= 7; $dow++ ) {
			$fasce = $fasce_giorno[ $dow ];
			if ( isset( $coda[ $dow ] ) ) {
				$fasce[ $coda[ $dow ]['i'] ]['alle'] = $coda[ $dow ]['alle'];
			}
			if ( isset( $togli[ $dow ] ) ) {
				unset( $fasce[ $togli[ $dow ] ] );
				$fasce = array_values( $fasce );
			}
			if ( $fasce ) {
				$parti = [];
				foreach ( $fasce as $f ) {
					$parti[] = $f['dalle'] . '-' . $f['alle'];
				}
				$chiave = implode( '/', $parti );
			} else {
				$chiave = 'chiuso';
			}
			$gruppi[ $chiave ][] = $dow;
		}

		$pezzi = [];
		foreach ( $gruppi as $chiave => $giorni ) {
			sort( $giorni );
			$sab_chiuso = $per_modello ? 'closed' : __( 'closed', 'sabriel-ai' );
			$pezzi[] = self::etichetta_giorni( $giorni, $per_modello ) . ' ' . ( 'closed' === $chiave ? $sab_chiuso : $chiave );
		}
		return implode( ', ', $pezzi );
	}

	private static function nome_giorno( $dow, $per_modello = false ) {
		global $wp_locale;
		$dow = (int) $dow;
		if ( $per_modello ) {
			$fissi = [ 1 => 'Mon', 2 => 'Tue', 3 => 'Wed', 4 => 'Thu', 5 => 'Fri', 6 => 'Sat', 7 => 'Sun' ];
			return $fissi[ $dow ] ?? (string) $dow;
		}
		if ( $wp_locale instanceof WP_Locale ) {
			$indice = ( 7 === $dow ) ? 0 : $dow;
			return $wp_locale->get_weekday_abbrev( $wp_locale->get_weekday( $indice ) );
		}
		$riserva = [ 1 => 'Mon', 2 => 'Tue', 3 => 'Wed', 4 => 'Thu', 5 => 'Fri', 6 => 'Sat', 7 => 'Sun' ];
		return isset( $riserva[ $dow ] ) ? $riserva[ $dow ] : (string) $dow;
	}

	private static function etichetta_giorni( array $giorni, $per_modello = false ) {
		$blocchi  = [];
		$corrente = [];
		foreach ( $giorni as $g ) {
			if ( empty( $corrente ) || (int) $g === (int) end( $corrente ) + 1 ) {
				$corrente[] = (int) $g;
			} else {
				$blocchi[]  = $corrente;
				$corrente   = [ (int) $g ];
			}
		}
		if ( ! empty( $corrente ) ) {
			$blocchi[] = $corrente;
		}
		$pezzi = [];
		foreach ( $blocchi as $blocco ) {
			if ( count( $blocco ) >= 3 ) {
				$pezzi[] = self::nome_giorno( $blocco[0], $per_modello ) . '-' . self::nome_giorno( end( $blocco ), $per_modello );
			} else {
				foreach ( $blocco as $g ) {
					$pezzi[] = self::nome_giorno( $g, $per_modello );
				}
			}
		}
		return implode( ', ', $pezzi );
	}
}
