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';
import { WindArrow } from './WindArrow';

export interface Sign3DInput {
  /** Comprimento ℓ (m) */
  length: number;
  /** Altura hₐ (m) */
  height: number;
  /** Distância do solo (m) */
  groundClearance: number;
  /** Ângulo de incidência (graus) */
  alpha: 0 | 50 | 90;
  /** Coeficiente de força Cf */
  cf: number;
  /** Força resultante F (kN) */
  forceKN: number;
  /** Excentricidade e (m) */
  applicationPoint: number;
}

/**
 * Módulo 3D para visualização de Muros e Placas Isoladas.
 */

function SignModel({
  length,
  height,
  groundClearance,
  alpha,
  cf,
  applicationPoint,
}: Sign3DInput) {
  const baseY = groundClearance;
  const topY = baseY + height;
  const halfL = length / 2;

  // Direção da seta no plano XZ (α é o ângulo de incidência do vento relativo à superfície)
  // O ângulo em relação à normal da placa (eixo X) é 90 - α
  const angleToNormalRad = ((90 - alpha) * Math.PI) / 180;
  const arrowDir = useMemo(() => new THREE.Vector3(Math.cos(angleToNormalRad), 0, Math.sin(angleToNormalRad)), [angleToNormalRad]);

  // Posição da seta no plano da placa (inicia no ponto de aplicação com a excentricidade ao longo de Z)
  const arrowStart = useMemo(
    () => new THREE.Vector3(0, baseY + height / 2, applicationPoint),
    [applicationPoint, height, baseY],
  );

  // Cor da placa baseada no Cf (mais vermelho = mais carga)
  const plateColor = useMemo(() => {
    const intensity = Math.min(1, Math.abs(cf) / 2.0);
    const hue = 220 - intensity * 220; // azul → vermelho
    return new THREE.Color(`hsl(${hue}, ${60 + intensity * 30}%, ${50 - intensity * 10}%)`);
  }, [cf]);

  // Pontas de extremidade (placas de extremidade opcionais)
  const endPlates = cf >= 1.3 && cf <= 2.0;

  return (
    <group>
      {/* Placa principal */}
      <mesh position={[0, (baseY + topY) / 2, 0]} castShadow receiveShadow>
        <boxGeometry args={[0.1, height, length]} />
        <meshStandardMaterial color={plateColor} opacity={0.8} transparent roughness={0.4} side={THREE.DoubleSide} />
      </mesh>

      {/* Placas de extremidade (retornos aerodinâmicos nas pontas) */}
      {endPlates && (
        <>
          <mesh position={[0, (baseY + topY) / 2, halfL]} castShadow>
            <boxGeometry args={[0.3, height * 0.95, 0.04]} />
            <meshStandardMaterial color="#64748b" opacity={0.6} transparent side={THREE.DoubleSide} />
          </mesh>
          <mesh position={[0, (baseY + topY) / 2, -halfL]} castShadow>
            <boxGeometry args={[0.3, height * 0.95, 0.04]} />
            <meshStandardMaterial color="#64748b" opacity={0.6} transparent side={THREE.DoubleSide} />
          </mesh>
        </>
      )}

      {/* Linha do solo (base translúcida) */}
      <mesh position={[0, 0, 0]} rotation={[-Math.PI / 2, 0, 0]} receiveShadow>
        <planeGeometry args={[length * 1.5, length * 1.5]} />
        <meshStandardMaterial color="#94a3b8" opacity={0.15} transparent />
      </mesh>

      {/* Eixo horizontal de referência de direção do vento */}
      <mesh position={[0, 0.005, 0]} rotation={[-Math.PI / 2, 0, 0]}>
        <planeGeometry args={[length * 1.5, 0.03]} />
        <meshStandardMaterial color="#475569" opacity={0.5} transparent />
      </mesh>

      {/* Marca da excentricidade (Ponto de Aplicação da Resultante) */}
      <mesh position={[0, (baseY + topY) / 2, applicationPoint]} castShadow>
        <sphereGeometry args={[0.08, 16, 16]} />
        <meshStandardMaterial color="#fbbf24" emissive="#fbbf24" emissiveIntensity={0.6} />
      </mesh>
      
      {/* Rótulo explicativo para o ponto de aplicação */}
      <Text
        position={[0.2, (baseY + topY) / 2, applicationPoint]}
        rotation={[0, Math.PI / 2, 0]}
        fontSize={0.15}
        color="#d97706"
        anchorX="left"
        anchorY="middle"
      >
        Resultante (e = {applicationPoint.toFixed(2)}m)
      </Text>

      {/* Vetor de vento (Seta verde/azul batendo no elemento) */}
      <WindArrow
        target={arrowStart}
        direction={arrowDir}
      />

      {/* === LINHAS DE COTA (CAD-Style Dimensions) === */}
      {/* Cota de Altura (h) */}
      <group position={[0, 0, -halfL - 0.4]}>
        {/* Linha vertical */}
        <mesh position={[0, (baseY + topY) / 2, 0]}>
          <boxGeometry args={[0.015, height, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        {/* Traço superior */}
        <mesh position={[0, topY, 0]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        {/* Traço inferior */}
        <mesh position={[0, baseY, 0]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        {/* Texto da altura */}
        <Text
          position={[-0.15, (baseY + topY) / 2, 0]}
          rotation={[0, -Math.PI / 2, 0]}
          fontSize={0.25}
          color="#475569"
          anchorX="center"
          anchorY="middle"
        >
          h = {height}m
        </Text>
      </group>

      {/* Cota de Comprimento (l) */}
      <group position={[-0.4, baseY + height / 2, 0]}>
        {/* Linha horizontal longitudinal */}
        <mesh position={[0, 0, 0]}>
          <boxGeometry args={[0.015, 0.015, length]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        {/* Traço frontal */}
        <mesh position={[0, 0, halfL]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        {/* Traço traseiro */}
        <mesh position={[0, 0, -halfL]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        {/* Texto do comprimento */}
        <Text
          position={[-0.15, 0, 0]}
          rotation={[0, -Math.PI / 2, 0]}
          fontSize={0.25}
          color="#475569"
          anchorX="center"
          anchorY="middle"
        >
          ℓ = {length}m
        </Text>
      </group>

      {/* Texto Informativo Superior */}
      <Text
        position={[0, topY + 0.6, 0]}
        fontSize={0.4}
        color="#1a202c"
        anchorX="center"
        anchorY="bottom"
      >
        Muro / Placa Isolada | Cf = {cf.toFixed(2)}
      </Text>
    </group>
  );
}



export default function Sign3DViewer({
  length,
  height,
  groundClearance,
  alpha,
  cf,
  forceKN,
  applicationPoint,
}: Sign3DInput) {
  const fallback = (
    <FallbackDiagram
      type="sign"
      props={{ length, height, groundClearance, alpha, cf, forceKN, applicationPoint }}
    />
  );

  const maxDim = Math.max(length, height);

  return (
    <SceneCanvas
      shadows
      gl={{ preserveDrawingBuffer: true, antialias: true }}
      camera={{ position: [length * 1.3, height * 1.5, length * 1.3], fov: 40 }}
      fallback={fallback}
    >
      <ambientLight intensity={0.7} />
      <directionalLight position={[length * 1.5, height * 2.5, length * 1.5]} intensity={1.2} castShadow shadow-mapSize-width={1024} shadow-mapSize-height={1024} />
      <SignModel
        length={length}
        height={height}
        groundClearance={groundClearance}
        alpha={alpha}
        cf={cf}
        forceKN={forceKN}
        applicationPoint={applicationPoint}
      />
      <Grid infiniteGrid fadeDistance={maxDim * 5} sectionColor="#94a3b8" cellColor="#cbd5e1" position={[0, -0.01, 0]} />
      <OrbitControls makeDefault minPolarAngle={0} maxPolarAngle={Math.PI / 2 - 0.05} />
      <Environment preset="city" />
    </SceneCanvas>
  );
}