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 IsolatedRoof3DInput {
  /** Tipo de cobertura: 'shed' (uma água) ou 'gable' (duas águas) */
  type: 'shed' | 'gable';
  /** Inclinação θ (graus) */
  theta: number;
  /** Altura livre dos suportes (m) */
  height: number;
  /** Largura da cobertura (m) — dimensão transversal (b) */
  width: number;
  /** Profundidade da cobertura (m) — dimensão longitudinal (l) */
  depth: number;
  /** Cpe barlavento (sobre a face exposta ao vento) */
  cpeWindward: number;
  /** Cpe sotavento (face oposta) */
  cpeLeeward: number;
  /** Cpe sob a face superior (sucção) */
  cpeTop: number;
  /** Força resultante na cobertura (kN) */
  forceKN: number;
}

function pressureColor(cpe: number): THREE.Color {
  const clamped = Math.max(-2.5, Math.min(1.5, cpe));
  const t = (clamped + 2.5) / 4.0;
  const h = 240 - t * 240; // azul -> vermelho
  return new THREE.Color(`hsl(${h}, 75%, 50%)`);
}

function IsolatedRoofModel({
  type,
  theta,
  height,
  width,
  depth,
  cpeWindward,
  cpeLeeward,
  forceKN,
}: IsolatedRoof3DInput) {
  const thetaRad = (theta * Math.PI) / 180;
  const halfDepth = depth / 2;
  const halfWidth = width / 2;

  const windwardColor = useMemo(() => pressureColor(cpeWindward), [cpeWindward]);
  const leewardColor = useMemo(() => pressureColor(cpeLeeward), [cpeLeeward]);

  const h_diff = depth * Math.tan(thetaRad);
  const h_half = (depth / 2) * Math.tan(thetaRad);

  // Altura média da cobertura no centro geométrico
  const centerY = type === 'shed' ? height + h_diff / 2 : height + h_half / 2;

  // Definição das colunas de suporte (pilares)
  const pillars = useMemo(() => {
    const list: { pos: [number, number, number]; h: number }[] = [];
    if (type === 'shed') {
      list.push(
        { pos: [-halfWidth, height / 2, -halfDepth], h: height },
        { pos: [halfWidth, height / 2, -halfDepth], h: height },
        { pos: [-halfWidth, (height + h_diff) / 2, halfDepth], h: height + h_diff },
        { pos: [halfWidth, (height + h_diff) / 2, halfDepth], h: height + h_diff },
      );
    } else {
      list.push(
        { pos: [-halfWidth, height / 2, -halfDepth], h: height },
        { pos: [halfWidth, height / 2, -halfDepth], h: height },
        { pos: [-halfWidth, height / 2, halfDepth], h: height },
        { pos: [halfWidth, height / 2, halfDepth], h: height },
        { pos: [-halfWidth, (height + h_half) / 2, 0], h: height + h_half },
        { pos: [halfWidth, (height + h_half) / 2, 0], h: height + h_half },
      );
    }
    return list;
  }, [type, depth, width, height, h_diff, h_half, halfDepth, halfWidth]);

  return (
    <group>
      {/* Solo translúcido */}
      <mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.01, 0]} receiveShadow>
        <planeGeometry args={[width * 1.5, depth * 1.5]} />
        <meshStandardMaterial color="#94a3b8" transparent opacity={0.15} />
      </mesh>

      {/* === COBERTURA (PAINÉIS 3D SÓLIDOS) === */}
      {type === 'shed' ? (
        // Uma água (Shed): dividida em metade barlavento e metade sotavento
        <group>
          {/* Metade Barlavento (Z < 0) */}
          <mesh
            position={[0, height + h_diff / 4, -depth / 4]}
            rotation={[-thetaRad, 0, 0]}
            castShadow
            receiveShadow
          >
            <boxGeometry args={[width, 0.08, depth / (2 * Math.cos(thetaRad))]} />
            <meshStandardMaterial color={windwardColor} opacity={0.9} transparent roughness={0.4} />
          </mesh>
          {/* Metade Sotavento (Z > 0) */}
          <mesh
            position={[0, height + (3 * h_diff) / 4, depth / 4]}
            rotation={[-thetaRad, 0, 0]}
            castShadow
            receiveShadow
          >
            <boxGeometry args={[width, 0.08, depth / (2 * Math.cos(thetaRad))]} />
            <meshStandardMaterial color={leewardColor} opacity={0.9} transparent roughness={0.4} />
          </mesh>
        </group>
      ) : (
        // Duas águas (Gable)
        <group>
          {/* Água Esquerda / Barlavento (Z < 0) */}
          <mesh
            position={[0, height + h_half / 2, -depth / 4]}
            rotation={[-thetaRad, 0, 0]}
            castShadow
            receiveShadow
          >
            <boxGeometry args={[width, 0.08, depth / (2 * Math.cos(thetaRad))]} />
            <meshStandardMaterial color={windwardColor} opacity={0.9} transparent roughness={0.4} />
          </mesh>
          {/* Água Direita / Sotavento (Z > 0) */}
          <mesh
            position={[0, height + h_half / 2, depth / 4]}
            rotation={[thetaRad, 0, 0]}
            castShadow
            receiveShadow
          >
            <boxGeometry args={[width, 0.08, depth / (2 * Math.cos(thetaRad))]} />
            <meshStandardMaterial color={leewardColor} opacity={0.9} transparent roughness={0.4} />
          </mesh>
        </group>
      )}

      {/* Pilares de Suporte */}
      {pillars.map((p, i) => (
        <mesh key={`pillar-${i}`} position={p.pos} castShadow>
          <cylinderGeometry args={[0.06, 0.06, p.h, 16]} />
          <meshStandardMaterial color="#475569" roughness={0.5} />
        </mesh>
      ))}

      {/* Vetor de vento (Seta verde/azul batendo no elemento) */}
      <WindArrow
        target={new THREE.Vector3(0, centerY, 0)}
        direction={new THREE.Vector3(0, 0, 1)}
      />

      {/* === LINHAS DE COTA (CAD-Style) === */}
      {/* Cota de Altura (h) */}
      <group position={[-halfDepth - 0.4, 0, -halfDepth]}>
        <mesh position={[0, height / 2, 0]}>
          <boxGeometry args={[0.015, height, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        <mesh position={[0, height, 0]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        <mesh position={[0, 0, 0]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        <Text
          position={[-0.15, height / 2, 0]}
          rotation={[0, -Math.PI / 2, 0]}
          fontSize={0.25}
          color="#475569"
          anchorX="center"
          anchorY="middle"
        >
          h = {height}m
        </Text>
      </group>

      {/* Cota de Profundidade/Span (d) */}
      <group position={[halfDepth + 0.4, height / 2, 0]}>
        <mesh position={[0, 0, 0]}>
          <boxGeometry args={[0.015, 0.015, depth]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        <mesh position={[0, 0, halfDepth]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        <mesh position={[0, 0, -halfDepth]}>
          <boxGeometry args={[0.1, 0.015, 0.015]} />
          <meshStandardMaterial color="#64748b" />
        </mesh>
        <Text
          position={[0.15, 0, 0]}
          rotation={[0, Math.PI / 2, 0]}
          fontSize={0.25}
          color="#475569"
          anchorX="center"
          anchorY="middle"
        >
          d = {depth}m
        </Text>
      </group>

      {/* Rótulo Superior */}
      <Text
        position={[0, centerY + 3, 0]}
        color="#1a202c"
        anchorX="center"
        anchorY="bottom"
      >
        θ={theta}° | F = {forceKN.toFixed(1)} kN
      </Text>
    </group>
  );
}

export default function IsolatedRoof3DViewer({
  type,
  theta,
  height,
  width,
  depth,
  cpeWindward,
  cpeLeeward,
  cpeTop,
  forceKN,
}: IsolatedRoof3DInput) {
  const cameraDistance = Math.max(Math.max(width, depth) * 1.3, height * 1.5, 8);

  const fallback = (
    <FallbackDiagram
      type="isolatedRoof"
      props={{ type, theta, height, width, depth, cpeWindward, cpeLeeward, cpeTop, forceKN }}
    />
  );

  return (
    <SceneCanvas
      shadows
      gl={{ preserveDrawingBuffer: true, antialias: true }}
      camera={{ position: [cameraDistance, cameraDistance * 0.8, cameraDistance], fov: 40 }}
      fallback={fallback}
    >
      <ambientLight intensity={0.7} />
      <directionalLight
        position={[depth * 1.5, height * 3, depth * 1.5]}
        intensity={1.2}
        castShadow
        shadow-mapSize-width={1024}
        shadow-mapSize-height={1024}
      />
      <IsolatedRoofModel
        type={type}
        theta={theta}
        height={height}
        width={width}
        depth={depth}
        cpeWindward={cpeWindward}
        cpeLeeward={cpeLeeward}
        cpeTop={cpeTop}
        forceKN={forceKN}
      />
      <Grid infiniteGrid fadeDistance={cameraDistance * 5} sectionColor="#94a3b8" cellColor="#cbd5e1" position={[0, -0.01, 0]} />
      <OrbitControls makeDefault minPolarAngle={0} maxPolarAngle={Math.PI / 2 - 0.05} />
      <Environment preset="city" />
    </SceneCanvas>
  );
}
