import React, { CSSProperties } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { escapeHtml, escapeAttr, cssValue } from '../../utils/escape';

interface Testimonial {
  quote: string;
  name: string;
  title: string;
  rating: number;
}

interface TestimonialsProps {
  testimonials?: Testimonial[];
  layout?: 'grid' | 'single';
  columns?: number;
  style?: CSSProperties;
  cardBg?: string;
  starColor?: string;
  anchorId?: string;
  animation?: string;
  animationDelay?: string;
  hideOnDesktop?: boolean;
  hideOnTablet?: boolean;
  hideOnMobile?: boolean;
}

const defaultTestimonials: Testimonial[] = [
  { quote: 'This product has completely transformed our workflow. Highly recommended for any team.', name: 'Sarah Johnson', title: 'Marketing Director', rating: 5 },
  { quote: 'Outstanding support and an incredibly intuitive interface. We saw results from day one.', name: 'Michael Chen', title: 'CTO, TechStart', rating: 5 },
  { quote: 'The best investment we have made this year. Simple, powerful, and reliable.', name: 'Emily Rodriguez', title: 'Founder, DesignLab', rating: 4 },
];

function renderStars(count: number, color: string): React.ReactNode {
  return (
    <div style={{ display: 'flex', gap: '2px', justifyContent: 'center', marginBottom: '12px' }}>
      {[1, 2, 3, 4, 5].map((i) => (
        <i
          key={i}
          className={`fa ${i <= count ? 'fa-star' : 'fa-star-o'}`}
          style={{ color, fontSize: '14px' }}
        />
      ))}
    </div>
  );
}

function starsHtml(count: number, color: string): string {
  // `count` is `Testimonial.rating`, typed `number` but arrives unchecked via
  // AI update_props / deserialized state -- coerce to a real number before
  // it's interpolated into the aria-label attribute below (both the loop
  // comparison and the escapeAttr(String(...)) call are safe against any
  // non-numeric/garbage value).
  const safeCount = Number(count) || 0;
  const stars = [1, 2, 3, 4, 5].map((i) =>
    `<i class="fa ${i <= safeCount ? 'fa-star' : 'fa-star-o'}" style="color:${color};font-size:14px" aria-hidden="true"></i>`
  ).join('');
  return `<div style="display:flex;gap:2px;justify-content:center;margin-bottom:12px" role="img" aria-label="${escapeAttr(`Rating: ${safeCount} out of 5`)}">${stars}</div>`;
}

export const Testimonials: UserComponent<TestimonialsProps> = ({
  testimonials = defaultTestimonials,
  layout = 'grid',
  columns = 3,
  style = {},
  cardBg = '#f8fafc',
  starColor = '#f59e0b',
  anchorId,
}) => {
  const {
    connectors: { connect, drag },
    selected,
  } = useNode((node) => ({
    selected: node.events.selected,
  }));

  const cardStyle: CSSProperties = {
    backgroundColor: cardBg,
    borderRadius: '12px',
    padding: '32px 24px',
    textAlign: 'center',
    border: '1px solid #e2e8f0',
  };

  const renderCard = (t: Testimonial, i: number) => (
    <div key={i} style={cardStyle}>
      {renderStars(t.rating, starColor)}
      <p style={{ fontSize: '15px', color: '#374151', lineHeight: '1.7', marginBottom: '16px', fontStyle: 'italic', fontFamily: 'Inter, sans-serif' }}>
        &ldquo;{t.quote}&rdquo;
      </p>
      <div style={{ fontWeight: '600', fontSize: '14px', color: '#18181b', fontFamily: 'Inter, sans-serif' }}>{t.name}</div>
      <div style={{ fontSize: '13px', color: '#64748b', fontFamily: 'Inter, sans-serif' }}>{t.title}</div>
    </div>
  );

  const items = testimonials.length > 0 ? testimonials : defaultTestimonials;

  return (
    <section
      ref={(ref: HTMLElement | null): void => { if (ref) connect(drag(ref)); }}
      id={anchorId || undefined}
      style={{
        padding: '80px 20px',
        backgroundColor: '#ffffff',
        outline: selected ? '2px solid #3b82f6' : 'none',
        ...style,
      }}
    >
      <div style={{ maxWidth: '1100px', margin: '0 auto' }}>
        {layout === 'grid' ? (
          <div style={{ display: 'grid', gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: '24px' }}>
            {items.map((t, i) => renderCard(t, i))}
          </div>
        ) : (
          // Static single testimonial (parity with the static toHtml export --
          // no carousel controls, since the published site has no JS for this
          // component). Always shows the first testimonial.
          <div style={{ maxWidth: '600px', margin: '0 auto', position: 'relative' }}>
            {renderCard(items[0], 0)}
          </div>
        )}
      </div>
    </section>
  );
};

/* ---------- Craft config ---------- */

Testimonials.craft = {
  displayName: 'Testimonials',
  props: {
    testimonials: defaultTestimonials,
    layout: 'grid',
    columns: 3,
    style: { backgroundColor: '#ffffff' },
    cardBg: '#f8fafc',
    starColor: '#f59e0b',
    anchorId: '',
    animation: '',
    animationDelay: '',
    hideOnDesktop: false,
    hideOnTablet: false,
    hideOnMobile: false,
  },
  rules: {
    canDrag: () => true,
    canMoveIn: () => false,
    canMoveOut: () => true,
  },
};

/* ---------- HTML export ---------- */

(Testimonials as any).toHtml = (props: TestimonialsProps, _childrenHtml: string) => {
  const {
    testimonials = defaultTestimonials,
    layout = 'grid',
    style = {},
  } = props;
  // Number() coercion: `columns` is a raw string-interpolation sink into the
  // grid style attribute below (repeat(${columns},1fr)); Number() of
  // anything non-numeric collapses safely to NaN instead of breaking out.
  const columns = Number(props.columns) || 3;
  // Sanitized -- raw string-interpolation sinks below (cardCss / starsHtml
  // style attributes).
  const cardBg = cssValue(props.cardBg) || '#f8fafc';
  const starColor = cssValue(props.starColor) || '#f59e0b';

  const items = testimonials.length > 0 ? testimonials : defaultTestimonials;

  const sectionStyle = cssPropsToString({
    padding: '80px 20px',
    backgroundColor: '#ffffff',
    ...style,
  });
  const idAttr = props.anchorId ? ` id="${escapeAttr(props.anchorId)}"` : '';

  const cardCss = `background-color:${cardBg};border-radius:12px;padding:32px 24px;text-align:center;border:1px solid #e2e8f0`;

  const cardHtml = (t: Testimonial): string => `<div style="${cardCss}">
      ${starsHtml(t.rating, starColor)}
      <p style="font-size:15px;color:#374151;line-height:1.7;margin-bottom:16px;font-style:italic;font-family:Inter,sans-serif">&ldquo;${escapeHtml(t.quote)}&rdquo;</p>
      <div style="font-weight:600;font-size:14px;color:#18181b;font-family:Inter,sans-serif">${escapeHtml(t.name)}</div>
      <div style="font-size:13px;color:#64748b;font-family:Inter,sans-serif">${escapeHtml(t.title)}</div>
    </div>`;

  if (layout === 'single') {
    // Static parity with the editor's single-layout render: exactly ONE
    // testimonial card (the first), no carousel controls -- the published
    // export has no JS for this component.
    return {
      html: `<section${idAttr}${sectionStyle ? ` style="${sectionStyle}"` : ''}>
  <div style="max-width:600px;margin:0 auto">
    ${cardHtml(items[0])}
  </div>
</section>`,
    };
  }

  const cards = items.map(cardHtml).join('\n    ');

  return {
    html: `<section${idAttr}${sectionStyle ? ` style="${sectionStyle}"` : ''}>
  <div style="max-width:1100px;margin:0 auto;display:grid;grid-template-columns:repeat(${columns},1fr);gap:24px">
    ${cards}
  </div>
</section>`,
  };
};
