<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import { Chart, registerables } from 'chart.js';

	Chart.register(...registerables);

	type Props = {
		data: {
			labels: string[];
			datasets: Array<{
				label: string;
				data: number[];
				backgroundColor?: string | string[];
				borderColor?: string | string[];
				borderWidth?: number;
			}>;
		};
		title?: string;
		height?: number;
		stacked?: boolean;
	};

	let { data, title = '', height = 400, stacked = false }: Props = $props();

	let canvas: HTMLCanvasElement;
	let chart: Chart | null = null;

	// Função para clarear cor
	function lightenColor(color: string, percent: number): string {
		const num = parseInt(color.replace('#', ''), 16);
		const amt = Math.round(2.55 * percent);
		const R = Math.min(255, (num >> 16) + amt);
		const G = Math.min(255, ((num >> 8) & 0x00ff) + amt);
		const B = Math.min(255, (num & 0x0000ff) + amt);
		return `#${(0x1000000 + R * 0x10000 + G * 0x100 + B).toString(16).slice(1)}`;
	}

	// Função para escurecer cor
	function darkenColor(color: string, percent: number): string {
		const num = parseInt(color.replace('#', ''), 16);
		const amt = Math.round(2.55 * percent);
		const R = Math.max(0, (num >> 16) - amt);
		const G = Math.max(0, ((num >> 8) & 0x00ff) - amt);
		const B = Math.max(0, (num & 0x0000ff) - amt);
		return `#${(0x1000000 + R * 0x10000 + G * 0x100 + B).toString(16).slice(1)}`;
	}

	// Criar gradientes 3D para cada cor
	function create3DGradientColors(colors: string[]): string[] {
		// Retornar cores com sombra 3D aplicada (usando cores mais claras e escuras)
		return colors.map((color) => {
			// Criar gradiente simulando 3D usando múltiplas cores
			return color; // Por enquanto retornar cor original, gradiente será aplicado via plugin
		});
	}

	onMount(() => {
		if (canvas) {
			const ctx = canvas.getContext('2d');
			if (ctx) {
				// Preparar dados com cores 3D
				const processedData = {
					labels: data.labels,
					datasets: data.datasets.map((dataset) => {
						// Processar cores de background
						let backgroundColor: string[];
						if (Array.isArray(dataset.backgroundColor)) {
							backgroundColor = dataset.backgroundColor;
						} else if (dataset.backgroundColor) {
							backgroundColor = data.labels.map(() => dataset.backgroundColor as string);
						} else {
							backgroundColor = data.labels.map(() => '#3b82f6');
						}

						// Processar cores de borda
						let borderColor: string[];
						if (Array.isArray(dataset.borderColor)) {
							borderColor = dataset.borderColor;
						} else if (dataset.borderColor) {
							borderColor = data.labels.map(() => dataset.borderColor as string);
						} else {
							borderColor = backgroundColor.map((color) => darkenColor(color, 15));
						}

						return {
							...dataset,
							backgroundColor,
							borderColor,
							borderWidth: dataset.borderWidth || 2,
							borderRadius: {
								topLeft: 10,
								topRight: 10,
								bottomLeft: 10,
								bottomRight: 10
							},
							borderSkipped: false,
							barThickness: 'flex',
							maxBarThickness: 60
						};
					})
				};

				chart = new Chart(ctx, {
					type: 'bar',
					data: processedData,
					options: {
						indexAxis: 'x',
						responsive: true,
						maintainAspectRatio: false,
						layout: {
							padding: {
								top: 15,
								right: 15,
								bottom: 15,
								left: 15
							}
						},
						plugins: {
							legend: {
								display: true,
								position: 'top',
								labels: {
									color: '#374151', // Cinza escuro para melhor legibilidade
									font: {
										size: 13,
										family: "'Inter', sans-serif",
										weight: '600'
									},
									usePointStyle: false,
									padding: 18,
									boxWidth: 18,
									boxHeight: 14,
									generateLabels: function (chart: any) {
										const datasets = chart.data.datasets;
										return datasets.map((dataset: any, datasetIndex: number) => {
											// Priorizar cor da legenda se disponível, senão usar a cor do background
											let backgroundColor: string;

											if (dataset.legendColor) {
												// Se há uma cor específica para a legenda, usar ela
												backgroundColor = dataset.legendColor;
											} else if (Array.isArray(dataset.backgroundColor)) {
												// Se todas as cores são iguais, usar a primeira
												const firstColor = dataset.backgroundColor[0];
												if (dataset.backgroundColor.every((c: string) => c === firstColor)) {
													backgroundColor = firstColor;
												} else {
													// Para múltiplas cores diferentes, usar a primeira como representativa
													backgroundColor = firstColor;
												}
											} else {
												backgroundColor = dataset.backgroundColor || '#3b82f6';
											}

											// Cor da borda para a legenda
											let borderColor: string;
											if (Array.isArray(dataset.borderColor)) {
												borderColor = dataset.borderColor[0] || backgroundColor;
											} else {
												borderColor = dataset.borderColor || backgroundColor;
											}

											return {
												text: dataset.label || `Dataset ${datasetIndex + 1}`,
												fillStyle: backgroundColor,
												strokeStyle: borderColor,
												lineWidth: dataset.borderWidth || 2,
												hidden: !chart.isDatasetVisible(datasetIndex),
												index: datasetIndex
											};
										});
									}
								}
							},
							title: {
								display: !!title,
								text: title,
								color: '#1f2937',
								font: {
									size: 18,
									weight: 'bold',
									family: "'Inter', sans-serif"
								},
								padding: {
									top: 10,
									bottom: 25
								}
							},
							tooltip: {
								backgroundColor: 'rgba(0, 0, 0, 0.9)',
								titleColor: '#fff',
								bodyColor: '#fff',
								borderColor: '#3b82f6',
								borderWidth: 2,
								padding: 14,
								cornerRadius: 10,
								displayColors: true,
								titleFont: {
									size: 14,
									weight: 'bold',
									family: "'Inter', sans-serif"
								},
								bodyFont: {
									size: 13,
									family: "'Inter', sans-serif"
								},
								callbacks: {
									label: function (context: any) {
										let label = context.dataset.label || '';
										if (label) {
											label += ': ';
										}
										if (context.parsed.y !== null && context.parsed.y !== undefined) {
											label += context.parsed.y.toLocaleString('pt-BR');
											// Verificar se é número de solicitações ou dias
											if (label.includes('Solicitações')) {
												label += ' solicitação(ões)';
											} else {
												label += ' dia(s)';
											}
										}
										return label;
									}
								}
							}
						},
						scales: {
							x: {
								stacked: stacked,
								grid: {
									display: false
								},
								ticks: {
									color: '#6b7280',
									font: {
										size: 12,
										family: "'Inter', sans-serif",
										weight: '500'
									},
									maxRotation: 45,
									minRotation: 0
								},
								border: {
									display: true,
									color: '#e5e7eb',
									width: 2
								}
							},
							y: {
								stacked: stacked,
								beginAtZero: true,
								grid: {
									color: 'rgba(0, 0, 0, 0.06)',
									lineWidth: 1,
									drawBorder: false
								},
								ticks: {
									color: '#6b7280',
									font: {
										size: 11,
										family: "'Inter', sans-serif",
										weight: '500'
									},
									callback: function (value: any) {
										if (typeof value === 'number') {
											return value.toLocaleString('pt-BR');
										}
										return value;
									}
								},
								border: {
									display: true,
									color: '#e5e7eb',
									width: 2
								}
							}
						},
						animation: {
							duration: 1200,
							easing: 'easeInOutQuart'
						},
						interaction: {
							mode: 'index',
							intersect: false
						},
						// Plugin customizado para aplicar gradiente 3D
						onHover: (event: any, activeElements: any[]) => {
							if (event.native) {
								const target = event.native.target as HTMLElement;
								if (activeElements.length > 0) {
									target.style.cursor = 'pointer';
								} else {
									target.style.cursor = 'default';
								}
							}
						}
					},
					plugins: [
						{
							id: 'gradient3D',
							beforeDraw: (chart: any) => {
								const ctx = chart.ctx;
								const chartArea = chart.chartArea;

								chart.data.datasets.forEach((dataset: any, datasetIndex: number) => {
									const meta = chart.getDatasetMeta(datasetIndex);
									if (!meta || !meta.data) return;

									meta.data.forEach((bar: any, index: number) => {
										if (!bar || bar.hidden) return;

										const backgroundColor = Array.isArray(dataset.backgroundColor)
											? dataset.backgroundColor[index]
											: dataset.backgroundColor;

										if (!backgroundColor || typeof backgroundColor !== 'string') return;

										// Criar gradiente 3D para a barra
										const gradient = ctx.createLinearGradient(
											bar.x - bar.width / 2,
											bar.y,
											bar.x + bar.width / 2,
											bar.base
										);

										// Aplicar gradiente com efeito 3D
										const lightColor = lightenColor(backgroundColor, 25);
										const darkColor = darkenColor(backgroundColor, 15);

										gradient.addColorStop(0, lightColor);
										gradient.addColorStop(0.3, backgroundColor);
										gradient.addColorStop(0.7, backgroundColor);
										gradient.addColorStop(1, darkColor);

										// Redesenhar a barra com gradiente
										ctx.save();
										ctx.fillStyle = gradient;
										ctx.fillRect(bar.x - bar.width / 2, bar.y, bar.width, bar.base - bar.y);
										ctx.restore();
									});
								});
							}
						}
					]
				} as any);
			}
		}
	});

	$effect(() => {
		if (chart && data) {
			// Atualizar dados do gráfico
			chart.data = data;
			chart.update('active');
		}
	});

	onDestroy(() => {
		if (chart) {
			chart.destroy();
		}
	});
</script>

<div style="height: {height}px; position: relative;">
	<canvas bind:this={canvas}></canvas>
</div>
