/*
  FrameBuilder - Renderer 1080x1920
  Uso:
    await FBRenderer.render(canvas, eventConfig, assetsMap, {
      name: 'João',
      photoFile: File|null,
      photoImage: HTMLImageElement|null
    });
*/

const FBRenderer = (() => {
  const W = 1080;
  const H = 1920;

  function clamp(n, a, b){ return Math.max(a, Math.min(b, n)); }

  function hexToRgba(hex, opacity){
    if (!hex) return `rgba(0,0,0,${opacity})`;
    let h = hex.replace('#','').trim();
    if (h.length===3) h = h.split('').map(ch=>ch+ch).join('');
    const r = parseInt(h.substring(0,2),16);
    const g = parseInt(h.substring(2,4),16);
    const b = parseInt(h.substring(4,6),16);
    return `rgba(${r},${g},${b},${clamp(opacity,0,1)})`;
  }

  function loadImage(url){
    return new Promise((resolve, reject)=>{
      const img = new Image();
      img.crossOrigin = 'anonymous';
      img.onload = ()=>resolve(img);
      img.onerror = ()=>reject(new Error('Falha ao carregar imagem'));
      img.src = url;
    });
  }

  async function fileToImage(file){
    return new Promise((resolve, reject)=>{
      const r = new FileReader();
      r.onload = () => {
        const img = new Image();
        img.onload = ()=>resolve(img);
        img.onerror = ()=>reject(new Error('Imagem inválida'));
        img.src = String(r.result);
      };
      r.onerror = ()=>reject(new Error('Falha ao ler arquivo'));
      r.readAsDataURL(file);
    });
  }

  function drawImageCover(ctx, img, x, y, w, h){
    const iw = img.naturalWidth || img.width;
    const ih = img.naturalHeight || img.height;
    const ir = iw/ih;
    const r = w/h;
    let sw, sh, sx, sy;
    if (ir > r) {
      sh = ih;
      sw = ih * r;
      sx = (iw - sw)/2;
      sy = 0;
    } else {
      sw = iw;
      sh = iw / r;
      sx = 0;
      sy = (ih - sh)/2;
    }
    ctx.drawImage(img, sx, sy, sw, sh, x, y, w, h);
  }

  function drawImageContain(ctx, img, x, y, w, h){
    const iw = img.naturalWidth || img.width;
    const ih = img.naturalHeight || img.height;
    const scale = Math.min(w/iw, h/ih);
    const dw = iw*scale;
    const dh = ih*scale;
    const dx = x + (w - dw)/2;
    const dy = y + (h - dh)/2;
    ctx.drawImage(img, dx, dy, dw, dh);
  }

  function drawRotated(ctx, x, y, rotateDeg, drawFn){
    const rad = (rotateDeg || 0) * Math.PI / 180;
    ctx.save();
    ctx.translate(x, y);
    ctx.rotate(rad);
    drawFn();
    ctx.restore();
  }

  async function render(canvas, config, assetsMap, data){
    if (!canvas) throw new Error('Canvas não encontrado');
    canvas.width = W;
    canvas.height = H;
    const ctx = canvas.getContext('2d');

    // fundo default
    ctx.clearRect(0,0,W,H);
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0,0,W,H);

    const layers = (config && config.layers) ? config.layers : (config || {});

    // -------- Background --------
    const bg = layers.background || {};
    if (bg.type === 'solid') {
      ctx.fillStyle = (bg.solid && bg.solid.color) ? bg.solid.color : '#ffffff';
      ctx.fillRect(0,0,W,H);
    }
    if (bg.type === 'gradient') {
      const g = bg.gradient || {};
      const angle = (g.angle ?? 90) * Math.PI / 180;
      const x1 = W/2 + Math.cos(angle) * W/2;
      const y1 = H/2 + Math.sin(angle) * H/2;
      const x0 = W - x1;
      const y0 = H - y1;
      const grad = ctx.createLinearGradient(x0,y0,x1,y1);
      grad.addColorStop(0, g.color_a || '#0F172A');
      grad.addColorStop(1, g.color_b || '#2563EB');
      ctx.fillStyle = grad;
      ctx.fillRect(0,0,W,H);
    }
    if (bg.type === 'image' && bg.image && bg.image.asset_id) {
      const url = assetsMap?.[String(bg.image.asset_id)];
      if (url) {
        try{
          const img = await loadImage(url);
          const zoom = bg.image.zoom ?? 1.0;
          const ox = bg.image.x ?? 0;
          const oy = bg.image.y ?? 0;
          const fit = bg.image.fit || 'cover';
          const rot = bg.image.rotate || 0;

          // desenha numa área maior e depois recorta
          ctx.save();
          drawRotated(ctx, W/2, H/2, rot, ()=>{
            // após translate/rotate, desenhar centralizado
            const dw = W * zoom;
            const dh = H * zoom;
            const dx = -dw/2 + ox;
            const dy = -dh/2 + oy;
            // fit cover/contain: usamos proporção da imagem em relação ao canvas
            if (fit === 'contain') {
              // contain dentro do retângulo dw/dh
              const iw = img.naturalWidth || img.width;
              const ih = img.naturalHeight || img.height;
              const scale = Math.min(dw/iw, dh/ih);
              const rw = iw*scale;
              const rh = ih*scale;
              const rx = dx + (dw - rw)/2;
              const ry = dy + (dh - rh)/2;
              ctx.drawImage(img, rx, ry, rw, rh);
            } else {
              // cover: desenha e cobre toda área dw/dh
              drawImageCover(ctx, img, dx, dy, dw, dh);
            }
          });
          ctx.restore();
        } catch(e){ /* ignora */ }
      }
    }

    // -------- Title --------
    const title = layers.title || {};
    if (title.type === 'text' && title.text) {
      const t = title.text;
      const size = t.font_size ?? 72;
      const weight = t.font_weight ?? 700;
      const family = t.font_family || 'Arial';
      ctx.save();
      ctx.translate(t.x ?? W/2, t.y ?? 180);
      ctx.rotate(((t.rotate||0)*Math.PI)/180);
      ctx.font = `${weight} ${size}px ${family}`;
      ctx.fillStyle = t.color || '#ffffff';
      ctx.textAlign = (t.align || 'center');
      ctx.textBaseline = 'middle';
      ctx.fillText(t.value || '', 0, 0);
      ctx.restore();
    }
    if (title.type === 'image' && title.image && title.image.asset_id) {
      const url = assetsMap?.[String(title.image.asset_id)];
      if (url) {
        try{
          const img = await loadImage(url);
          const i = title.image;
          drawRotated(ctx, (i.x ?? 0) + (i.w ?? 100)/2, (i.y ?? 0) + (i.h ?? 100)/2, i.rotate || 0, ()=>{
            ctx.drawImage(img, -(i.w??100)/2, -(i.h??100)/2, (i.w??100), (i.h??100));
          });
        } catch(e){ /* ignora */ }
      }
    }

    // -------- Photo slot --------
    let photoImg = data?.photoImage || null;
    if (!photoImg && data?.photoFile) {
      try{ photoImg = await fileToImage(data.photoFile); } catch(e){}
    }

    const slot = layers.photo_slot || {};
    const cx = slot.x ?? W/2;
    const cy = slot.y ?? 840;
    const radius = slot.radius ?? 340;
    const border = slot.border || {enabled:true, color:'#ffffff', width:10};

    // placeholder simples se não houver foto
    if (!photoImg) {
      ctx.save();
      ctx.fillStyle = 'rgba(255,255,255,.7)';
      ctx.beginPath();
      ctx.arc(cx, cy, radius, 0, Math.PI*2);
      ctx.fill();
      ctx.fillStyle = 'rgba(0,0,0,.45)';
      ctx.font = '700 56px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText('FOTO', cx, cy);
      ctx.restore();
    } else {
      ctx.save();
      ctx.beginPath();
      ctx.arc(cx, cy, radius, 0, Math.PI*2);
      ctx.clip();
      drawImageCover(ctx, photoImg, cx-radius, cy-radius, radius*2, radius*2);
      ctx.restore();
    }

    if (border && border.enabled) {
      ctx.save();
      ctx.lineWidth = border.width ?? 10;
      ctx.strokeStyle = border.color || '#ffffff';
      ctx.beginPath();
      ctx.arc(cx, cy, radius + (ctx.lineWidth/2), 0, Math.PI*2);
      ctx.stroke();
      ctx.restore();
    }

    // -------- Name bar --------
    const bar = layers.name_bar || {};
    const bx = bar.x ?? 120;
    const by = bar.y ?? 1320;
    const bw = bar.w ?? 840;
    const bh = bar.h ?? 170;
    const br = bar.border_radius ?? 18;
    const fill = bar.fill || {color:'#ffffff', opacity:0.92};

    function roundRectPath(ctx, x, y, w, h, r){
      const rr = clamp(r, 0, Math.min(w,h)/2);
      ctx.beginPath();
      ctx.moveTo(x+rr,y);
      ctx.arcTo(x+w,y,x+w,y+h,rr);
      ctx.arcTo(x+w,y+h,x,y+h,rr);
      ctx.arcTo(x,y+h,x,y,rr);
      ctx.arcTo(x,y,x+w,y,rr);
      ctx.closePath();
    }

    ctx.save();
    if (bar.shadow && bar.shadow.enabled) {
      ctx.shadowColor = `rgba(0,0,0,${bar.shadow.opacity ?? 0.25})`;
      ctx.shadowBlur = bar.shadow.blur ?? 12;
      ctx.shadowOffsetX = bar.shadow.x ?? 0;
      ctx.shadowOffsetY = bar.shadow.y ?? 6;
    }
    roundRectPath(ctx, bx, by, bw, bh, br);
    ctx.fillStyle = hexToRgba(fill.color || '#ffffff', fill.opacity ?? 0.92);
    ctx.fill();
    ctx.shadowColor = 'transparent';

    if (bar.stroke && bar.stroke.enabled) {
      ctx.lineWidth = bar.stroke.width ?? 2;
      ctx.strokeStyle = bar.stroke.color || '#000000';
      roundRectPath(ctx, bx, by, bw, bh, br);
      ctx.stroke();
    }
    ctx.restore();

    // -------- Name text --------
    const nameText = layers.name_text || {};
    const userName = (data?.name || 'NOME DO CLIENTE').trim();
    ctx.save();
    ctx.font = `${nameText.font_weight ?? 800} ${(nameText.font_size ?? 64)}px ${(nameText.font_family || 'Arial')}`;
    ctx.fillStyle = nameText.color || '#111111';
    ctx.textAlign = nameText.align || 'center';
    ctx.textBaseline = 'middle';
    const nx = (nameText.x ?? (bx + (bw/2)));
    const ny = (nameText.y ?? (by + (bh/2)));
    ctx.fillText(userName, nx, ny);
    ctx.restore();

    // -------- Subtitle --------
    const sub = layers.subtitle_text || {};
    const subtitleValue = sub.value || '';
    if (subtitleValue) {
      ctx.save();
      ctx.font = `${sub.font_weight ?? 600} ${(sub.font_size ?? 36)}px ${(sub.font_family || 'Arial')}`;
      ctx.fillStyle = sub.color || '#ffffff';
      ctx.textAlign = sub.align || 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(subtitleValue, sub.x ?? W/2, sub.y ?? 1530);
      ctx.restore();
    }

    // -------- Footer --------
    const footer = layers.footer || {};
    if (footer.type === 'text' && footer.text) {
      const f = footer.text;
      const align = footer.align || 'center';
      const pad = f.padding_x ?? 80;
      let fx = W/2;
      if (align === 'left') fx = pad;
      if (align === 'right') fx = W - pad;
      ctx.save();
      ctx.font = `${f.font_weight ?? 600} ${(f.font_size ?? 28)}px ${(f.font_family || 'Arial')}`;
      ctx.fillStyle = f.color || '#ffffff';
      ctx.textAlign = align;
      ctx.textBaseline = 'middle';
      ctx.fillText(f.value || '', fx, f.y ?? 1860);
      ctx.restore();
    }

    if (footer.type === 'image' && footer.image && footer.image.asset_id) {
      const url = assetsMap?.[String(footer.image.asset_id)];
      if (url) {
        try{
          const img = await loadImage(url);
          const f = footer.image;
          const align = footer.align || 'center';
          const pad = f.padding_x ?? 80;
          const w = f.w ?? 240;
          const h = f.h ?? 80;
          let x = (W - w)/2;
          if (align === 'left') x = pad;
          if (align === 'right') x = W - pad - w;
          ctx.drawImage(img, x, f.y ?? 1830, w, h);
        } catch(e){ /* ignora */ }
      }
    }

    return canvas;
  }

  function canvasToPngDataUrl(canvas){
    return canvas.toDataURL('image/png');
  }

  return { render, canvasToPngDataUrl, W, H };
})();
