<script lang="ts">
	import { onMount } from 'svelte';
	import { Calendar } from '@fullcalendar/core';
	import dayGridPlugin from '@fullcalendar/daygrid';
	import interactionPlugin from '@fullcalendar/interaction';
	import multiMonthPlugin from '@fullcalendar/multimonth';
	import ptBrLocale from '@fullcalendar/core/locales/pt-br';
	import { SvelteDate } from 'svelte/reactivity';

	interface Props {
		periodosExistentes?: Array<{ dataInicio: string; dataFim: string; dias: number }>;
		onPeriodoAdicionado?: (periodo: { dataInicio: string; dataFim: string; dias: number }) => void;
		onPeriodoRemovido?: (index: number) => void;
		maxPeriodos?: number;
		minDiasPorPeriodo?: number;
		modoVisualizacao?: 'month' | 'multiMonth';
		readonly?: boolean;
	}

	let {
		periodosExistentes = [],
		onPeriodoAdicionado,
		onPeriodoRemovido,
		maxPeriodos = 3,
		minDiasPorPeriodo = 5,
		modoVisualizacao = 'month',
		readonly = false
	}: Props = $props();

	let calendarEl: HTMLDivElement;
	let calendar: Calendar | null = null;

	// Cores dos períodos
	const coresPeriodos = [
		{ bg: '#667eea', border: '#5568d3', text: '#ffffff' }, // Roxo
		{ bg: '#f093fb', border: '#c75ce6', text: '#ffffff' }, // Rosa
		{ bg: '#4facfe', border: '#00c6ff', text: '#ffffff' } // Azul
	];

	const eventos = $derived.by(() =>
		periodosExistentes.map((periodo, index) => ({
			id: `periodo-${index}`,
			title: `Período ${index + 1} (${periodo.dias} dias)`,
			start: periodo.dataInicio,
			end: calcularDataFim(periodo.dataFim),
			backgroundColor: coresPeriodos[index % coresPeriodos.length].bg,
			borderColor: coresPeriodos[index % coresPeriodos.length].border,
			textColor: coresPeriodos[index % coresPeriodos.length].text,
			display: 'block',
			extendedProps: {
				index,
				dias: periodo.dias
			}
		}))
	);

	// Helper: Adicionar 1 dia à data fim (FullCalendar usa exclusive end)
	function calcularDataFim(dataFim: string): string {
		const data = new SvelteDate(dataFim);
		data.setDate(data.getDate() + 1);
		return data.toISOString().split('T')[0];
	}

	// Helper: Calcular dias entre datas (inclusivo)
	function calcularDias(inicio: Date, fim: Date): number {
		const diffTime = Math.abs(fim.getTime() - inicio.getTime());
		const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
		return diffDays;
	}

	// Atualizar eventos quando períodos mudam
	$effect(() => {
		if (!calendar) return;

		calendar.removeAllEvents();
		if (eventos.length === 0) return;

		// FullCalendar muta os objetos de evento internamente, então fornecemos cópias
		const eventosClonados = eventos.map((evento) => ({
			...evento,
			extendedProps: { ...evento.extendedProps }
		}));
		calendar.addEventSource(eventosClonados);
	});

	onMount(() => {
		if (!calendarEl) return;

		calendar = new Calendar(calendarEl, {
			plugins: [dayGridPlugin, interactionPlugin, multiMonthPlugin],
			initialView: modoVisualizacao === 'multiMonth' ? 'multiMonthYear' : 'dayGridMonth',
			locale: ptBrLocale,
			headerToolbar: {
				left: 'prev,next today',
				center: 'title',
				right: modoVisualizacao === 'multiMonth' ? 'multiMonthYear' : 'dayGridMonth'
			},
			height: 'auto',
			selectable: !readonly,
			selectMirror: true,
			unselectAuto: false,
			events: eventos.map((evento) => ({ ...evento, extendedProps: { ...evento.extendedProps } })),

			// Estilo customizado
			buttonText: {
				today: 'Hoje',
				month: 'Mês',
				multiMonthYear: 'Ano'
			},

			// Seleção de período
			select: (info) => {
				if (readonly) return;

				const inicio = new Date(info.startStr);
				const fim = new SvelteDate(info.endStr);
				fim.setDate(fim.getDate() - 1); // FullCalendar usa exclusive end

				const dias = calcularDias(inicio, fim);

				// Validar número de períodos
				if (periodosExistentes.length >= maxPeriodos) {
					alert(`Máximo de ${maxPeriodos} períodos permitidos`);
					calendar?.unselect();
					return;
				}

				// Validar mínimo de dias
				if (dias < minDiasPorPeriodo) {
					alert(`Período deve ter no mínimo ${minDiasPorPeriodo} dias`);
					calendar?.unselect();
					return;
				}

				// Adicionar período
				const novoPeriodo = {
					dataInicio: info.startStr,
					dataFim: fim.toISOString().split('T')[0],
					dias
				};

				if (onPeriodoAdicionado) {
					onPeriodoAdicionado(novoPeriodo);
				}

				calendar?.unselect();
			},

			// Click em evento para remover
			eventClick: (info) => {
				if (readonly) return;

				const index = info.event.extendedProps.index;
				if (
					confirm(`Deseja remover o Período ${index + 1} (${info.event.extendedProps.dias} dias)?`)
				) {
					if (onPeriodoRemovido) {
						onPeriodoRemovido(index);
					}
				}
			},

			// Tooltip ao passar mouse
			eventDidMount: (info) => {
				info.el.title = `Click para remover\n${info.event.title}`;
				info.el.style.cursor = readonly ? 'default' : 'pointer';
			},

			// Desabilitar datas passadas
			selectAllow: (selectInfo) => {
				const hoje = new SvelteDate();
				hoje.setHours(0, 0, 0, 0);
				return new Date(selectInfo.start) >= hoje;
			},

			// Highlight de fim de semana
			dayCellClassNames: (arg) => {
				if (arg.date.getDay() === 0 || arg.date.getDay() === 6) {
					return ['fc-day-weekend-custom'];
				}
				return [];
			}
		});

		calendar.render();

		return () => {
			calendar?.destroy();
		};
	});
</script>

<div class="calendario-ferias-wrapper">
	<!-- Header com instruções -->
	{#if !readonly}
		<div class="alert alert-info mb-4 shadow-lg">
			<svg
				xmlns="http://www.w3.org/2000/svg"
				fill="none"
				viewBox="0 0 24 24"
				class="h-6 w-6 shrink-0 stroke-current"
			>
				<path
					stroke-linecap="round"
					stroke-linejoin="round"
					stroke-width="2"
					d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
				></path>
			</svg>
			<div class="text-sm">
				<p class="font-bold">Como usar:</p>
				<ul class="mt-1 list-inside list-disc">
					<li>Clique e arraste no calendário para selecionar um período de férias</li>
					<li>Clique em um período colorido para removê-lo</li>
					<li>
						Você pode adicionar até {maxPeriodos} períodos (mínimo {minDiasPorPeriodo} dias cada)
					</li>
				</ul>
			</div>
		</div>
	{/if}

	<!-- Calendário -->
	<div
		bind:this={calendarEl}
		class="calendario-ferias border-primary/10 overflow-hidden rounded-2xl border-2 shadow-2xl"
	></div>

	<!-- Legenda de períodos -->
	{#if periodosExistentes.length > 0}
		<div class="mt-6 grid grid-cols-1 gap-4 md:grid-cols-3">
			{#each periodosExistentes as periodo, index (index)}
				<div
					class="stat bg-base-100 rounded-xl border-2 shadow-lg transition-all hover:scale-105"
					style="border-color: {coresPeriodos[index % coresPeriodos.length].border}"
				>
					<div
						class="stat-figure flex h-12 w-12 items-center justify-center rounded-full text-xl font-bold text-white"
						style="background: {coresPeriodos[index % coresPeriodos.length].bg}"
					>
						{index + 1}
					</div>
					<div class="stat-title">Período {index + 1}</div>
					<div
						class="stat-value text-2xl"
						style="color: {coresPeriodos[index % coresPeriodos.length].bg}"
					>
						{periodo.dias} dias
					</div>
					<div class="stat-desc">
						{new Date(periodo.dataInicio).toLocaleDateString('pt-BR')} até
						{new Date(periodo.dataFim).toLocaleDateString('pt-BR')}
					</div>
				</div>
			{/each}
		</div>
	{/if}
</div>

<style>
	/* Calendário Premium */
	.calendario-ferias {
		font-family:
			'Inter',
			-apple-system,
			BlinkMacSystemFont,
			'Segoe UI',
			sans-serif;
	}

	/* Toolbar moderna */
	:global(.fc .fc-toolbar) {
		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
		padding: 1rem;
		border-radius: 1rem 1rem 0 0;
		color: white !important;
	}

	:global(.fc .fc-toolbar-title) {
		color: white !important;
		font-weight: 700;
		font-size: 1.5rem;
	}

	:global(.fc .fc-button) {
		background: rgba(255, 255, 255, 0.2) !important;
		border: 1px solid rgba(255, 255, 255, 0.3) !important;
		color: white !important;
		font-weight: 600;
		text-transform: capitalize;
		transition: all 0.3s ease;
	}

	:global(.fc .fc-button:hover) {
		background: rgba(255, 255, 255, 0.3) !important;
		transform: translateY(-2px);
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
	}

	:global(.fc .fc-button-active) {
		background: rgba(255, 255, 255, 0.4) !important;
	}

	/* Cabeçalho dos dias */
	:global(.fc .fc-col-header-cell) {
		background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
		font-weight: 600;
		text-transform: uppercase;
		font-size: 0.75rem;
		letter-spacing: 0.05em;
		padding: 0.75rem 0.5rem;
		color: #495057;
	}

	/* Células dos dias */
	:global(.fc .fc-daygrid-day) {
		transition: all 0.2s ease;
	}

	:global(.fc .fc-daygrid-day:hover) {
		background: rgba(102, 126, 234, 0.05);
	}

	:global(.fc .fc-daygrid-day-number) {
		padding: 0.5rem;
		font-weight: 600;
		color: #495057;
	}

	/* Fim de semana */
	:global(.fc .fc-day-weekend-custom) {
		background: rgba(255, 193, 7, 0.05);
	}

	/* Hoje */
	:global(.fc .fc-day-today) {
		background: rgba(102, 126, 234, 0.1) !important;
		border: 2px solid #667eea !important;
	}

	/* Eventos (períodos selecionados) */
	:global(.fc .fc-event) {
		border-radius: 0.5rem;
		padding: 0.25rem 0.5rem;
		font-weight: 600;
		font-size: 0.875rem;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
		transition: all 0.3s ease;
		cursor: pointer;
	}

	:global(.fc .fc-event:hover) {
		transform: translateY(-2px);
		box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
	}

	/* Seleção (arrastar) */
	:global(.fc .fc-highlight) {
		background: rgba(102, 126, 234, 0.3) !important;
		border: 2px dashed #667eea;
	}

	/* Datas desabilitadas (passado) */
	:global(.fc .fc-day-past .fc-daygrid-day-number) {
		opacity: 0.4;
	}

	/* Remover bordas padrão */
	:global(.fc .fc-scrollgrid) {
		border: none !important;
	}

	:global(.fc .fc-scrollgrid-section > td) {
		border: none !important;
	}

	/* Grid moderno */
	:global(.fc .fc-daygrid-day-frame) {
		border: 1px solid #e9ecef;
		min-height: 80px;
	}

	/* Responsivo */
	@media (max-width: 768px) {
		:global(.fc .fc-toolbar) {
			flex-direction: column;
			gap: 0.75rem;
		}

		:global(.fc .fc-toolbar-title) {
			font-size: 1.25rem;
		}

		:global(.fc .fc-button) {
			font-size: 0.75rem;
			padding: 0.25rem 0.5rem;
		}
	}
</style>
