import { useMemo } from 'react';
import { OrbitControls, Grid, Environment, Text } from '@react-three/drei';
import * as THREE from 'three';
import SceneCanvas from '../SceneCanvas';
import FallbackDiagram from '../FallbackDiagram';

export interface Bar3DInput {
  /** Tipo de seção */
  barType: 'flat' | 'circular';
  /** Forma (apenas flat): 'placa' | 'l' | 't' | 'i' | 'rectangle' */
  section?: 'placa' | 'l' | 't' | 'i' | 'rectangle';
  /** Diâmetro (apenas circular, m) */
  diameter?: number;
  /** Largura da seção (flat, m) */
  width?: number;
  /** Comprimento da barra (m) */
  length: number;
  /** Ângulo de incidência (graus) — 0° = face plana contra o vento */
  alpha: number;
  /** Força Fx (kN) */
  fxKN: number;
  /** Força Fy (kN) */
  fyKN: number;
  /** Coeficiente Cx (apenas visualização) */
  cx: number;
}

function BarModel({
  barType,
  section,
  diameter,
  width,
  length,
  alpha,
  cx,
}: Bar3DInput) {
  const barRadius = barType === 'circular' ? (diameter ?? 0.05) / 2 : Math.min(width ?? 0.1, 0.08) / 2;
  const barThickness = barType === 'circular' ? barRadius : barRadius * 0.5;

  const barColor = useMemo(() => {
    const intensity = Math.min(1, Math.abs(cx) / 2.5);
    const hue = 215 - intensity * 215;
    return new THREE.Color(`hsl(${hue}, ${65 + intensity * 25}%, ${45 - intensity * 10}%)`);
  }, [cx]);

  // Ação do vento deve rotacionar a barra em seu próprio eixo longitudinal (roll).
  // O eixo longitudinal na nossa geometria é o X.
  const alphaRad = (alpha * Math.PI) / 180;
  // A rotação deve ser negativa para que o vento (vindo de -Z) atinja as faces corretas conforme a NBR.
  const barRotationX = -alphaRad; 

  return (
    <group>
      {/* Seta do Vento (Fixa Globalmente, soprando em +Z) */}
      <group position={[0, 0, barRadius + 0.5]}>
        <mesh position={[0, 0, 0.4]} rotation={[Math.PI / 2, 0, 0]}>
          <cylinderGeometry args={[0.02, 0.02, 0.8, 8]} />
          <meshStandardMaterial color="#22c55e" />
        </mesh>
        <mesh position={[0, 0, 0]} rotation={[-Math.PI / 2, 0, 0]}>
          <coneGeometry args={[0.08, 0.2, 8]} />
          <meshStandardMaterial color="#22c55e" />
        </mesh>
      </group>
      
      {/* Barra Rotacionada (Roll) */}
      <group rotation={[barRotationX, 0, 0]}>
        {/* Eixo principal da barra ao longo do eixo X */}
        {barType === 'circular' ? (
          <mesh position={[0, 0, 0]} rotation={[0, 0, Math.PI / 2]} castShadow>
            <cylinderGeometry args={[barRadius, barRadius, length, 16]} />
            <meshStandardMaterial color={barColor} roughness={0.4} metalness={0.3} />
          </mesh>
        ) : (
          <SectionShape section={section ?? 'placa'} width={width ?? 0.1} length={length} color={barColor} thickness={barThickness} />
        )}

        {/* Eixos de referência locais da barra */}
        <axesHelper args={[length * 0.5]} />
      </group>

      {/* Marca de origem */}
      <mesh position={[0, 0, 0]} castShadow>
        <sphereGeometry args={[0.06, 12, 12]} />
        <meshStandardMaterial color="#fbbf24" emissive="#fbbf24" emissiveIntensity={0.4} />
      </mesh>
      <Text
        position={[0, -barRadius * 2 - 0.4, 0]}
        fontSize={0.3}
        color="#1e40af"
        anchorX="center"
        anchorY="top"
      >
        α={alpha}° | Cx={cx.toFixed(2)}
      </Text>
    </group>
  );
}

function SectionShape({
  section,
  width,
  length,
  color,
  thickness,
}: {
  section: 'placa' | 'l' | 't' | 'i' | 'rectangle';
  width: number;
  length: number;
  color: THREE.Color;
  thickness: number;
}) {
  switch (section) {
    case 'placa':
      return (
        <mesh position={[0, 0, 0]} castShadow>
          <boxGeometry args={[length, width, thickness]} />
          <meshStandardMaterial color={color} roughness={0.5} />
        </mesh>
      );
    case 'l':
      return (
        <group>
          <mesh position={[0, width / 2 - thickness / 2, width / 2 - thickness / 2]} castShadow>
            <boxGeometry args={[length, thickness, width]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
          <mesh position={[0, 0, 0]} castShadow>
            <boxGeometry args={[length, width, thickness]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
        </group>
      );
    case 't':
      return (
        <group>
          <mesh position={[0, width / 2 - thickness / 2, 0]} castShadow>
            <boxGeometry args={[length, thickness, width]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
          <mesh position={[0, 0, 0]} castShadow>
            <boxGeometry args={[length, width, thickness]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
        </group>
      );
    case 'i':
      return (
        <group>
          <mesh position={[0, width / 2 - thickness / 2, 0]} castShadow>
            <boxGeometry args={[length, thickness, width]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
          <mesh position={[0, 0, 0]} castShadow>
            <boxGeometry args={[length, width - thickness, thickness]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
          <mesh position={[0, -width / 2 + thickness / 2, 0]} castShadow>
            <boxGeometry args={[length, thickness, width]} />
            <meshStandardMaterial color={color} roughness={0.5} />
          </mesh>
        </group>
      );
    case 'rectangle':
      return (
        <mesh position={[0, 0, 0]} castShadow>
          <boxGeometry args={[length, width, thickness]} />
          <meshStandardMaterial color={color} roughness={0.5} />
        </mesh>
      );
  }
}

export default function Bar3DViewer(input: Bar3DInput) {
  const { length, width, diameter } = input;
  const size = Math.max(length * 0.6, (width ?? diameter ?? 0.1) * 8);

  const fallback = (
    <FallbackDiagram
      type="bar"
      props={input}
    />
  );

  return (
    <SceneCanvas
      shadows
      gl={{ preserveDrawingBuffer: true, antialias: true }}
      camera={{ position: [size, size * 0.6, size], fov: 45 }}
      fallback={fallback}
    >
      <ambientLight intensity={0.6} />
      <directionalLight position={[size, size, size]} intensity={1.2} castShadow shadow-mapSize-width={1024} shadow-mapSize-height={1024} />
      <BarModel {...input} />
      <Grid infiniteGrid fadeDistance={size * 2} sectionColor="#94a3b8" cellColor="#cbd5e1" position={[0, -size * 0.3, 0]} />
      <OrbitControls makeDefault minPolarAngle={0} maxPolarAngle={Math.PI - 0.05} />
      <Environment preset="city" />
    </SceneCanvas>
  );
}