/**
 * Entity Property Inspector module for dwg-dxf-viewer-sample.
 * Formats CAD entity properties and renders detailed property UI panels.
 */

export interface FormattedProperties {
  id: string;
  type: string;
  handle: string;
  layer: string;
  general: [string, string][];
  geometry: [string, string][];
}

const f2 = (v: any): string => (typeof v === 'number' ? v.toFixed(2) : (v ?? '-'));
const f3 = (v: any): string => (typeof v === 'number' ? v.toFixed(3) : (v ?? '-'));
const deg = (r: any): string => {
  if (typeof r !== 'number') return '-';
  let d = (r * 180) / Math.PI;
  while (d < 0) d += 360;
  while (d >= 360) d -= 360;
  return d.toFixed(1) + '°';
};

const pt = (p: any): string => {
  if (!p) return '-';
  const x = typeof p.x === 'number' ? f2(p.x) : '0.00';
  const y = typeof p.y === 'number' ? f2(p.y) : '0.00';
  const z = typeof p.z === 'number' && Math.abs(p.z) > 1e-6 ? `, ${f2(p.z)}` : '';
  return `${x}, ${y}${z}`;
};

function formatColor(colorVal: any): string {
  if (colorVal == null) return 'BYLAYER';
  if (typeof colorVal === 'number') {
    if (colorVal === 256) return 'BYLAYER (256)';
    if (colorVal === 0) return 'BYBLOCK (0)';
    return `ACI ${colorVal}`;
  }
  return String(colorVal);
}

export function formatEntityProperties(entity: any): FormattedProperties {
  if (!entity) {
    return { id: '', type: '', handle: '', layer: '', general: [], geometry: [] };
  }

  const d = entity.data || entity;
  const type = (entity.type || entity.typeName || 'ENTITY').toUpperCase();
  const handle = entity.handle?.value ?? entity.handle ?? '-';
  const layer = entity.layer ?? entity.layerName ?? '0';
  const color = formatColor(entity.color ?? d.color);
  const linetype = entity.lineType ?? entity.linetype ?? d.lineType ?? 'BYLAYER';

  const general: [string, string][] = [
    ['유형 (Type)', type],
    ['핸들 (Handle)', String(handle)],
    ['레이어 (Layer)', String(layer)],
    ['색상 (Color)', color],
    ['선종류 (Linetype)', String(linetype)],
  ];

  const geometry: [string, string][] = [];

  switch (type) {
    case 'LINE': {
      if (d.start && d.end) {
        const dx = d.end.x - d.start.x;
        const dy = d.end.y - d.start.y;
        const dz = (d.end.z || 0) - (d.start.z || 0);
        const len = Math.hypot(dx, dy, dz);
        const angle = Math.atan2(dy, dx);

        geometry.push(['시작점 (Start)', pt(d.start)]);
        geometry.push(['끝점 (End)', pt(d.end)]);
        geometry.push(['증분 (ΔX, ΔY)', `${f2(dx)}, ${f2(dy)}`]);
        geometry.push(['길이 (Length)', f3(len)]);
        geometry.push(['각도 (Angle)', deg(angle)]);
      }
      break;
    }

    case 'CIRCLE': {
      if (d.center && d.radius != null) {
        const r = d.radius;
        const diameter = r * 2;
        const circumference = 2 * Math.PI * r;
        const area = Math.PI * r * r;

        geometry.push(['중심점 (Center)', pt(d.center)]);
        geometry.push(['반지름 (Radius)', f3(r)]);
        geometry.push(['지름 (Diameter)', f3(diameter)]);
        geometry.push(['둘레 (Circumference)', f3(circumference)]);
        geometry.push(['넓이 (Area)', f3(area)]);
      }
      break;
    }

    case 'ARC': {
      if (d.center && d.radius != null) {
        const r = d.radius;
        const sa = d.startAngle ?? 0;
        const ea = d.endAngle ?? Math.PI * 2;
        let sweep = ea - sa;
        while (sweep < 0) sweep += Math.PI * 2;
        const arcLen = sweep * r;

        geometry.push(['중심점 (Center)', pt(d.center)]);
        geometry.push(['반지름 (Radius)', f3(r)]);
        geometry.push(['시작각 (Start Angle)', deg(sa)]);
        geometry.push(['끝각 (End Angle)', deg(ea)]);
        geometry.push(['중심각 (Sweep Angle)', deg(sweep)]);
        geometry.push(['호 길이 (Arc Length)', f3(arcLen)]);
      }
      break;
    }

    case 'LWPOLYLINE':
    case 'POLYLINE': {
      const rawPts = d.points ?? d.vertices ?? [];
      const isClosed = !!(d.closed || (d.flags & 1));
      let totalLen = 0;

      for (let i = 0; i < rawPts.length - (isClosed ? 0 : 1); i++) {
        const p1 = rawPts[i];
        const p2 = rawPts[(i + 1) % rawPts.length];
        if (p1 && p2) {
          totalLen += Math.hypot(p2.x - p1.x, p2.y - p1.y);
        }
      }

      geometry.push(['정점 개수 (Vertices)', String(rawPts.length)]);
      geometry.push(['닫힘 여부 (Closed)', isClosed ? '예 (Closed)' : '아니오 (Open)']);
      geometry.push(['총 길이 (Total Length)', f3(totalLen)]);

      if (isClosed && rawPts.length >= 3) {
        let shoelace = 0;
        for (let i = 0; i < rawPts.length; i++) {
          const p1 = rawPts[i];
          const p2 = rawPts[(i + 1) % rawPts.length];
          shoelace += p1.x * p2.y - p2.x * p1.y;
        }
        geometry.push(['면적 (Area)', f3(Math.abs(shoelace) / 2)]);
      }

      if (rawPts.length > 0) {
        const sampleCount = Math.min(rawPts.length, 4);
        for (let i = 0; i < sampleCount; i++) {
          geometry.push([`정점 P${i + 1}`, pt(rawPts[i])]);
        }
        if (rawPts.length > sampleCount) {
          geometry.push(['...', `외 ${rawPts.length - sampleCount}개 정점`]);
        }
      }
      break;
    }

    case 'TEXT':
    case 'MTEXT':
    case 'ATTRIB': {
      const content = d.text ?? entity.text ?? d.textValue ?? '-';
      const height = d.textHeight ?? d.height ?? entity.textHeight;
      const rot = d.rotationAngle ?? d.rotation ?? 0;
      const pos = d.insertionPoint ?? d.insertionPt ?? d.alignmentPt ?? d.pos;

      geometry.push(['텍스트 내용 (Content)', String(content)]);
      if (height != null) geometry.push(['높이 (Height)', f3(height)]);
      geometry.push(['회전각 (Rotation)', deg(rot)]);
      if (pos) geometry.push(['삽입점 (Position)', pt(pos)]);
      break;
    }

    case 'INSERT': {
      const name = d.name ?? d.blockName ?? entity.name ?? '-';
      const pos = d.insertionPoint ?? d.insertionPt ?? entity.insertionPt;
      const sx = d.xScale ?? d.scale?.x ?? 1;
      const sy = d.yScale ?? d.scale?.y ?? 1;
      const sz = d.zScale ?? d.scale?.z ?? 1;
      const rot = d.rotation ?? 0;

      geometry.push(['블록 이름 (Block)', String(name)]);
      if (pos) geometry.push(['삽입점 (Position)', pt(pos)]);
      geometry.push(['축척 (Scale X,Y,Z)', `${f2(sx)}, ${f2(sy)}, ${f2(sz)}`]);
      geometry.push(['회전각 (Rotation)', deg(rot)]);
      break;
    }

    case 'HATCH': {
      const isSolid = d.solidFill ?? entity.solidFill ?? false;
      const pattern = d.patternName ?? d.name ?? (isSolid ? 'SOLID' : 'HATCH');
      const paths = d.paths ?? entity.paths ?? [];

      geometry.push(['패턴 (Pattern)', String(pattern)]);
      geometry.push(['채우기 유형 (Type)', isSolid ? '단색 채우기 (Solid)' : '패턴 (Pattern)']);
      geometry.push(['경계 루프 수 (Loops)', String(paths.length)]);
      break;
    }

    case 'DIMENSION':
    case 'DIMENSION_LINEAR':
    case 'DIMENSION_ALIGNED':
    case 'DIMENSION_RADIUS':
    case 'DIMENSION_DIAMETER':
    case 'DIMENSION_ANG_3PT':
    case 'DIMENSION_ANG_2LN':
    case 'DIMENSION_ORDINATE': {
      const meas = d.actualMeasurement ?? entity.actualMeasurement;
      const textVal = d.userText || (meas != null ? f3(meas) : '-');
      const midPt = d.textMidPt ?? entity.textMidPt;

      geometry.push(['치수 유형 (Dim Type)', type]);
      if (meas != null) geometry.push(['측정값 (Measurement)', f3(meas)]);
      geometry.push(['표시 텍스트 (Text)', String(textVal)]);
      if (midPt) geometry.push(['텍스트 위치 (Text Mid)', pt(midPt)]);
      break;
    }

    case 'ELLIPSE': {
      if (d.center) {
        geometry.push(['중심점 (Center)', pt(d.center)]);
        if (d.majorAxis) geometry.push(['주축 벡터 (Major Axis)', pt(d.majorAxis)]);
        if (d.axisRatio != null || d.ratio != null) {
          geometry.push(['단축 비율 (Ratio)', f3(d.axisRatio ?? d.ratio)]);
        }
      }
      break;
    }

    default: {
      let count = 0;
      for (const [k, v] of Object.entries(d)) {
        if (typeof v === 'object' || v == null || typeof v === 'function') continue;
        geometry.push([k, String(v)]);
        count++;
        if (count >= 12) break;
      }
    }
  }

  const id = `${type}${handle !== '-' ? ' · #' + handle : ''}`;
  return { id, type, handle: String(handle), layer: String(layer), general, geometry };
}

function escapeHtml(str: string): string {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

export function renderPropertyInspector(
  bodyEl: HTMLElement,
  entity: any,
  options?: { onZoomToSelection?: () => void; zoomBtnEl?: HTMLElement | null }
): void {
  if (!bodyEl) return;

  if (!entity) {
    if (options?.zoomBtnEl) options.zoomBtnEl.style.display = 'none';
    bodyEl.innerHTML = `
      <div style="padding:40px 20px;text-align:center;color:var(--muted);font-size:12px;line-height:1.6">
        <div style="font-size:24px;margin-bottom:8px;opacity:.5">🔍</div>
        도면에서 객체(엔티티)를 클릭하면<br/>상세 속성이 표시됩니다
      </div>`;
    return;
  }

  if (options?.zoomBtnEl) options.zoomBtnEl.style.display = 'inline-flex';

  const prop = formatEntityProperties(entity);

  const renderRows = (rows: [string, string][]) =>
    rows
      .map(
        ([k, v]) => `
      <div style="display:flex;justify-content:space-between;align-items:center;gap:12px;padding:6px 0;border-bottom:1px solid var(--line)">
        <span style="font-size:12px;color:var(--muted);flex-shrink:0">${escapeHtml(k)}</span>
        <span style="font-family:var(--mono);font-size:12px;color:var(--ink);text-align:right;word-break:break-all;user-select:all">${escapeHtml(v)}</span>
      </div>`
      )
      .join('');

  bodyEl.innerHTML = `
    <div style="padding:14px">
      <!-- Entity ID Tag -->
      <div style="display:flex;align-items:center;gap:8px;margin-bottom:14px;background:rgba(63,185,80,.1);border:1px solid rgba(63,185,80,.25);padding:8px 10px;border-radius:6px">
        <span style="width:8px;height:8px;border-radius:50%;background:var(--accent);flex-shrink:0"></span>
        <span style="font-family:var(--mono);font-size:13px;font-weight:700;color:var(--accent)">${escapeHtml(prop.id)}</span>
      </div>

      <!-- General Section -->
      <div style="margin-bottom:14px">
        <div style="font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:6px">
          일반 정보 (General)
        </div>
        ${renderRows(prop.general)}
      </div>

      <!-- Geometry Section -->
      ${
        prop.geometry.length > 0
          ? `
      <div>
        <div style="font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--accent);margin-bottom:6px">
          기하 속성 (Geometry)
        </div>
        ${renderRows(prop.geometry)}
      </div>`
          : ''
      }
    </div>`;
}
