/**
 * Marker-cluster icons — color- and style-driven SVG so a host can theme the
 * count bubbles to match its brand. Used by BOTH map adapters: Leaflet (as
 * divIcon innerHTML) and Google (as a marker icon data-URI). Generic — the host
 * picks the style + colour (settings) and passes them via the provider opts
 * (clusterStyle / clusterColor).
 */

// Bubble size scales gently with the cluster count for a subtle hierarchy.
export const clusterSize = ( count ) =>
	count >= 100 ? 54 : count >= 25 ? 48 : count >= 10 ? 44 : 38;

// Preset keys — shared with the host's "Cluster style" settings dropdown.
export const CLUSTER_STYLES = [ 'soft', 'solid', 'ring', 'rounded', 'gradient', 'outline', 'glass', 'glass-rings', 'stacked', 'pin' ];

/** Build the cluster bubble SVG markup for a style + colour + count. */
export const clusterSvg = ( style, color, count ) => {
	const s = clusterSize( count );
	const c = color || '#3858e9';
	const r = s / 2;
	const fs = count >= 100 ? 13 : 14;
	const label = ( fill, cy = '50%' ) =>
		`<text x="50%" y="${ cy }" dy=".36em" text-anchor="middle" font-family="-apple-system,Segoe UI,Roboto,sans-serif" font-weight="700" font-size="${ fs }" fill="${ fill }">${ count }</text>`;
	// Stable per-(count,size) gradient id; identical defs may safely share an id.
	const gid = `cg${ count }x${ s }`;

	let body;
	switch ( style ) {
		case 'ring':
			body = `<circle cx="${ r }" cy="${ r }" r="${ r - 3 }" fill="#fff" stroke="${ c }" stroke-width="4"/>${ label( c ) }`;
			break;
		case 'rounded': {
			const p = 3;
			const w = s - p * 2;
			body = `<rect x="${ p }" y="${ p }" width="${ w }" height="${ w }" rx="${ Math.round( w * 0.28 ) }" fill="${ c }"/>${ label( '#fff' ) }`;
			break;
		}
		case 'solid':
			body = `<circle cx="${ r }" cy="${ r }" r="${ r - 2 }" fill="${ c }"/>${ label( '#fff' ) }`;
			break;
		case 'gradient':
			// Vertical gradient (full colour → translucent) for a glossy bubble.
			body = `<defs><linearGradient id="${ gid }" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="${ c }"/><stop offset="1" stop-color="${ c }" stop-opacity="0.55"/></linearGradient></defs><circle cx="${ r }" cy="${ r }" r="${ r - 2 }" fill="url(#${ gid })"/>${ label( '#fff' ) }`;
			break;
		case 'outline':
			// Map shows through a faint tint; coloured border + coloured count.
			body = `<circle cx="${ r }" cy="${ r }" r="${ r - 3 }" fill="${ c }" fill-opacity="0.12" stroke="${ c }" stroke-width="2"/>${ label( c ) }`;
			break;
		case 'glass':
			// Frosted: near-white centre, coloured hairline ring + coloured count.
			body = `<circle cx="${ r }" cy="${ r }" r="${ r - 2 }" fill="#fff" fill-opacity="0.86" stroke="${ c }" stroke-width="2"/>${ label( c ) }`;
			break;
		case 'glass-rings':
			// Three translucent concentric layers: the familiar multi-ring cluster
			// treatment, with a frosted centre that remains readable over any map.
			body = `<circle cx="${ r }" cy="${ r }" r="${ r - 1 }" fill="${ c }" fill-opacity="0.10" stroke="${ c }" stroke-opacity="0.22"/><circle cx="${ r }" cy="${ r }" r="${ r - 5 }" fill="#fff" fill-opacity="0.42" stroke="${ c }" stroke-opacity="0.42"/><circle cx="${ r }" cy="${ r }" r="${ r - 9 }" fill="#fff" fill-opacity="0.90" stroke="${ c }" stroke-width="1.5"/>${ label( c ) }`;
			break;
		case 'stacked': {
			// Offset translucent discs communicate that this marker represents a
			// stack of locations, while the solid front disc carries the count.
			const br = r - 7;
			body = `<circle cx="${ r - 4 }" cy="${ r - 4 }" r="${ br }" fill="${ c }" fill-opacity="0.20" stroke="#fff" stroke-opacity="0.75"/><circle cx="${ r + 4 }" cy="${ r - 2 }" r="${ br }" fill="${ c }" fill-opacity="0.42" stroke="#fff" stroke-opacity="0.85"/><circle cx="${ r }" cy="${ r + 4 }" r="${ br }" fill="${ c }" stroke="#fff" stroke-width="1.5"/>${ label( '#fff', r + 4 ) }`;
			break;
		}
		case 'pin': {
			// Teardrop pin: rounded body + a downward point. Count sits in the body.
			const cy = r - 2;
			const br = r - 4;
			body = `<path d="M ${ r } ${ s - 1 } C ${ r - br * 0.9 } ${ cy + br * 0.7 } ${ r - br } ${ cy + br * 0.2 } ${ r - br } ${ cy } a ${ br } ${ br } 0 1 1 ${ br * 2 } 0 C ${ r + br } ${ cy + br * 0.2 } ${ r + br * 0.9 } ${ cy + br * 0.7 } ${ r } ${ s - 1 } Z" fill="${ c }"/>${ label( '#fff', cy ) }`;
			break;
		}
		case 'soft':
		default:
			body = `<circle cx="${ r }" cy="${ r }" r="${ r }" fill="${ c }" fill-opacity="0.28"/><circle cx="${ r }" cy="${ r }" r="${ r - 6 }" fill="${ c }"/>${ label( '#fff' ) }`;
	}

	return `<svg xmlns="http://www.w3.org/2000/svg" width="${ s }" height="${ s }" viewBox="0 0 ${ s } ${ s }">${ body }</svg>`;
};

/** Same SVG as a data-URI (for an <img>/Google marker icon url). */
export const clusterSvgDataUri = ( style, color, count ) =>
	`data:image/svg+xml,${ encodeURIComponent( clusterSvg( style, color, count ) ) }`;
